aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2010-06-26 13:27:00 -0400
committerDavid S. Miller <davem@davemloft.net>2010-06-26 13:27:00 -0400
commitc67dda14389205f0a223c5089307495290939b3b (patch)
treefad0bb26b28703d02a22ebdd44d94eabac4a2ade /drivers
parent43bc2db47292a824152145253b1dd2847e7312a3 (diff)
parent7e27d6e778cd87b6f2415515d7127eba53fe5d02 (diff)
Merge branch 'master' of /home/davem/src/GIT/linux-2.6/
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Makefile2
-rw-r--r--drivers/acpi/Kconfig9
-rw-r--r--drivers/acpi/Makefile5
-rw-r--r--drivers/acpi/acpi_pad.c22
-rw-r--r--drivers/acpi/acpica/evxfevnt.c33
-rw-r--r--drivers/acpi/acpica/hwacpi.c20
-rw-r--r--drivers/acpi/apei/Kconfig30
-rw-r--r--drivers/acpi/apei/Makefile5
-rw-r--r--drivers/acpi/apei/apei-base.c593
-rw-r--r--drivers/acpi/apei/apei-internal.h114
-rw-r--r--drivers/acpi/apei/cper.c84
-rw-r--r--drivers/acpi/apei/einj.c548
-rw-r--r--drivers/acpi/apei/erst.c855
-rw-r--r--drivers/acpi/apei/ghes.c427
-rw-r--r--drivers/acpi/apei/hest.c173
-rw-r--r--drivers/acpi/atomicio.c360
-rw-r--r--drivers/acpi/ec.c25
-rw-r--r--drivers/acpi/hed.c112
-rw-r--r--drivers/acpi/hest.c139
-rw-r--r--drivers/acpi/internal.h5
-rw-r--r--drivers/acpi/osl.c9
-rw-r--r--drivers/acpi/pci_root.c67
-rw-r--r--drivers/acpi/processor_driver.c15
-rw-r--r--drivers/acpi/processor_idle.c75
-rw-r--r--drivers/acpi/sleep.c214
-rw-r--r--drivers/acpi/sleep.h2
-rw-r--r--drivers/acpi/tables.c4
-rw-r--r--drivers/acpi/video.c118
-rw-r--r--drivers/acpi/video_detect.c2
-rw-r--r--drivers/ata/Kconfig511
-rw-r--r--drivers/ata/Makefile83
-rw-r--r--drivers/ata/ata_generic.c2
-rw-r--r--drivers/ata/ata_piix.c4
-rw-r--r--drivers/ata/libahci.c21
-rw-r--r--drivers/ata/libata-core.c22
-rw-r--r--drivers/ata/libata-scsi.c29
-rw-r--r--drivers/ata/libata-sff.c416
-rw-r--r--drivers/ata/pata_acpi.c2
-rw-r--r--drivers/ata/pata_ali.c5
-rw-r--r--drivers/ata/pata_amd.c2
-rw-r--r--drivers/ata/pata_artop.c2
-rw-r--r--drivers/ata/pata_atiixp.c4
-rw-r--r--drivers/ata/pata_atp867x.c2
-rw-r--r--drivers/ata/pata_bf54x.c2
-rw-r--r--drivers/ata/pata_cmd64x.c2
-rw-r--r--drivers/ata/pata_cs5520.c2
-rw-r--r--drivers/ata/pata_cs5530.c2
-rw-r--r--drivers/ata/pata_cs5535.c2
-rw-r--r--drivers/ata/pata_cs5536.c2
-rw-r--r--drivers/ata/pata_cypress.c2
-rw-r--r--drivers/ata/pata_efar.c4
-rw-r--r--drivers/ata/pata_hpt366.c2
-rw-r--r--drivers/ata/pata_hpt37x.c2
-rw-r--r--drivers/ata/pata_hpt3x2n.c2
-rw-r--r--drivers/ata/pata_hpt3x3.c2
-rw-r--r--drivers/ata/pata_icside.c2
-rw-r--r--drivers/ata/pata_it8213.c2
-rw-r--r--drivers/ata/pata_it821x.c2
-rw-r--r--drivers/ata/pata_jmicron.c2
-rw-r--r--drivers/ata/pata_macio.c12
-rw-r--r--drivers/ata/pata_marvell.c2
-rw-r--r--drivers/ata/pata_mpc52xx.c2
-rw-r--r--drivers/ata/pata_netcell.c2
-rw-r--r--drivers/ata/pata_ninja32.c2
-rw-r--r--drivers/ata/pata_ns87415.c2
-rw-r--r--drivers/ata/pata_octeon_cf.c18
-rw-r--r--drivers/ata/pata_oldpiix.c2
-rw-r--r--drivers/ata/pata_optidma.c2
-rw-r--r--drivers/ata/pata_pdc2027x.c2
-rw-r--r--drivers/ata/pata_pdc202xx_old.c2
-rw-r--r--drivers/ata/pata_piccolo.c2
-rw-r--r--drivers/ata/pata_radisys.c2
-rw-r--r--drivers/ata/pata_rdc.c4
-rw-r--r--drivers/ata/pata_sc1200.c2
-rw-r--r--drivers/ata/pata_scc.c4
-rw-r--r--drivers/ata/pata_sch.c2
-rw-r--r--drivers/ata/pata_serverworks.c2
-rw-r--r--drivers/ata/pata_sil680.c4
-rw-r--r--drivers/ata/pata_sis.c2
-rw-r--r--drivers/ata/pata_sl82c105.c2
-rw-r--r--drivers/ata/pata_triflex.c2
-rw-r--r--drivers/ata/pata_via.c2
-rw-r--r--drivers/ata/sata_mv.c4
-rw-r--r--drivers/ata/sata_nv.c10
-rw-r--r--drivers/ata/sata_qstor.c16
-rw-r--r--drivers/ata/sata_sil.c4
-rw-r--r--drivers/ata/sata_sil24.c24
-rw-r--r--drivers/ata/sata_sis.c4
-rw-r--r--drivers/ata/sata_svw.c2
-rw-r--r--drivers/ata/sata_uli.c2
-rw-r--r--drivers/ata/sata_via.c35
-rw-r--r--drivers/ata/sata_vsc.c2
-rw-r--r--drivers/base/topology.c2
-rw-r--r--drivers/block/brd.c53
-rw-r--r--drivers/block/cciss_scsi.c2
-rw-r--r--drivers/block/drbd/drbd_int.h14
-rw-r--r--drivers/block/drbd/drbd_main.c68
-rw-r--r--drivers/block/drbd/drbd_receiver.c45
-rw-r--r--drivers/block/drbd/drbd_req.c54
-rw-r--r--drivers/block/drbd/drbd_req.h1
-rw-r--r--drivers/block/drbd/drbd_worker.c24
-rw-r--r--drivers/block/swim3.c6
-rw-r--r--drivers/block/virtio_blk.c4
-rw-r--r--drivers/char/Kconfig8
-rw-r--r--drivers/char/Makefile1
-rw-r--r--drivers/char/agp/amd64-agp.c28
-rw-r--r--drivers/char/agp/intel-gtt.c46
-rw-r--r--drivers/char/agp/uninorth-agp.c2
-rw-r--r--drivers/char/amiserial.c61
-rw-r--r--drivers/char/applicom.c11
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c15
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c468
-rw-r--r--drivers/char/n_gsm.c9
-rw-r--r--drivers/char/ppdev.c4
-rw-r--r--drivers/char/ps3flash.c3
-rw-r--r--drivers/char/ramoops.c162
-rw-r--r--drivers/char/virtio_console.c14
-rw-r--r--drivers/char/vt.c10
-rw-r--r--drivers/char/vt_ioctl.c4
-rw-r--r--drivers/clocksource/sh_cmt.c22
-rw-r--r--drivers/clocksource/sh_tmu.c20
-rw-r--r--drivers/cpuidle/cpuidle.c12
-rw-r--r--drivers/cpuidle/cpuidle.h1
-rw-r--r--drivers/cpuidle/driver.c16
-rw-r--r--drivers/cpuidle/sysfs.c5
-rw-r--r--drivers/crypto/amcc/crypto4xx_core.c6
-rw-r--r--drivers/crypto/n2_core.c123
-rw-r--r--drivers/dma/Kconfig9
-rw-r--r--drivers/dma/Makefile1
-rw-r--r--drivers/dma/mpc512x_dma.c10
-rw-r--r--drivers/dma/pl330.c866
-rw-r--r--drivers/dma/ppc4xx/adma.c4
-rw-r--r--drivers/edac/Kconfig13
-rw-r--r--drivers/edac/Makefile2
-rw-r--r--drivers/edac/edac_core.h23
-rw-r--r--drivers/edac/edac_mc_sysfs.c175
-rw-r--r--drivers/edac/edac_mce.c61
-rw-r--r--drivers/edac/i5000_edac.c20
-rw-r--r--drivers/edac/i5400_edac.c20
-rw-r--r--drivers/edac/i7core_edac.c2078
-rw-r--r--drivers/edac/i82443bxgx_edac.c22
-rw-r--r--drivers/edac/mpc85xx_edac.c12
-rw-r--r--drivers/edac/ppc4xx_edac.c6
-rw-r--r--drivers/firewire/core-card.c46
-rw-r--r--drivers/firewire/core-cdev.c8
-rw-r--r--drivers/firewire/core-transaction.c96
-rw-r--r--drivers/firewire/core.h6
-rw-r--r--drivers/firewire/ohci.c188
-rw-r--r--drivers/firewire/ohci.h10
-rw-r--r--drivers/gpio/Kconfig37
-rw-r--r--drivers/gpio/Makefile5
-rw-r--r--drivers/gpio/cs5535-gpio.c2
-rw-r--r--drivers/gpio/gpiolib.c49
-rw-r--r--drivers/gpio/it8761e_gpio.c5
-rw-r--r--drivers/gpio/janz-ttl.c258
-rw-r--r--drivers/gpio/langwell_gpio.c83
-rw-r--r--drivers/gpio/max732x.c368
-rw-r--r--drivers/gpio/pca953x.c2
-rw-r--r--drivers/gpio/pl061.c2
-rw-r--r--drivers/gpio/rdc321x-gpio.c246
-rw-r--r--drivers/gpio/tc35892-gpio.c381
-rw-r--r--drivers/gpu/drm/drm_crtc.c4
-rw-r--r--drivers/gpu/drm/drm_crtc_helper.c28
-rw-r--r--drivers/gpu/drm/drm_edid.c5
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c2
-rw-r--r--drivers/gpu/drm/i915/Makefile1
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c82
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c734
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c70
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h210
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c897
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c182
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h82
-rw-r--r--drivers/gpu/drm/i915/i915_trace.h24
-rw-r--r--drivers/gpu/drm/i915/intel_bios.c10
-rw-r--r--drivers/gpu/drm/i915/intel_crt.c23
-rw-r--r--drivers/gpu/drm/i915/intel_display.c304
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c11
-rw-r--r--drivers/gpu/drm/i915/intel_fb.c16
-rw-r--r--drivers/gpu/drm/i915/intel_hdmi.c5
-rw-r--r--drivers/gpu/drm/i915/intel_overlay.c52
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c849
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.h124
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_acpi.c71
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bios.c96
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.c37
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_crtc.h2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.c29
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.h5
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fbcon.c8
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_mem.c3
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_state.c25
-rw-r--r--drivers/gpu/drm/nouveau/nv04_cursor.c1
-rw-r--r--drivers/gpu/drm/nouveau/nv40_graph.c8
-rw-r--r--drivers/gpu/drm/nouveau/nv50_cursor.c1
-rw-r--r--drivers/gpu/drm/nouveau/nv50_fb.c10
-rw-r--r--drivers/gpu/drm/nouveau/nv50_gpio.c2
-rw-r--r--drivers/gpu/drm/nouveau/nv50_sor.c7
-rw-r--r--drivers/gpu/drm/radeon/Makefile7
-rw-r--r--drivers/gpu/drm/radeon/atombios_crtc.c1
-rw-r--r--drivers/gpu/drm/radeon/evergreen.c15
-rw-r--r--drivers/gpu/drm/radeon/evergreen_cs.c1356
-rw-r--r--drivers/gpu/drm/radeon/evergreen_reg.h3
-rw-r--r--drivers/gpu/drm/radeon/evergreend.h464
-rw-r--r--drivers/gpu/drm/radeon/r100.c10
-rw-r--r--drivers/gpu/drm/radeon/r420.c12
-rw-r--r--drivers/gpu/drm/radeon/r600.c105
-rw-r--r--drivers/gpu/drm/radeon/radeon.h14
-rw-r--r--drivers/gpu/drm/radeon/radeon_agp.c5
-rw-r--r--drivers/gpu/drm/radeon/radeon_asic.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_asic.h1
-rw-r--r--drivers/gpu/drm/radeon/radeon_atombios.c89
-rw-r--r--drivers/gpu/drm/radeon/radeon_combios.c9
-rw-r--r--drivers/gpu/drm/radeon/radeon_device.c11
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c3
-rw-r--r--drivers/gpu/drm/radeon/radeon_drv.c3
-rw-r--r--drivers/gpu/drm/radeon/radeon_fb.c12
-rw-r--r--drivers/gpu/drm/radeon/radeon_kms.c9
-rw-r--r--drivers/gpu/drm/radeon/radeon_legacy_encoders.c11
-rw-r--r--drivers/gpu/drm/radeon/radeon_pm.c170
-rw-r--r--drivers/gpu/drm/radeon/radeon_state.c5
-rw-r--r--drivers/gpu/drm/radeon/reg_srcs/evergreen611
-rw-r--r--drivers/gpu/drm/radeon/rs600.c3
-rw-r--r--drivers/gpu/drm/radeon/rv770.c13
-rw-r--r--drivers/gpu/drm/ttm/ttm_page_alloc.c64
-rw-r--r--drivers/gpu/drm/vmwgfx/Makefile2
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.c24
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.h49
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c10
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_fb.c87
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_fence.c173
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c23
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_irq.c17
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c203
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.h4
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c189
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c2
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_resource.c8
-rw-r--r--drivers/gpu/vga/vgaarb.c61
-rw-r--r--drivers/hid/Kconfig8
-rw-r--r--drivers/hid/Makefile1
-rw-r--r--drivers/hid/hid-core.c1
-rw-r--r--drivers/hid/hid-debug.c2
-rw-r--r--drivers/hid/hid-gyration.c1
-rw-r--r--drivers/hid/hid-ids.h1
-rw-r--r--drivers/hid/hid-roccat-kone.c73
-rw-r--r--drivers/hid/hid-roccat-kone.h9
-rw-r--r--drivers/hid/hid-roccat.c428
-rw-r--r--drivers/hid/hid-roccat.h31
-rw-r--r--drivers/hwmon/Kconfig34
-rw-r--r--drivers/hwmon/Makefile2
-rw-r--r--drivers/hwmon/adm1031.c68
-rw-r--r--drivers/hwmon/adt7411.c2
-rw-r--r--drivers/hwmon/applesmc.c186
-rw-r--r--drivers/hwmon/asc7621.c2
-rw-r--r--drivers/hwmon/asus_atk0110.c7
-rw-r--r--drivers/hwmon/dme1737.c328
-rw-r--r--drivers/hwmon/emc1403.c344
-rw-r--r--drivers/hwmon/f71882fg.c170
-rw-r--r--drivers/hwmon/f75375s.c2
-rw-r--r--drivers/hwmon/g760a.c2
-rw-r--r--drivers/hwmon/lm63.c16
-rw-r--r--drivers/hwmon/lm73.c1
-rw-r--r--drivers/hwmon/lm75.c4
-rw-r--r--drivers/hwmon/lm90.c3
-rw-r--r--drivers/hwmon/lm95241.c1
-rw-r--r--drivers/hwmon/ltc4245.c18
-rw-r--r--drivers/hwmon/tmp102.c319
-rw-r--r--drivers/hwmon/tmp401.c255
-rw-r--r--drivers/hwmon/tmp421.c2
-rw-r--r--drivers/hwmon/w83781d.c2
-rw-r--r--drivers/i2c/busses/Kconfig40
-rw-r--r--drivers/i2c/busses/Makefile6
-rw-r--r--drivers/i2c/i2c-core.c179
-rw-r--r--drivers/i2c/i2c-smbus.c1
-rw-r--r--drivers/ide/gayle.c147
-rw-r--r--drivers/ide/pmac.c7
-rw-r--r--drivers/idle/Kconfig11
-rw-r--r--drivers/idle/Makefile1
-rwxr-xr-xdrivers/idle/intel_idle.c461
-rw-r--r--drivers/ieee1394/dv1394.c11
-rw-r--r--drivers/ieee1394/raw1394.c3
-rw-r--r--drivers/ieee1394/video1394.c5
-rw-r--r--drivers/infiniband/core/ucm.c11
-rw-r--r--drivers/infiniband/hw/ehca/ehca_irq.c2
-rw-r--r--drivers/infiniband/hw/qib/qib_fs.c29
-rw-r--r--drivers/infiniband/hw/qib/qib_iba6120.c12
-rw-r--r--drivers/infiniband/hw/qib/qib_iba7322.c771
-rw-r--r--drivers/infiniband/hw/qib/qib_init.c6
-rw-r--r--drivers/input/joydev.c10
-rw-r--r--drivers/input/keyboard/adp5588-keys.c1
-rw-r--r--drivers/input/keyboard/amikbd.c97
-rw-r--r--drivers/input/keyboard/lm8323.c2
-rw-r--r--drivers/input/keyboard/max7359_keypad.c1
-rw-r--r--drivers/input/keyboard/qt2160.c1
-rw-r--r--drivers/input/keyboard/tca6416-keypad.c2
-rw-r--r--drivers/input/misc/Kconfig10
-rw-r--r--drivers/input/misc/Makefile1
-rw-r--r--drivers/input/misc/ad714x-i2c.c1
-rw-r--r--drivers/input/misc/hp_sdc_rtc.c2
-rw-r--r--drivers/input/misc/max8925_onkey.c148
-rw-r--r--drivers/input/misc/pcf8574_keypad.c2
-rw-r--r--drivers/input/misc/twl4030-vibra.c2
-rw-r--r--drivers/input/misc/uinput.c4
-rw-r--r--drivers/input/mouse/amimouse.c98
-rw-r--r--drivers/input/mouse/synaptics_i2c.c1
-rw-r--r--drivers/input/serio/Kconfig3
-rw-r--r--drivers/input/tablet/wacom_sys.c1
-rw-r--r--drivers/input/tablet/wacom_wac.c73
-rw-r--r--drivers/input/tablet/wacom_wac.h1
-rw-r--r--drivers/input/touchscreen/Kconfig15
-rw-r--r--drivers/input/touchscreen/Makefile1
-rw-r--r--drivers/input/touchscreen/ad7879.c5
-rw-r--r--drivers/input/touchscreen/ads7846.c4
-rw-r--r--drivers/input/touchscreen/eeti_ts.c2
-rw-r--r--drivers/input/touchscreen/mcs5000_ts.c1
-rw-r--r--drivers/input/touchscreen/s3c2410_ts.c4
-rw-r--r--drivers/input/touchscreen/tps6507x-ts.c396
-rw-r--r--drivers/input/touchscreen/tsc2007.c2
-rw-r--r--drivers/input/touchscreen/usbtouchscreen.c7
-rw-r--r--drivers/isdn/capi/kcapi.c6
-rw-r--r--drivers/isdn/hardware/mISDN/hfcsusb.c4
-rw-r--r--drivers/isdn/hardware/mISDN/netjet.c4
-rw-r--r--drivers/isdn/mISDN/timerdev.c2
-rw-r--r--drivers/leds/Kconfig19
-rw-r--r--drivers/leds/Makefile2
-rw-r--r--drivers/leds/led-class.c2
-rw-r--r--drivers/leds/leds-88pm860x.c11
-rw-r--r--drivers/leds/leds-bd2802.c2
-rw-r--r--drivers/leds/leds-gpio.c30
-rw-r--r--drivers/leds/leds-lp3944.c10
-rw-r--r--drivers/leds/leds-mc13783.c403
-rw-r--r--drivers/leds/leds-net5501.c94
-rw-r--r--drivers/leds/leds-pca9532.c5
-rw-r--r--drivers/leds/leds-pca955x.c2
-rw-r--r--drivers/leds/leds-ss4200.c2
-rw-r--r--drivers/macintosh/macio_asic.c8
-rw-r--r--drivers/macintosh/mediabay.c6
-rw-r--r--drivers/macintosh/rack-meter.c8
-rw-r--r--drivers/macintosh/therm_adt746x.c2
-rw-r--r--drivers/macintosh/windfarm_lm75_sensor.c5
-rw-r--r--drivers/macintosh/windfarm_max6690_sensor.c1
-rw-r--r--drivers/macintosh/windfarm_smu_sat.c1
-rw-r--r--drivers/md/raid5.c2
-rw-r--r--drivers/media/IR/Kconfig2
-rw-r--r--drivers/media/IR/imon.c75
-rw-r--r--drivers/media/IR/ir-keytable.c17
-rw-r--r--drivers/media/IR/ir-sysfs.c7
-rw-r--r--drivers/media/IR/keymaps/Makefile3
-rw-r--r--drivers/media/IR/keymaps/rc-avermedia-m135a-rm-jx.c90
-rw-r--r--drivers/media/IR/keymaps/rc-avermedia-m135a.c147
-rw-r--r--drivers/media/IR/keymaps/rc-avermedia-m733a-rm-k6.c95
-rw-r--r--drivers/media/dvb/dm1105/dm1105.c2
-rw-r--r--drivers/media/dvb/dvb-core/dvb_net.c12
-rw-r--r--drivers/media/dvb/dvb-usb/Kconfig4
-rw-r--r--drivers/media/dvb/dvb-usb/cxusb.c4
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-ids.h1
-rw-r--r--drivers/media/dvb/dvb-usb/ttusb2.c95
-rw-r--r--drivers/media/dvb/firewire/firedtv-1394.c2
-rw-r--r--drivers/media/dvb/frontends/au8522_decoder.c26
-rw-r--r--drivers/media/dvb/frontends/ds3000.c5
-rw-r--r--drivers/media/dvb/frontends/stv6110x.c5
-rw-r--r--drivers/media/dvb/ngene/ngene-cards.c15
-rw-r--r--drivers/media/dvb/ngene/ngene-core.c80
-rw-r--r--drivers/media/dvb/ngene/ngene-dvb.c15
-rw-r--r--drivers/media/dvb/ngene/ngene-i2c.c1
-rw-r--r--drivers/media/dvb/ngene/ngene.h3
-rw-r--r--drivers/media/dvb/ttpci/Kconfig5
-rw-r--r--drivers/media/dvb/ttpci/budget-ci.c1
-rw-r--r--drivers/media/radio/si470x/radio-si470x-i2c.c1
-rw-r--r--drivers/media/video/Kconfig4
-rw-r--r--drivers/media/video/ak881x.c3
-rw-r--r--drivers/media/video/bw-qcam.c759
-rw-r--r--drivers/media/video/bw-qcam.h69
-rw-r--r--drivers/media/video/c-qcam.c634
-rw-r--r--drivers/media/video/cx18/cx18-alsa-main.c2
-rw-r--r--drivers/media/video/cx18/cx18-alsa-mixer.c2
-rw-r--r--drivers/media/video/cx18/cx18-alsa-mixer.h2
-rw-r--r--drivers/media/video/cx18/cx18-alsa-pcm.c2
-rw-r--r--drivers/media/video/cx18/cx18-alsa-pcm.h2
-rw-r--r--drivers/media/video/cx18/cx18-alsa.h2
-rw-r--r--drivers/media/video/cx18/cx18-av-audio.c2
-rw-r--r--drivers/media/video/cx18/cx18-av-core.c127
-rw-r--r--drivers/media/video/cx18/cx18-av-core.h2
-rw-r--r--drivers/media/video/cx18/cx18-av-firmware.c2
-rw-r--r--drivers/media/video/cx18/cx18-cards.c2
-rw-r--r--drivers/media/video/cx18/cx18-cards.h2
-rw-r--r--drivers/media/video/cx18/cx18-controls.c11
-rw-r--r--drivers/media/video/cx18/cx18-driver.c2
-rw-r--r--drivers/media/video/cx18/cx18-driver.h2
-rw-r--r--drivers/media/video/cx18/cx18-dvb.c2
-rw-r--r--drivers/media/video/cx18/cx18-fileops.c2
-rw-r--r--drivers/media/video/cx18/cx18-firmware.c2
-rw-r--r--drivers/media/video/cx18/cx18-gpio.c2
-rw-r--r--drivers/media/video/cx18/cx18-gpio.h2
-rw-r--r--drivers/media/video/cx18/cx18-i2c.c2
-rw-r--r--drivers/media/video/cx18/cx18-io.c2
-rw-r--r--drivers/media/video/cx18/cx18-io.h4
-rw-r--r--drivers/media/video/cx18/cx18-ioctl.c10
-rw-r--r--drivers/media/video/cx18/cx18-ioctl.h2
-rw-r--r--drivers/media/video/cx18/cx18-irq.c2
-rw-r--r--drivers/media/video/cx18/cx18-irq.h2
-rw-r--r--drivers/media/video/cx18/cx18-mailbox.c2
-rw-r--r--drivers/media/video/cx18/cx18-mailbox.h2
-rw-r--r--drivers/media/video/cx18/cx18-queue.c2
-rw-r--r--drivers/media/video/cx18/cx18-queue.h2
-rw-r--r--drivers/media/video/cx18/cx18-scb.c2
-rw-r--r--drivers/media/video/cx18/cx18-scb.h2
-rw-r--r--drivers/media/video/cx18/cx18-streams.c2
-rw-r--r--drivers/media/video/cx18/cx18-streams.h2
-rw-r--r--drivers/media/video/cx231xx/cx231xx-video.c5
-rw-r--r--drivers/media/video/cx2341x.c6
-rw-r--r--drivers/media/video/cx23885/cx23885-dvb.c2
-rw-r--r--drivers/media/video/cx23885/cx23885-i2c.c12
-rw-r--r--drivers/media/video/cx23885/cx23885-input.c2
-rw-r--r--drivers/media/video/cx23885/cx23885-input.h2
-rw-r--r--drivers/media/video/cx23885/cx23885-ioctl.c2
-rw-r--r--drivers/media/video/cx23885/cx23885-ioctl.h2
-rw-r--r--drivers/media/video/cx23885/cx23885-ir.c2
-rw-r--r--drivers/media/video/cx23885/cx23885-ir.h2
-rw-r--r--drivers/media/video/cx23885/cx23885-video.c5
-rw-r--r--drivers/media/video/cx23885/cx23888-ir.c2
-rw-r--r--drivers/media/video/cx23885/cx23888-ir.h2
-rw-r--r--drivers/media/video/cx25840/cx25840-core.c99
-rw-r--r--drivers/media/video/cx88/cx88-i2c.c16
-rw-r--r--drivers/media/video/em28xx/em28xx-core.c7
-rw-r--r--drivers/media/video/gspca/sonixb.c2
-rw-r--r--drivers/media/video/gspca/sonixj.c5
-rw-r--r--drivers/media/video/hdpvr/hdpvr-video.c2
-rw-r--r--drivers/media/video/ivtv/ivtv-controls.c10
-rw-r--r--drivers/media/video/ivtv/ivtv-fileops.c11
-rw-r--r--drivers/media/video/ivtv/ivtv-ioctl.c6
-rw-r--r--drivers/media/video/ivtv/ivtv-streams.c23
-rw-r--r--drivers/media/video/ivtv/ivtvfb.c14
-rw-r--r--drivers/media/video/mt9m001.c6
-rw-r--r--drivers/media/video/mt9m111.c6
-rw-r--r--drivers/media/video/mt9t031.c4
-rw-r--r--drivers/media/video/mt9t112.c6
-rw-r--r--drivers/media/video/mt9v011.c37
-rw-r--r--drivers/media/video/mt9v022.c6
-rw-r--r--drivers/media/video/mx3_camera.c4
-rw-r--r--drivers/media/video/omap/omap_vout.c3
-rw-r--r--drivers/media/video/ov772x.c6
-rw-r--r--drivers/media/video/ov9640.c6
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-devattr.c1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-devattr.h5
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw.c37
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-main.c4
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-sysfs.c13
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-v4l2.c15
-rw-r--r--drivers/media/video/pxa_camera.c4
-rw-r--r--drivers/media/video/rj54n1cb0c.c6
-rw-r--r--drivers/media/video/saa7115.c19
-rw-r--r--drivers/media/video/saa7127.c8
-rw-r--r--drivers/media/video/saa7134/saa6752hs.c46
-rw-r--r--drivers/media/video/saa7134/saa7134-cards.c55
-rw-r--r--drivers/media/video/saa7134/saa7134-empress.c9
-rw-r--r--drivers/media/video/saa7134/saa7134-input.c18
-rw-r--r--drivers/media/video/saa7134/saa7134.h1
-rw-r--r--drivers/media/video/saa717x.c38
-rw-r--r--drivers/media/video/sh_mobile_ceu_camera.c4
-rw-r--r--drivers/media/video/sn9c102/sn9c102_devtable.h2
-rw-r--r--drivers/media/video/soc_camera.c3
-rw-r--r--drivers/media/video/soc_camera_platform.c2
-rw-r--r--drivers/media/video/tcm825x.c8
-rw-r--r--drivers/media/video/tvp514x.c223
-rw-r--r--drivers/media/video/tvp5150.c20
-rw-r--r--drivers/media/video/tw9910.c4
-rw-r--r--drivers/media/video/usbvision/usbvision-video.c3
-rw-r--r--drivers/message/i2o/i2o_config.c11
-rw-r--r--drivers/mfd/88pm860x-core.c6
-rw-r--r--drivers/mfd/88pm860x-i2c.c2
-rw-r--r--drivers/mfd/Kconfig87
-rw-r--r--drivers/mfd/Makefile13
-rw-r--r--drivers/mfd/ab3100-core.c97
-rw-r--r--drivers/mfd/ab3100-otp.c13
-rw-r--r--drivers/mfd/ab3550-core.c1400
-rw-r--r--drivers/mfd/ab4500-core.c209
-rw-r--r--drivers/mfd/ab8500-core.c444
-rw-r--r--drivers/mfd/ab8500-spi.c133
-rw-r--r--drivers/mfd/abx500-core.c157
-rw-r--r--drivers/mfd/adp5520.c2
-rw-r--r--drivers/mfd/da903x.c1
-rw-r--r--drivers/mfd/janz-cmodio.c304
-rw-r--r--drivers/mfd/max8925-core.c7
-rw-r--r--drivers/mfd/max8925-i2c.c3
-rw-r--r--drivers/mfd/mc13783-core.c4
-rw-r--r--drivers/mfd/menelaus.c1
-rw-r--r--drivers/mfd/mfd-core.c2
-rw-r--r--drivers/mfd/pcf50633-adc.c39
-rw-r--r--drivers/mfd/pcf50633-core.c348
-rw-r--r--drivers/mfd/pcf50633-irq.c318
-rw-r--r--drivers/mfd/rdc321x-southbridge.c123
-rw-r--r--drivers/mfd/t7l66xb.c3
-rw-r--r--drivers/mfd/tc35892.c345
-rw-r--r--drivers/mfd/timberdale.c156
-rw-r--r--drivers/mfd/timberdale.h16
-rw-r--r--drivers/mfd/tps65010.c1
-rw-r--r--drivers/mfd/tps6507x.c159
-rw-r--r--drivers/mfd/twl4030-irq.c11
-rw-r--r--drivers/mfd/wm831x-core.c112
-rw-r--r--drivers/mfd/wm831x-irq.c18
-rw-r--r--drivers/mfd/wm8350-i2c.c4
-rw-r--r--drivers/mfd/wm8400-core.c6
-rw-r--r--drivers/misc/eeprom/at24.c1
-rw-r--r--drivers/misc/lkdtm.c20
-rw-r--r--drivers/misc/vmware_balloon.c18
-rw-r--r--drivers/mmc/core/core.c3
-rw-r--r--drivers/mmc/core/sd_ops.c2
-rw-r--r--drivers/mmc/core/sdio_io.c30
-rw-r--r--drivers/mmc/host/Kconfig22
-rw-r--r--drivers/mmc/host/Makefile2
-rw-r--r--drivers/mmc/host/at91_mci.c2
-rw-r--r--drivers/mmc/host/atmel-mci.c64
-rw-r--r--drivers/mmc/host/au1xmmc.c2
-rw-r--r--drivers/mmc/host/bfin_sdh.c2
-rw-r--r--drivers/mmc/host/cb710-mmc.c2
-rw-r--r--drivers/mmc/host/davinci_mmc.c111
-rw-r--r--drivers/mmc/host/imxmmc.c2
-rw-r--r--drivers/mmc/host/mmci.c2
-rw-r--r--drivers/mmc/host/msm_sdcc.c2
-rw-r--r--drivers/mmc/host/mvsdio.c2
-rw-r--r--drivers/mmc/host/mxcmmc.c2
-rw-r--r--drivers/mmc/host/omap.c65
-rw-r--r--drivers/mmc/host/omap_hsmmc.c279
-rw-r--r--drivers/mmc/host/pxamci.c2
-rw-r--r--drivers/mmc/host/s3cmci.c3
-rw-r--r--drivers/mmc/host/sdhci-of-core.c2
-rw-r--r--drivers/mmc/host/sdhci-of-esdhc.c12
-rw-r--r--drivers/mmc/host/sdhci-of-hlwd.c12
-rw-r--r--drivers/mmc/host/sdhci-pci.c2
-rw-r--r--drivers/mmc/host/sdhci-pltfm.c26
-rw-r--r--drivers/mmc/host/sdhci-s3c.c10
-rw-r--r--drivers/mmc/host/sdhci-spear.c298
-rw-r--r--drivers/mmc/host/sdhci.c25
-rw-r--r--drivers/mmc/host/sdhci.h42
-rw-r--r--drivers/mmc/host/sdricoh_cs.c2
-rw-r--r--drivers/mmc/host/sh_mmcif.c940
-rw-r--r--drivers/mmc/host/tifm_sd.c2
-rw-r--r--drivers/mmc/host/tmio_mmc.c2
-rw-r--r--drivers/mmc/host/via-sdmmc.c2
-rw-r--r--drivers/mmc/host/wbsd.c2
-rw-r--r--drivers/mtd/maps/pismo.c2
-rw-r--r--drivers/mtd/mtdchar.c11
-rw-r--r--drivers/mtd/nand/Kconfig21
-rw-r--r--drivers/mtd/nand/fsl_upm.c17
-rw-r--r--drivers/mtd/nand/mpc5121_nfc.c8
-rw-r--r--drivers/mtd/nand/r852.c27
-rw-r--r--drivers/mtd/nand/socrates_nand.c4
-rw-r--r--drivers/mtd/ubi/cdev.c3
-rw-r--r--drivers/net/3c507.c3
-rw-r--r--drivers/net/8139cp.c2
-rw-r--r--drivers/net/8139too.c3
-rw-r--r--drivers/net/benet/be_cmds.c15
-rw-r--r--drivers/net/benet/be_main.c2
-rw-r--r--drivers/net/bmac.c7
-rw-r--r--drivers/net/bnx2.c14
-rw-r--r--drivers/net/can/Kconfig10
-rw-r--r--drivers/net/can/Makefile1
-rw-r--r--drivers/net/can/janz-ican3.c1830
-rw-r--r--drivers/net/can/mscan/mpc5xxx_can.c10
-rw-r--r--drivers/net/cnic.c10
-rw-r--r--drivers/net/cnic_if.h4
-rw-r--r--drivers/net/e1000e/netdev.c2
-rw-r--r--drivers/net/enic/enic.h7
-rw-r--r--drivers/net/enic/enic_main.c200
-rw-r--r--drivers/net/epic100.c7
-rw-r--r--drivers/net/fec.c44
-rw-r--r--drivers/net/fs_enet/mac-fcc.c49
-rw-r--r--drivers/net/fs_enet/mii-bitbang.c4
-rw-r--r--drivers/net/gianfar.c3
-rw-r--r--drivers/net/greth.c11
-rw-r--r--drivers/net/hamradio/yam.c3
-rw-r--r--drivers/net/ixgbe/ixgbe_common.c2
-rw-r--r--drivers/net/ixgbe/ixgbe_main.c2
-rw-r--r--drivers/net/ixgbe/ixgbe_type.h1
-rw-r--r--drivers/net/korina.c32
-rw-r--r--drivers/net/ksz884x.c3
-rw-r--r--drivers/net/ll_temac.h5
-rw-r--r--drivers/net/ll_temac_main.c84
-rw-r--r--drivers/net/mace.c7
-rw-r--r--drivers/net/pcmcia/smc91c92_cs.c1
-rw-r--r--drivers/net/phy/lxt.c51
-rw-r--r--drivers/net/ppp_generic.c2
-rw-r--r--drivers/net/r8169.c11
-rw-r--r--drivers/net/sfc/net_driver.h2
-rw-r--r--drivers/net/sfc/siena.c4
-rw-r--r--drivers/net/tehuti.c4
-rw-r--r--drivers/net/usb/asix.c2
-rw-r--r--drivers/net/virtio_net.c8
-rw-r--r--drivers/net/wan/x25_asy.c2
-rw-r--r--drivers/net/wimax/i2400m/fw.c2
-rw-r--r--drivers/net/wireless/ath/ar9170/usb.c14
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c29
-rw-r--r--drivers/net/wireless/ath/ath5k/phy.c7
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c6
-rw-r--r--drivers/net/wireless/hostap/hostap_hw.c9
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-lib.c30
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-tx.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c318
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c39
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c56
-rw-r--r--drivers/net/wireless/libertas/rx.c5
-rw-r--r--drivers/net/wireless/orinoco/airport.c7
-rw-r--r--drivers/net/wireless/p54/p54usb.c1
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c2
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_sdio.c1
-rw-r--r--drivers/parport/parport_amiga.c64
-rw-r--r--drivers/pci/hotplug/cpqphp_core.c7
-rw-r--r--drivers/pci/pci-sysfs.c37
-rw-r--r--drivers/pci/pcie/aer/aerdrv.h17
-rw-r--r--drivers/pci/pcie/aer/aerdrv_acpi.c77
-rw-r--r--drivers/pci/pcie/aer/aerdrv_core.c8
-rw-r--r--drivers/pci/probe.c8
-rw-r--r--drivers/pci/quirks.c5
-rw-r--r--drivers/pci/setup-res.c10
-rw-r--r--drivers/pci/slot.c48
-rw-r--r--drivers/pcmcia/ds.c1
-rw-r--r--drivers/pcmcia/m8xx_pcmcia.c4
-rw-r--r--drivers/pcmcia/yenta_socket.c19
-rw-r--r--drivers/platform/x86/intel_scu_ipc.c2
-rw-r--r--drivers/power/max17040_battery.c2
-rw-r--r--drivers/rapidio/Kconfig24
-rw-r--r--drivers/rapidio/Makefile4
-rw-r--r--drivers/rapidio/rio-scan.c424
-rw-r--r--drivers/rapidio/rio.c433
-rw-r--r--drivers/rapidio/rio.h44
-rw-r--r--drivers/rapidio/switches/Kconfig28
-rw-r--r--drivers/rapidio/switches/Makefile9
-rw-r--r--drivers/rapidio/switches/idtcps.c137
-rw-r--r--drivers/rapidio/switches/tsi500.c20
-rw-r--r--drivers/rapidio/switches/tsi568.c146
-rw-r--r--drivers/rapidio/switches/tsi57x.c315
-rw-r--r--drivers/regulator/ab3100.c35
-rw-r--r--drivers/regulator/lp3971.c2
-rw-r--r--drivers/regulator/max1586.c1
-rw-r--r--drivers/regulator/max8649.c2
-rw-r--r--drivers/regulator/max8660.c1
-rw-r--r--drivers/regulator/tps65023-regulator.c3
-rw-r--r--drivers/regulator/tps6507x-regulator.c373
-rw-r--r--drivers/rtc/Kconfig7
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/rtc-ab3100.c41
-rw-r--r--drivers/rtc/rtc-ab8500.c363
-rw-r--r--drivers/rtc/rtc-ds1374.c2
-rw-r--r--drivers/rtc/rtc-m41t80.c6
-rw-r--r--drivers/rtc/rtc-mpc5121.c14
-rw-r--r--drivers/rtc/rtc-rx8025.c2
-rw-r--r--drivers/rtc/rtc-s35390a.c2
-rw-r--r--drivers/rtc/rtc-s3c.c9
-rw-r--r--drivers/s390/block/dasd.c23
-rw-r--r--drivers/s390/block/dasd_eckd.c1
-rw-r--r--drivers/s390/block/dasd_int.h1
-rw-r--r--drivers/s390/cio/ccwgroup.c7
-rw-r--r--drivers/s390/cio/ccwreq.c15
-rw-r--r--drivers/s390/cio/ioasm.h15
-rw-r--r--drivers/s390/cio/itcw.c2
-rw-r--r--drivers/scsi/a2091.c245
-rw-r--r--drivers/scsi/a2091.h4
-rw-r--r--drivers/scsi/a3000.c256
-rw-r--r--drivers/scsi/a3000.h4
-rw-r--r--drivers/scsi/a4000t.c101
-rw-r--r--drivers/scsi/aacraid/commctrl.c4
-rw-r--r--drivers/scsi/arcmsr/arcmsr.h29
-rw-r--r--drivers/scsi/arcmsr/arcmsr_attr.c3
-rw-r--r--drivers/scsi/arcmsr/arcmsr_hba.c684
-rw-r--r--drivers/scsi/be2iscsi/be_mgmt.c5
-rw-r--r--drivers/scsi/bfa/bfa_core.c22
-rw-r--r--drivers/scsi/gvp11.c541
-rw-r--r--drivers/scsi/gvp11.h11
-rw-r--r--drivers/scsi/ipr.c221
-rw-r--r--drivers/scsi/ipr.h31
-rw-r--r--drivers/scsi/iscsi_tcp.c6
-rw-r--r--drivers/scsi/mac53c94.c7
-rw-r--r--drivers/scsi/mesh.c7
-rw-r--r--drivers/scsi/mvme147.c33
-rw-r--r--drivers/scsi/osst.c9
-rw-r--r--drivers/scsi/scsi_scan.c9
-rw-r--r--drivers/scsi/sd.c22
-rw-r--r--drivers/scsi/st.c1
-rw-r--r--drivers/serial/8250_pci.c71
-rw-r--r--drivers/serial/altera_uart.c44
-rw-r--r--drivers/serial/bfin_5xx.c9
-rw-r--r--drivers/serial/msm_serial.c21
-rw-r--r--drivers/serial/msm_serial.h56
-rw-r--r--drivers/serial/pmac_zilog.c7
-rw-r--r--drivers/serial/s5pv210.c8
-rw-r--r--drivers/serial/serial_cs.c18
-rw-r--r--drivers/sfi/sfi_acpi.c41
-rw-r--r--drivers/sfi/sfi_core.c107
-rw-r--r--drivers/sfi/sfi_core.h8
-rw-r--r--drivers/sh/intc.c12
-rw-r--r--drivers/spi/mpc512x_psc_spi.c12
-rw-r--r--drivers/spi/spi_ppc4xx.c2
-rw-r--r--drivers/ssb/pci.c9
-rw-r--r--drivers/ssb/sprom.c1
-rw-r--r--drivers/staging/Kconfig6
-rw-r--r--drivers/staging/Makefile3
-rw-r--r--drivers/staging/adis16255/Kconfig2
-rw-r--r--drivers/staging/adis16255/adis16255.c4
-rw-r--r--drivers/staging/batman-adv/device.c2
-rw-r--r--drivers/staging/batman-adv/main.c5
-rw-r--r--drivers/staging/batman-adv/send.c24
-rw-r--r--drivers/staging/comedi/Kconfig81
-rw-r--r--drivers/staging/comedi/comedi_fops.c44
-rw-r--r--drivers/staging/comedi/drivers/Makefile4
-rw-r--r--drivers/staging/comedi/drivers/addi-data/addi_common.c14
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_035.c2
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_1032.c2
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_1500.c2
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_1516.c2
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_1564.c2
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_16xx.c2
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_1710.c2
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_2016.c2
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_2032.c2
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_2200.c2
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_3001.c2
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_3120.c2
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_3200.c2
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_3300.c2
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_3501.c2
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_3xxx.c2
-rw-r--r--drivers/staging/comedi/drivers/adv_pci_dio.c180
-rw-r--r--drivers/staging/comedi/drivers/amplc_dio200.c35
-rw-r--r--drivers/staging/comedi/drivers/ni_mio_cs.c2
-rw-r--r--drivers/staging/comedi/drivers/usbdux.c3
-rw-r--r--drivers/staging/dream/synaptics_i2c_rmi.c2
-rw-r--r--drivers/staging/dt3155/allocator.c4
-rw-r--r--drivers/staging/go7007/saa7134-go7007.c8
-rw-r--r--drivers/staging/go7007/wis-saa7113.c2
-rw-r--r--drivers/staging/go7007/wis-saa7115.c2
-rw-r--r--drivers/staging/go7007/wis-sony-tuner.c1
-rw-r--r--drivers/staging/go7007/wis-tw2804.c1
-rw-r--r--drivers/staging/go7007/wis-tw9903.c2
-rw-r--r--drivers/staging/iio/Documentation/iio_utils.h3
-rw-r--r--drivers/staging/iio/adc/max1363_core.c2
-rw-r--r--drivers/staging/iio/light/tsl2563.c2
-rw-r--r--drivers/staging/iio/ring_sw.c2
-rw-r--r--drivers/staging/mrst-touchscreen/Kconfig7
-rw-r--r--drivers/staging/mrst-touchscreen/Makefile3
-rw-r--r--drivers/staging/mrst-touchscreen/TODO2
-rw-r--r--drivers/staging/mrst-touchscreen/intel-mid-touch.c864
-rw-r--r--drivers/staging/msm/Kconfig134
-rw-r--r--drivers/staging/msm/Makefile93
-rw-r--r--drivers/staging/msm/TODO3
-rw-r--r--drivers/staging/msm/ebi2_l2f.c569
-rw-r--r--drivers/staging/msm/ebi2_lcd.c250
-rw-r--r--drivers/staging/msm/ebi2_tmd20.c1122
-rw-r--r--drivers/staging/msm/hdmi_sii9022.c248
-rw-r--r--drivers/staging/msm/lcdc.c239
-rw-r--r--drivers/staging/msm/lcdc_external.c54
-rw-r--r--drivers/staging/msm/lcdc_gordon.c446
-rw-r--r--drivers/staging/msm/lcdc_grapefruit.c60
-rw-r--r--drivers/staging/msm/lcdc_panel.c88
-rw-r--r--drivers/staging/msm/lcdc_prism.c64
-rw-r--r--drivers/staging/msm/lcdc_sharp_wvga_pt.c290
-rw-r--r--drivers/staging/msm/lcdc_st15.c237
-rw-r--r--drivers/staging/msm/lcdc_st1_wxga.c54
-rw-r--r--drivers/staging/msm/lcdc_toshiba_wvga_pt.c374
-rw-r--r--drivers/staging/msm/lcdc_wxga.c56
-rw-r--r--drivers/staging/msm/logo.c98
-rw-r--r--drivers/staging/msm/mddi.c375
-rw-r--r--drivers/staging/msm/mddi_ext.c320
-rw-r--r--drivers/staging/msm/mddi_ext_lcd.c91
-rw-r--r--drivers/staging/msm/mddi_prism.c114
-rw-r--r--drivers/staging/msm/mddi_sharp.c892
-rw-r--r--drivers/staging/msm/mddi_toshiba.c1741
-rw-r--r--drivers/staging/msm/mddi_toshiba.h52
-rw-r--r--drivers/staging/msm/mddi_toshiba_vga.c136
-rw-r--r--drivers/staging/msm/mddi_toshiba_wvga.c63
-rw-r--r--drivers/staging/msm/mddi_toshiba_wvga_pt.c64
-rw-r--r--drivers/staging/msm/mddihost.c377
-rw-r--r--drivers/staging/msm/mddihost.h225
-rw-r--r--drivers/staging/msm/mddihost_e.c63
-rw-r--r--drivers/staging/msm/mddihosti.c2239
-rw-r--r--drivers/staging/msm/mddihosti.h547
-rw-r--r--drivers/staging/msm/mdp.c1113
-rw-r--r--drivers/staging/msm/mdp.h695
-rw-r--r--drivers/staging/msm/mdp4.h352
-rw-r--r--drivers/staging/msm/mdp4_debugfs.c181
-rw-r--r--drivers/staging/msm/mdp4_overlay.c1259
-rw-r--r--drivers/staging/msm/mdp4_overlay_lcdc.c313
-rw-r--r--drivers/staging/msm/mdp4_overlay_mddi.c254
-rw-r--r--drivers/staging/msm/mdp4_util.c1686
-rw-r--r--drivers/staging/msm/mdp_cursor.c104
-rw-r--r--drivers/staging/msm/mdp_dma.c561
-rw-r--r--drivers/staging/msm/mdp_dma_lcdc.c379
-rw-r--r--drivers/staging/msm/mdp_dma_s.c139
-rw-r--r--drivers/staging/msm/mdp_dma_tv.c142
-rw-r--r--drivers/staging/msm/mdp_hw_init.c720
-rw-r--r--drivers/staging/msm/mdp_ppp.c1502
-rw-r--r--drivers/staging/msm/mdp_ppp_dq.c347
-rw-r--r--drivers/staging/msm/mdp_ppp_dq.h86
-rw-r--r--drivers/staging/msm/mdp_ppp_v20.c2486
-rw-r--r--drivers/staging/msm/mdp_ppp_v31.c828
-rw-r--r--drivers/staging/msm/mdp_vsync.c389
-rw-r--r--drivers/staging/msm/memory.c214
-rw-r--r--drivers/staging/msm/memory_ll.h61
-rw-r--r--drivers/staging/msm/msm_fb.c2354
-rw-r--r--drivers/staging/msm/msm_fb.h174
-rw-r--r--drivers/staging/msm/msm_fb_bl.c79
-rw-r--r--drivers/staging/msm/msm_fb_def.h201
-rw-r--r--drivers/staging/msm/msm_fb_panel.c136
-rw-r--r--drivers/staging/msm/msm_fb_panel.h145
-rw-r--r--drivers/staging/msm/msm_mdp.h245
-rw-r--r--drivers/staging/msm/staging-devices.c323
-rw-r--r--drivers/staging/msm/tv_ntsc.c163
-rw-r--r--drivers/staging/msm/tv_pal.c213
-rw-r--r--drivers/staging/msm/tvenc.c295
-rw-r--r--drivers/staging/msm/tvenc.h117
-rw-r--r--drivers/staging/phison/Kconfig2
-rw-r--r--drivers/staging/pohmelfs/inode.c10
-rw-r--r--drivers/staging/rt2860/sta_ioctl.c2
-rw-r--r--drivers/staging/sep/sep_driver.c52
-rw-r--r--drivers/staging/tm6000/Kconfig3
-rw-r--r--drivers/staging/tm6000/tm6000-alsa.c25
-rw-r--r--drivers/staging/tm6000/tm6000-cards.c45
-rw-r--r--drivers/staging/tm6000/tm6000-core.c121
-rw-r--r--drivers/staging/tm6000/tm6000-dvb.c74
-rw-r--r--drivers/staging/tm6000/tm6000-video.c104
-rw-r--r--drivers/staging/tm6000/tm6000.h25
-rw-r--r--drivers/staging/vme/bridges/vme_ca91cx42.c2
-rw-r--r--drivers/staging/vme/bridges/vme_tsi148.c2
-rw-r--r--drivers/staging/wlags49_h2/Kconfig12
-rw-r--r--drivers/staging/wlags49_h25/Kconfig12
-rw-r--r--drivers/staging/xgifb/Kconfig11
-rw-r--r--drivers/staging/xgifb/Makefile4
-rw-r--r--drivers/staging/xgifb/TODO15
-rw-r--r--drivers/staging/xgifb/XGI.h10
-rw-r--r--drivers/staging/xgifb/XGI_accel.c596
-rw-r--r--drivers/staging/xgifb/XGI_accel.h511
-rw-r--r--drivers/staging/xgifb/XGI_main.h1023
-rw-r--r--drivers/staging/xgifb/XGI_main_26.c3773
-rw-r--r--drivers/staging/xgifb/XGIfb.h215
-rw-r--r--drivers/staging/xgifb/osdef.h153
-rw-r--r--drivers/staging/xgifb/vb_def.h1017
-rw-r--r--drivers/staging/xgifb/vb_ext.c1370
-rw-r--r--drivers/staging/xgifb/vb_ext.h32
-rw-r--r--drivers/staging/xgifb/vb_init.c3444
-rw-r--r--drivers/staging/xgifb/vb_init.h7
-rw-r--r--drivers/staging/xgifb/vb_setmode.c10736
-rw-r--r--drivers/staging/xgifb/vb_setmode.h40
-rw-r--r--drivers/staging/xgifb/vb_struct.h534
-rw-r--r--drivers/staging/xgifb/vb_table.h4406
-rw-r--r--drivers/staging/xgifb/vb_util.c263
-rw-r--r--drivers/staging/xgifb/vb_util.h15
-rw-r--r--drivers/staging/xgifb/vgatypes.h325
-rw-r--r--drivers/telephony/ixj.c15
-rw-r--r--drivers/usb/class/cdc-acm.c6
-rw-r--r--drivers/usb/core/driver.c2
-rw-r--r--drivers/usb/gadget/Kconfig1
-rw-r--r--drivers/usb/gadget/f_audio.c4
-rw-r--r--drivers/usb/gadget/fsl_qe_udc.c4
-rw-r--r--drivers/usb/gadget/m66592-udc.h22
-rw-r--r--drivers/usb/gadget/printer.c2
-rw-r--r--drivers/usb/gadget/r8a66597-udc.c4
-rw-r--r--drivers/usb/gadget/r8a66597-udc.h24
-rw-r--r--drivers/usb/gadget/s3c-hsotg.c57
-rw-r--r--drivers/usb/host/ehci-hcd.c20
-rw-r--r--drivers/usb/host/ehci-xilinx-of.c2
-rw-r--r--drivers/usb/host/isp1362.h2
-rw-r--r--drivers/usb/host/r8a66597-hcd.c4
-rw-r--r--drivers/usb/host/r8a66597.h26
-rw-r--r--drivers/usb/host/xhci-pci.c2
-rw-r--r--drivers/usb/host/xhci-ring.c31
-rw-r--r--drivers/usb/host/xhci.c57
-rw-r--r--drivers/usb/host/xhci.h12
-rw-r--r--drivers/usb/serial/digi_acceleport.c3
-rw-r--r--drivers/usb/serial/ftdi_sio.c4
-rw-r--r--drivers/usb/serial/mos7840.c1
-rw-r--r--drivers/vhost/net.c16
-rw-r--r--drivers/vhost/vhost.c57
-rw-r--r--drivers/video/Kconfig6
-rw-r--r--drivers/video/aty/mach64_accel.c9
-rw-r--r--drivers/video/backlight/88pm860x_bl.c2
-rw-r--r--drivers/video/backlight/Kconfig116
-rw-r--r--drivers/video/backlight/Makefile4
-rw-r--r--drivers/video/backlight/adp8860_bl.c836
-rw-r--r--drivers/video/backlight/adx_bl.c4
-rw-r--r--drivers/video/backlight/ep93xx_bl.c160
-rw-r--r--drivers/video/backlight/l4f00242t03.c11
-rw-r--r--drivers/video/backlight/max8925_bl.c1
-rw-r--r--drivers/video/backlight/mbp_nvidia_bl.c47
-rw-r--r--drivers/video/backlight/pcf50633-backlight.c190
-rw-r--r--drivers/video/backlight/s6e63m0.c920
-rw-r--r--drivers/video/backlight/s6e63m0_gamma.h266
-rw-r--r--drivers/video/backlight/tosa_bl.c2
-rw-r--r--drivers/video/bf54x-lq043fb.c7
-rw-r--r--drivers/video/bfin-t350mcqb-fb.c7
-rw-r--r--drivers/video/bw2.c2
-rw-r--r--drivers/video/cg14.c2
-rw-r--r--drivers/video/cg3.c2
-rw-r--r--drivers/video/fb_defio.c54
-rw-r--r--drivers/video/leo.c2
-rw-r--r--drivers/video/mb862xx/mb862xxfb.c2
-rw-r--r--drivers/video/p9100.c2
-rw-r--r--drivers/video/s3fb.c101
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c6
-rw-r--r--drivers/video/tcx.c2
-rw-r--r--drivers/video/via/viafbdev.c11
-rw-r--r--drivers/watchdog/gef_wdt.c2
-rw-r--r--drivers/watchdog/mpc8xxx_wdt.c2
-rw-r--r--drivers/watchdog/rdc321x_wdt.c53
-rw-r--r--drivers/watchdog/wm8350_wdt.c2
-rw-r--r--drivers/xen/xenbus/xenbus_xs.c2
909 files changed, 97776 insertions, 9507 deletions
diff --git a/drivers/Makefile b/drivers/Makefile
index f42a03029b7c..91874e048552 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_PCI) += pci/
10obj-$(CONFIG_PARISC) += parisc/ 10obj-$(CONFIG_PARISC) += parisc/
11obj-$(CONFIG_RAPIDIO) += rapidio/ 11obj-$(CONFIG_RAPIDIO) += rapidio/
12obj-y += video/ 12obj-y += video/
13obj-y += idle/
13obj-$(CONFIG_ACPI) += acpi/ 14obj-$(CONFIG_ACPI) += acpi/
14obj-$(CONFIG_SFI) += sfi/ 15obj-$(CONFIG_SFI) += sfi/
15# PnP must come after ACPI since it will eventually need to check if acpi 16# PnP must come after ACPI since it will eventually need to check if acpi
@@ -91,7 +92,6 @@ obj-$(CONFIG_EISA) += eisa/
91obj-y += lguest/ 92obj-y += lguest/
92obj-$(CONFIG_CPU_FREQ) += cpufreq/ 93obj-$(CONFIG_CPU_FREQ) += cpufreq/
93obj-$(CONFIG_CPU_IDLE) += cpuidle/ 94obj-$(CONFIG_CPU_IDLE) += cpuidle/
94obj-y += idle/
95obj-$(CONFIG_MMC) += mmc/ 95obj-$(CONFIG_MMC) += mmc/
96obj-$(CONFIG_MEMSTICK) += memstick/ 96obj-$(CONFIG_MEMSTICK) += memstick/
97obj-$(CONFIG_NEW_LEDS) += leds/ 97obj-$(CONFIG_NEW_LEDS) += leds/
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 93d2c7971df6..746411518802 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -360,4 +360,13 @@ config ACPI_SBS
360 To compile this driver as a module, choose M here: 360 To compile this driver as a module, choose M here:
361 the modules will be called sbs and sbshc. 361 the modules will be called sbs and sbshc.
362 362
363config ACPI_HED
364 tristate "Hardware Error Device"
365 help
366 This driver supports the Hardware Error Device (PNP0C33),
367 which is used to report some hardware errors notified via
368 SCI, mainly the corrected errors.
369
370source "drivers/acpi/apei/Kconfig"
371
363endif # ACPI 372endif # ACPI
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index a8d8998dd5c5..6ee33169e1dc 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -19,7 +19,7 @@ obj-y += acpi.o \
19 19
20# All the builtin files are in the "acpi." module_param namespace. 20# All the builtin files are in the "acpi." module_param namespace.
21acpi-y += osl.o utils.o reboot.o 21acpi-y += osl.o utils.o reboot.o
22acpi-y += hest.o 22acpi-y += atomicio.o
23 23
24# sleep related files 24# sleep related files
25acpi-y += wakeup.o 25acpi-y += wakeup.o
@@ -59,6 +59,7 @@ obj-$(CONFIG_ACPI_BATTERY) += battery.o
59obj-$(CONFIG_ACPI_SBS) += sbshc.o 59obj-$(CONFIG_ACPI_SBS) += sbshc.o
60obj-$(CONFIG_ACPI_SBS) += sbs.o 60obj-$(CONFIG_ACPI_SBS) += sbs.o
61obj-$(CONFIG_ACPI_POWER_METER) += power_meter.o 61obj-$(CONFIG_ACPI_POWER_METER) += power_meter.o
62obj-$(CONFIG_ACPI_HED) += hed.o
62 63
63# processor has its own "processor." module_param namespace 64# processor has its own "processor." module_param namespace
64processor-y := processor_driver.o processor_throttling.o 65processor-y := processor_driver.o processor_throttling.o
@@ -66,3 +67,5 @@ processor-y += processor_idle.o processor_thermal.o
66processor-$(CONFIG_CPU_FREQ) += processor_perflib.o 67processor-$(CONFIG_CPU_FREQ) += processor_perflib.o
67 68
68obj-$(CONFIG_ACPI_PROCESSOR_AGGREGATOR) += acpi_pad.o 69obj-$(CONFIG_ACPI_PROCESSOR_AGGREGATOR) += acpi_pad.o
70
71obj-$(CONFIG_ACPI_APEI) += apei/
diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c
index 62122134693b..d269a8f3329c 100644
--- a/drivers/acpi/acpi_pad.c
+++ b/drivers/acpi/acpi_pad.c
@@ -43,6 +43,10 @@ static DEFINE_MUTEX(isolated_cpus_lock);
43#define CPUID5_ECX_EXTENSIONS_SUPPORTED (0x1) 43#define CPUID5_ECX_EXTENSIONS_SUPPORTED (0x1)
44#define CPUID5_ECX_INTERRUPT_BREAK (0x2) 44#define CPUID5_ECX_INTERRUPT_BREAK (0x2)
45static unsigned long power_saving_mwait_eax; 45static unsigned long power_saving_mwait_eax;
46
47static unsigned char tsc_detected_unstable;
48static unsigned char tsc_marked_unstable;
49
46static void power_saving_mwait_init(void) 50static void power_saving_mwait_init(void)
47{ 51{
48 unsigned int eax, ebx, ecx, edx; 52 unsigned int eax, ebx, ecx, edx;
@@ -87,8 +91,8 @@ static void power_saving_mwait_init(void)
87 91
88 /*FALL THROUGH*/ 92 /*FALL THROUGH*/
89 default: 93 default:
90 /* TSC could halt in idle, so notify users */ 94 /* TSC could halt in idle */
91 mark_tsc_unstable("TSC halts in idle"); 95 tsc_detected_unstable = 1;
92 } 96 }
93#endif 97#endif
94} 98}
@@ -168,16 +172,14 @@ static int power_saving_thread(void *data)
168 172
169 do_sleep = 0; 173 do_sleep = 0;
170 174
171 current_thread_info()->status &= ~TS_POLLING;
172 /*
173 * TS_POLLING-cleared state must be visible before we test
174 * NEED_RESCHED:
175 */
176 smp_mb();
177
178 expire_time = jiffies + HZ * (100 - idle_pct) / 100; 175 expire_time = jiffies + HZ * (100 - idle_pct) / 100;
179 176
180 while (!need_resched()) { 177 while (!need_resched()) {
178 if (tsc_detected_unstable && !tsc_marked_unstable) {
179 /* TSC could halt in idle, so notify users */
180 mark_tsc_unstable("TSC halts in idle");
181 tsc_marked_unstable = 1;
182 }
181 local_irq_disable(); 183 local_irq_disable();
182 cpu = smp_processor_id(); 184 cpu = smp_processor_id();
183 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, 185 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER,
@@ -200,8 +202,6 @@ static int power_saving_thread(void *data)
200 } 202 }
201 } 203 }
202 204
203 current_thread_info()->status |= TS_POLLING;
204
205 /* 205 /*
206 * current sched_rt has threshold for rt task running time. 206 * current sched_rt has threshold for rt task running time.
207 * When a rt task uses 95% CPU time, the rt thread will be 207 * When a rt task uses 95% CPU time, the rt thread will be
diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c
index 7c7bbb4d402c..d5a5efc043bf 100644
--- a/drivers/acpi/acpica/evxfevnt.c
+++ b/drivers/acpi/acpica/evxfevnt.c
@@ -69,7 +69,7 @@ acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
69 69
70acpi_status acpi_enable(void) 70acpi_status acpi_enable(void)
71{ 71{
72 acpi_status status = AE_OK; 72 acpi_status status;
73 73
74 ACPI_FUNCTION_TRACE(acpi_enable); 74 ACPI_FUNCTION_TRACE(acpi_enable);
75 75
@@ -84,21 +84,30 @@ acpi_status acpi_enable(void)
84 if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) { 84 if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) {
85 ACPI_DEBUG_PRINT((ACPI_DB_INIT, 85 ACPI_DEBUG_PRINT((ACPI_DB_INIT,
86 "System is already in ACPI mode\n")); 86 "System is already in ACPI mode\n"));
87 } else { 87 return_ACPI_STATUS(AE_OK);
88 /* Transition to ACPI mode */ 88 }
89 89
90 status = acpi_hw_set_mode(ACPI_SYS_MODE_ACPI); 90 /* Transition to ACPI mode */
91 if (ACPI_FAILURE(status)) {
92 ACPI_ERROR((AE_INFO,
93 "Could not transition to ACPI mode"));
94 return_ACPI_STATUS(status);
95 }
96 91
97 ACPI_DEBUG_PRINT((ACPI_DB_INIT, 92 status = acpi_hw_set_mode(ACPI_SYS_MODE_ACPI);
98 "Transition to ACPI mode successful\n")); 93 if (ACPI_FAILURE(status)) {
94 ACPI_ERROR((AE_INFO,
95 "Could not transition to ACPI mode"));
96 return_ACPI_STATUS(status);
99 } 97 }
100 98
101 return_ACPI_STATUS(status); 99 /* Sanity check that transition succeeded */
100
101 if (acpi_hw_get_mode() != ACPI_SYS_MODE_ACPI) {
102 ACPI_ERROR((AE_INFO,
103 "Hardware did not enter ACPI mode"));
104 return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
105 }
106
107 ACPI_DEBUG_PRINT((ACPI_DB_INIT,
108 "Transition to ACPI mode successful\n"));
109
110 return_ACPI_STATUS(AE_OK);
102} 111}
103 112
104ACPI_EXPORT_SYMBOL(acpi_enable) 113ACPI_EXPORT_SYMBOL(acpi_enable)
diff --git a/drivers/acpi/acpica/hwacpi.c b/drivers/acpi/acpica/hwacpi.c
index 679a112a7d26..b44274a0b62c 100644
--- a/drivers/acpi/acpica/hwacpi.c
+++ b/drivers/acpi/acpica/hwacpi.c
@@ -63,7 +63,6 @@ acpi_status acpi_hw_set_mode(u32 mode)
63{ 63{
64 64
65 acpi_status status; 65 acpi_status status;
66 u32 retry;
67 66
68 ACPI_FUNCTION_TRACE(hw_set_mode); 67 ACPI_FUNCTION_TRACE(hw_set_mode);
69 68
@@ -125,24 +124,7 @@ acpi_status acpi_hw_set_mode(u32 mode)
125 return_ACPI_STATUS(status); 124 return_ACPI_STATUS(status);
126 } 125 }
127 126
128 /* 127 return_ACPI_STATUS(AE_OK);
129 * Some hardware takes a LONG time to switch modes. Give them 3 sec to
130 * do so, but allow faster systems to proceed more quickly.
131 */
132 retry = 3000;
133 while (retry) {
134 if (acpi_hw_get_mode() == mode) {
135 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
136 "Mode %X successfully enabled\n",
137 mode));
138 return_ACPI_STATUS(AE_OK);
139 }
140 acpi_os_stall(1000);
141 retry--;
142 }
143
144 ACPI_ERROR((AE_INFO, "Hardware did not change modes"));
145 return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
146} 128}
147 129
148/******************************************************************************* 130/*******************************************************************************
diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig
new file mode 100644
index 000000000000..f8c668f27b5a
--- /dev/null
+++ b/drivers/acpi/apei/Kconfig
@@ -0,0 +1,30 @@
1config ACPI_APEI
2 bool "ACPI Platform Error Interface (APEI)"
3 depends on X86
4 help
5 APEI allows to report errors (for example from the chipset)
6 to the operating system. This improves NMI handling
7 especially. In addition it supports error serialization and
8 error injection.
9
10config ACPI_APEI_GHES
11 tristate "APEI Generic Hardware Error Source"
12 depends on ACPI_APEI && X86
13 select ACPI_HED
14 help
15 Generic Hardware Error Source provides a way to report
16 platform hardware errors (such as that from chipset). It
17 works in so called "Firmware First" mode, that is, hardware
18 errors are reported to firmware firstly, then reported to
19 Linux by firmware. This way, some non-standard hardware
20 error registers or non-standard hardware link can be checked
21 by firmware to produce more valuable hardware error
22 information for Linux.
23
24config ACPI_APEI_EINJ
25 tristate "APEI Error INJection (EINJ)"
26 depends on ACPI_APEI && DEBUG_FS
27 help
28 EINJ provides a hardware error injection mechanism, it is
29 mainly used for debugging and testing the other parts of
30 APEI and some other RAS features.
diff --git a/drivers/acpi/apei/Makefile b/drivers/acpi/apei/Makefile
new file mode 100644
index 000000000000..b13b03a17789
--- /dev/null
+++ b/drivers/acpi/apei/Makefile
@@ -0,0 +1,5 @@
1obj-$(CONFIG_ACPI_APEI) += apei.o
2obj-$(CONFIG_ACPI_APEI_GHES) += ghes.o
3obj-$(CONFIG_ACPI_APEI_EINJ) += einj.o
4
5apei-y := apei-base.o hest.o cper.o erst.o
diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c
new file mode 100644
index 000000000000..db3946e9c66b
--- /dev/null
+++ b/drivers/acpi/apei/apei-base.c
@@ -0,0 +1,593 @@
1/*
2 * apei-base.c - ACPI Platform Error Interface (APEI) supporting
3 * infrastructure
4 *
5 * APEI allows to report errors (for example from the chipset) to the
6 * the operating system. This improves NMI handling especially. In
7 * addition it supports error serialization and error injection.
8 *
9 * For more information about APEI, please refer to ACPI Specification
10 * version 4.0, chapter 17.
11 *
12 * This file has Common functions used by more than one APEI table,
13 * including framework of interpreter for ERST and EINJ; resource
14 * management for APEI registers.
15 *
16 * Copyright (C) 2009, Intel Corp.
17 * Author: Huang Ying <ying.huang@intel.com>
18 *
19 * This program is free software; you can redistribute it and/or
20 * modify it under the terms of the GNU General Public License version
21 * 2 as published by the Free Software Foundation.
22 *
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 */
32
33#include <linux/kernel.h>
34#include <linux/module.h>
35#include <linux/init.h>
36#include <linux/acpi.h>
37#include <linux/io.h>
38#include <linux/kref.h>
39#include <linux/rculist.h>
40#include <linux/interrupt.h>
41#include <linux/debugfs.h>
42#include <acpi/atomicio.h>
43
44#include "apei-internal.h"
45
46#define APEI_PFX "APEI: "
47
48/*
49 * APEI ERST (Error Record Serialization Table) and EINJ (Error
50 * INJection) interpreter framework.
51 */
52
53#define APEI_EXEC_PRESERVE_REGISTER 0x1
54
55void apei_exec_ctx_init(struct apei_exec_context *ctx,
56 struct apei_exec_ins_type *ins_table,
57 u32 instructions,
58 struct acpi_whea_header *action_table,
59 u32 entries)
60{
61 ctx->ins_table = ins_table;
62 ctx->instructions = instructions;
63 ctx->action_table = action_table;
64 ctx->entries = entries;
65}
66EXPORT_SYMBOL_GPL(apei_exec_ctx_init);
67
68int __apei_exec_read_register(struct acpi_whea_header *entry, u64 *val)
69{
70 int rc;
71
72 rc = acpi_atomic_read(val, &entry->register_region);
73 if (rc)
74 return rc;
75 *val >>= entry->register_region.bit_offset;
76 *val &= entry->mask;
77
78 return 0;
79}
80
81int apei_exec_read_register(struct apei_exec_context *ctx,
82 struct acpi_whea_header *entry)
83{
84 int rc;
85 u64 val = 0;
86
87 rc = __apei_exec_read_register(entry, &val);
88 if (rc)
89 return rc;
90 ctx->value = val;
91
92 return 0;
93}
94EXPORT_SYMBOL_GPL(apei_exec_read_register);
95
96int apei_exec_read_register_value(struct apei_exec_context *ctx,
97 struct acpi_whea_header *entry)
98{
99 int rc;
100
101 rc = apei_exec_read_register(ctx, entry);
102 if (rc)
103 return rc;
104 ctx->value = (ctx->value == entry->value);
105
106 return 0;
107}
108EXPORT_SYMBOL_GPL(apei_exec_read_register_value);
109
110int __apei_exec_write_register(struct acpi_whea_header *entry, u64 val)
111{
112 int rc;
113
114 val &= entry->mask;
115 val <<= entry->register_region.bit_offset;
116 if (entry->flags & APEI_EXEC_PRESERVE_REGISTER) {
117 u64 valr = 0;
118 rc = acpi_atomic_read(&valr, &entry->register_region);
119 if (rc)
120 return rc;
121 valr &= ~(entry->mask << entry->register_region.bit_offset);
122 val |= valr;
123 }
124 rc = acpi_atomic_write(val, &entry->register_region);
125
126 return rc;
127}
128
129int apei_exec_write_register(struct apei_exec_context *ctx,
130 struct acpi_whea_header *entry)
131{
132 return __apei_exec_write_register(entry, ctx->value);
133}
134EXPORT_SYMBOL_GPL(apei_exec_write_register);
135
136int apei_exec_write_register_value(struct apei_exec_context *ctx,
137 struct acpi_whea_header *entry)
138{
139 int rc;
140
141 ctx->value = entry->value;
142 rc = apei_exec_write_register(ctx, entry);
143
144 return rc;
145}
146EXPORT_SYMBOL_GPL(apei_exec_write_register_value);
147
148int apei_exec_noop(struct apei_exec_context *ctx,
149 struct acpi_whea_header *entry)
150{
151 return 0;
152}
153EXPORT_SYMBOL_GPL(apei_exec_noop);
154
155/*
156 * Interpret the specified action. Go through whole action table,
157 * execute all instructions belong to the action.
158 */
159int apei_exec_run(struct apei_exec_context *ctx, u8 action)
160{
161 int rc;
162 u32 i, ip;
163 struct acpi_whea_header *entry;
164 apei_exec_ins_func_t run;
165
166 ctx->ip = 0;
167
168 /*
169 * "ip" is the instruction pointer of current instruction,
170 * "ctx->ip" specifies the next instruction to executed,
171 * instruction "run" function may change the "ctx->ip" to
172 * implement "goto" semantics.
173 */
174rewind:
175 ip = 0;
176 for (i = 0; i < ctx->entries; i++) {
177 entry = &ctx->action_table[i];
178 if (entry->action != action)
179 continue;
180 if (ip == ctx->ip) {
181 if (entry->instruction >= ctx->instructions ||
182 !ctx->ins_table[entry->instruction].run) {
183 pr_warning(FW_WARN APEI_PFX
184 "Invalid action table, unknown instruction type: %d\n",
185 entry->instruction);
186 return -EINVAL;
187 }
188 run = ctx->ins_table[entry->instruction].run;
189 rc = run(ctx, entry);
190 if (rc < 0)
191 return rc;
192 else if (rc != APEI_EXEC_SET_IP)
193 ctx->ip++;
194 }
195 ip++;
196 if (ctx->ip < ip)
197 goto rewind;
198 }
199
200 return 0;
201}
202EXPORT_SYMBOL_GPL(apei_exec_run);
203
204typedef int (*apei_exec_entry_func_t)(struct apei_exec_context *ctx,
205 struct acpi_whea_header *entry,
206 void *data);
207
208static int apei_exec_for_each_entry(struct apei_exec_context *ctx,
209 apei_exec_entry_func_t func,
210 void *data,
211 int *end)
212{
213 u8 ins;
214 int i, rc;
215 struct acpi_whea_header *entry;
216 struct apei_exec_ins_type *ins_table = ctx->ins_table;
217
218 for (i = 0; i < ctx->entries; i++) {
219 entry = ctx->action_table + i;
220 ins = entry->instruction;
221 if (end)
222 *end = i;
223 if (ins >= ctx->instructions || !ins_table[ins].run) {
224 pr_warning(FW_WARN APEI_PFX
225 "Invalid action table, unknown instruction type: %d\n",
226 ins);
227 return -EINVAL;
228 }
229 rc = func(ctx, entry, data);
230 if (rc)
231 return rc;
232 }
233
234 return 0;
235}
236
237static int pre_map_gar_callback(struct apei_exec_context *ctx,
238 struct acpi_whea_header *entry,
239 void *data)
240{
241 u8 ins = entry->instruction;
242
243 if (ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER)
244 return acpi_pre_map_gar(&entry->register_region);
245
246 return 0;
247}
248
249/*
250 * Pre-map all GARs in action table to make it possible to access them
251 * in NMI handler.
252 */
253int apei_exec_pre_map_gars(struct apei_exec_context *ctx)
254{
255 int rc, end;
256
257 rc = apei_exec_for_each_entry(ctx, pre_map_gar_callback,
258 NULL, &end);
259 if (rc) {
260 struct apei_exec_context ctx_unmap;
261 memcpy(&ctx_unmap, ctx, sizeof(*ctx));
262 ctx_unmap.entries = end;
263 apei_exec_post_unmap_gars(&ctx_unmap);
264 }
265
266 return rc;
267}
268EXPORT_SYMBOL_GPL(apei_exec_pre_map_gars);
269
270static int post_unmap_gar_callback(struct apei_exec_context *ctx,
271 struct acpi_whea_header *entry,
272 void *data)
273{
274 u8 ins = entry->instruction;
275
276 if (ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER)
277 acpi_post_unmap_gar(&entry->register_region);
278
279 return 0;
280}
281
282/* Post-unmap all GAR in action table. */
283int apei_exec_post_unmap_gars(struct apei_exec_context *ctx)
284{
285 return apei_exec_for_each_entry(ctx, post_unmap_gar_callback,
286 NULL, NULL);
287}
288EXPORT_SYMBOL_GPL(apei_exec_post_unmap_gars);
289
290/*
291 * Resource management for GARs in APEI
292 */
293struct apei_res {
294 struct list_head list;
295 unsigned long start;
296 unsigned long end;
297};
298
299/* Collect all resources requested, to avoid conflict */
300struct apei_resources apei_resources_all = {
301 .iomem = LIST_HEAD_INIT(apei_resources_all.iomem),
302 .ioport = LIST_HEAD_INIT(apei_resources_all.ioport),
303};
304
305static int apei_res_add(struct list_head *res_list,
306 unsigned long start, unsigned long size)
307{
308 struct apei_res *res, *resn, *res_ins = NULL;
309 unsigned long end = start + size;
310
311 if (end <= start)
312 return 0;
313repeat:
314 list_for_each_entry_safe(res, resn, res_list, list) {
315 if (res->start > end || res->end < start)
316 continue;
317 else if (end <= res->end && start >= res->start) {
318 kfree(res_ins);
319 return 0;
320 }
321 list_del(&res->list);
322 res->start = start = min(res->start, start);
323 res->end = end = max(res->end, end);
324 kfree(res_ins);
325 res_ins = res;
326 goto repeat;
327 }
328
329 if (res_ins)
330 list_add(&res_ins->list, res_list);
331 else {
332 res_ins = kmalloc(sizeof(*res), GFP_KERNEL);
333 if (!res_ins)
334 return -ENOMEM;
335 res_ins->start = start;
336 res_ins->end = end;
337 list_add(&res_ins->list, res_list);
338 }
339
340 return 0;
341}
342
343static int apei_res_sub(struct list_head *res_list1,
344 struct list_head *res_list2)
345{
346 struct apei_res *res1, *resn1, *res2, *res;
347 res1 = list_entry(res_list1->next, struct apei_res, list);
348 resn1 = list_entry(res1->list.next, struct apei_res, list);
349 while (&res1->list != res_list1) {
350 list_for_each_entry(res2, res_list2, list) {
351 if (res1->start >= res2->end ||
352 res1->end <= res2->start)
353 continue;
354 else if (res1->end <= res2->end &&
355 res1->start >= res2->start) {
356 list_del(&res1->list);
357 kfree(res1);
358 break;
359 } else if (res1->end > res2->end &&
360 res1->start < res2->start) {
361 res = kmalloc(sizeof(*res), GFP_KERNEL);
362 if (!res)
363 return -ENOMEM;
364 res->start = res2->end;
365 res->end = res1->end;
366 res1->end = res2->start;
367 list_add(&res->list, &res1->list);
368 resn1 = res;
369 } else {
370 if (res1->start < res2->start)
371 res1->end = res2->start;
372 else
373 res1->start = res2->end;
374 }
375 }
376 res1 = resn1;
377 resn1 = list_entry(resn1->list.next, struct apei_res, list);
378 }
379
380 return 0;
381}
382
383static void apei_res_clean(struct list_head *res_list)
384{
385 struct apei_res *res, *resn;
386
387 list_for_each_entry_safe(res, resn, res_list, list) {
388 list_del(&res->list);
389 kfree(res);
390 }
391}
392
393void apei_resources_fini(struct apei_resources *resources)
394{
395 apei_res_clean(&resources->iomem);
396 apei_res_clean(&resources->ioport);
397}
398EXPORT_SYMBOL_GPL(apei_resources_fini);
399
400static int apei_resources_merge(struct apei_resources *resources1,
401 struct apei_resources *resources2)
402{
403 int rc;
404 struct apei_res *res;
405
406 list_for_each_entry(res, &resources2->iomem, list) {
407 rc = apei_res_add(&resources1->iomem, res->start,
408 res->end - res->start);
409 if (rc)
410 return rc;
411 }
412 list_for_each_entry(res, &resources2->ioport, list) {
413 rc = apei_res_add(&resources1->ioport, res->start,
414 res->end - res->start);
415 if (rc)
416 return rc;
417 }
418
419 return 0;
420}
421
422/*
423 * EINJ has two groups of GARs (EINJ table entry and trigger table
424 * entry), so common resources are subtracted from the trigger table
425 * resources before the second requesting.
426 */
427int apei_resources_sub(struct apei_resources *resources1,
428 struct apei_resources *resources2)
429{
430 int rc;
431
432 rc = apei_res_sub(&resources1->iomem, &resources2->iomem);
433 if (rc)
434 return rc;
435 return apei_res_sub(&resources1->ioport, &resources2->ioport);
436}
437EXPORT_SYMBOL_GPL(apei_resources_sub);
438
439/*
440 * IO memory/port rersource management mechanism is used to check
441 * whether memory/port area used by GARs conflicts with normal memory
442 * or IO memory/port of devices.
443 */
444int apei_resources_request(struct apei_resources *resources,
445 const char *desc)
446{
447 struct apei_res *res, *res_bak;
448 struct resource *r;
449
450 apei_resources_sub(resources, &apei_resources_all);
451
452 list_for_each_entry(res, &resources->iomem, list) {
453 r = request_mem_region(res->start, res->end - res->start,
454 desc);
455 if (!r) {
456 pr_err(APEI_PFX
457 "Can not request iomem region <%016llx-%016llx> for GARs.\n",
458 (unsigned long long)res->start,
459 (unsigned long long)res->end);
460 res_bak = res;
461 goto err_unmap_iomem;
462 }
463 }
464
465 list_for_each_entry(res, &resources->ioport, list) {
466 r = request_region(res->start, res->end - res->start, desc);
467 if (!r) {
468 pr_err(APEI_PFX
469 "Can not request ioport region <%016llx-%016llx> for GARs.\n",
470 (unsigned long long)res->start,
471 (unsigned long long)res->end);
472 res_bak = res;
473 goto err_unmap_ioport;
474 }
475 }
476
477 apei_resources_merge(&apei_resources_all, resources);
478
479 return 0;
480err_unmap_ioport:
481 list_for_each_entry(res, &resources->ioport, list) {
482 if (res == res_bak)
483 break;
484 release_mem_region(res->start, res->end - res->start);
485 }
486 res_bak = NULL;
487err_unmap_iomem:
488 list_for_each_entry(res, &resources->iomem, list) {
489 if (res == res_bak)
490 break;
491 release_region(res->start, res->end - res->start);
492 }
493 return -EINVAL;
494}
495EXPORT_SYMBOL_GPL(apei_resources_request);
496
497void apei_resources_release(struct apei_resources *resources)
498{
499 struct apei_res *res;
500
501 list_for_each_entry(res, &resources->iomem, list)
502 release_mem_region(res->start, res->end - res->start);
503 list_for_each_entry(res, &resources->ioport, list)
504 release_region(res->start, res->end - res->start);
505
506 apei_resources_sub(&apei_resources_all, resources);
507}
508EXPORT_SYMBOL_GPL(apei_resources_release);
509
510static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr)
511{
512 u32 width, space_id;
513
514 width = reg->bit_width;
515 space_id = reg->space_id;
516 /* Handle possible alignment issues */
517 memcpy(paddr, &reg->address, sizeof(*paddr));
518 if (!*paddr) {
519 pr_warning(FW_BUG APEI_PFX
520 "Invalid physical address in GAR [0x%llx/%u/%u]\n",
521 *paddr, width, space_id);
522 return -EINVAL;
523 }
524
525 if ((width != 8) && (width != 16) && (width != 32) && (width != 64)) {
526 pr_warning(FW_BUG APEI_PFX
527 "Invalid bit width in GAR [0x%llx/%u/%u]\n",
528 *paddr, width, space_id);
529 return -EINVAL;
530 }
531
532 if (space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY &&
533 space_id != ACPI_ADR_SPACE_SYSTEM_IO) {
534 pr_warning(FW_BUG APEI_PFX
535 "Invalid address space type in GAR [0x%llx/%u/%u]\n",
536 *paddr, width, space_id);
537 return -EINVAL;
538 }
539
540 return 0;
541}
542
543static int collect_res_callback(struct apei_exec_context *ctx,
544 struct acpi_whea_header *entry,
545 void *data)
546{
547 struct apei_resources *resources = data;
548 struct acpi_generic_address *reg = &entry->register_region;
549 u8 ins = entry->instruction;
550 u64 paddr;
551 int rc;
552
553 if (!(ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER))
554 return 0;
555
556 rc = apei_check_gar(reg, &paddr);
557 if (rc)
558 return rc;
559
560 switch (reg->space_id) {
561 case ACPI_ADR_SPACE_SYSTEM_MEMORY:
562 return apei_res_add(&resources->iomem, paddr,
563 reg->bit_width / 8);
564 case ACPI_ADR_SPACE_SYSTEM_IO:
565 return apei_res_add(&resources->ioport, paddr,
566 reg->bit_width / 8);
567 default:
568 return -EINVAL;
569 }
570}
571
572/*
573 * Same register may be used by multiple instructions in GARs, so
574 * resources are collected before requesting.
575 */
576int apei_exec_collect_resources(struct apei_exec_context *ctx,
577 struct apei_resources *resources)
578{
579 return apei_exec_for_each_entry(ctx, collect_res_callback,
580 resources, NULL);
581}
582EXPORT_SYMBOL_GPL(apei_exec_collect_resources);
583
584struct dentry *apei_get_debugfs_dir(void)
585{
586 static struct dentry *dapei;
587
588 if (!dapei)
589 dapei = debugfs_create_dir("apei", NULL);
590
591 return dapei;
592}
593EXPORT_SYMBOL_GPL(apei_get_debugfs_dir);
diff --git a/drivers/acpi/apei/apei-internal.h b/drivers/acpi/apei/apei-internal.h
new file mode 100644
index 000000000000..18df1e940276
--- /dev/null
+++ b/drivers/acpi/apei/apei-internal.h
@@ -0,0 +1,114 @@
1/*
2 * apei-internal.h - ACPI Platform Error Interface internal
3 * definations.
4 */
5
6#ifndef APEI_INTERNAL_H
7#define APEI_INTERNAL_H
8
9#include <linux/cper.h>
10
11struct apei_exec_context;
12
13typedef int (*apei_exec_ins_func_t)(struct apei_exec_context *ctx,
14 struct acpi_whea_header *entry);
15
16#define APEI_EXEC_INS_ACCESS_REGISTER 0x0001
17
18struct apei_exec_ins_type {
19 u32 flags;
20 apei_exec_ins_func_t run;
21};
22
23struct apei_exec_context {
24 u32 ip;
25 u64 value;
26 u64 var1;
27 u64 var2;
28 u64 src_base;
29 u64 dst_base;
30 struct apei_exec_ins_type *ins_table;
31 u32 instructions;
32 struct acpi_whea_header *action_table;
33 u32 entries;
34};
35
36void apei_exec_ctx_init(struct apei_exec_context *ctx,
37 struct apei_exec_ins_type *ins_table,
38 u32 instructions,
39 struct acpi_whea_header *action_table,
40 u32 entries);
41
42static inline void apei_exec_ctx_set_input(struct apei_exec_context *ctx,
43 u64 input)
44{
45 ctx->value = input;
46}
47
48static inline u64 apei_exec_ctx_get_output(struct apei_exec_context *ctx)
49{
50 return ctx->value;
51}
52
53int apei_exec_run(struct apei_exec_context *ctx, u8 action);
54
55/* Common instruction implementation */
56
57/* IP has been set in instruction function */
58#define APEI_EXEC_SET_IP 1
59
60int __apei_exec_read_register(struct acpi_whea_header *entry, u64 *val);
61int __apei_exec_write_register(struct acpi_whea_header *entry, u64 val);
62int apei_exec_read_register(struct apei_exec_context *ctx,
63 struct acpi_whea_header *entry);
64int apei_exec_read_register_value(struct apei_exec_context *ctx,
65 struct acpi_whea_header *entry);
66int apei_exec_write_register(struct apei_exec_context *ctx,
67 struct acpi_whea_header *entry);
68int apei_exec_write_register_value(struct apei_exec_context *ctx,
69 struct acpi_whea_header *entry);
70int apei_exec_noop(struct apei_exec_context *ctx,
71 struct acpi_whea_header *entry);
72int apei_exec_pre_map_gars(struct apei_exec_context *ctx);
73int apei_exec_post_unmap_gars(struct apei_exec_context *ctx);
74
75struct apei_resources {
76 struct list_head iomem;
77 struct list_head ioport;
78};
79
80static inline void apei_resources_init(struct apei_resources *resources)
81{
82 INIT_LIST_HEAD(&resources->iomem);
83 INIT_LIST_HEAD(&resources->ioport);
84}
85
86void apei_resources_fini(struct apei_resources *resources);
87int apei_resources_sub(struct apei_resources *resources1,
88 struct apei_resources *resources2);
89int apei_resources_request(struct apei_resources *resources,
90 const char *desc);
91void apei_resources_release(struct apei_resources *resources);
92int apei_exec_collect_resources(struct apei_exec_context *ctx,
93 struct apei_resources *resources);
94
95struct dentry;
96struct dentry *apei_get_debugfs_dir(void);
97
98#define apei_estatus_for_each_section(estatus, section) \
99 for (section = (struct acpi_hest_generic_data *)(estatus + 1); \
100 (void *)section - (void *)estatus < estatus->data_length; \
101 section = (void *)(section+1) + section->error_data_length)
102
103static inline u32 apei_estatus_len(struct acpi_hest_generic_status *estatus)
104{
105 if (estatus->raw_data_length)
106 return estatus->raw_data_offset + \
107 estatus->raw_data_length;
108 else
109 return sizeof(*estatus) + estatus->data_length;
110}
111
112int apei_estatus_check_header(const struct acpi_hest_generic_status *estatus);
113int apei_estatus_check(const struct acpi_hest_generic_status *estatus);
114#endif
diff --git a/drivers/acpi/apei/cper.c b/drivers/acpi/apei/cper.c
new file mode 100644
index 000000000000..f4cf2fc4c8c1
--- /dev/null
+++ b/drivers/acpi/apei/cper.c
@@ -0,0 +1,84 @@
1/*
2 * UEFI Common Platform Error Record (CPER) support
3 *
4 * Copyright (C) 2010, Intel Corp.
5 * Author: Huang Ying <ying.huang@intel.com>
6 *
7 * CPER is the format used to describe platform hardware error by
8 * various APEI tables, such as ERST, BERT and HEST etc.
9 *
10 * For more information about CPER, please refer to Appendix N of UEFI
11 * Specification version 2.3.
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License version
15 * 2 as published by the Free Software Foundation.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 */
26
27#include <linux/kernel.h>
28#include <linux/module.h>
29#include <linux/time.h>
30#include <linux/cper.h>
31#include <linux/acpi.h>
32
33/*
34 * CPER record ID need to be unique even after reboot, because record
35 * ID is used as index for ERST storage, while CPER records from
36 * multiple boot may co-exist in ERST.
37 */
38u64 cper_next_record_id(void)
39{
40 static atomic64_t seq;
41
42 if (!atomic64_read(&seq))
43 atomic64_set(&seq, ((u64)get_seconds()) << 32);
44
45 return atomic64_inc_return(&seq);
46}
47EXPORT_SYMBOL_GPL(cper_next_record_id);
48
49int apei_estatus_check_header(const struct acpi_hest_generic_status *estatus)
50{
51 if (estatus->data_length &&
52 estatus->data_length < sizeof(struct acpi_hest_generic_data))
53 return -EINVAL;
54 if (estatus->raw_data_length &&
55 estatus->raw_data_offset < sizeof(*estatus) + estatus->data_length)
56 return -EINVAL;
57
58 return 0;
59}
60EXPORT_SYMBOL_GPL(apei_estatus_check_header);
61
62int apei_estatus_check(const struct acpi_hest_generic_status *estatus)
63{
64 struct acpi_hest_generic_data *gdata;
65 unsigned int data_len, gedata_len;
66 int rc;
67
68 rc = apei_estatus_check_header(estatus);
69 if (rc)
70 return rc;
71 data_len = estatus->data_length;
72 gdata = (struct acpi_hest_generic_data *)(estatus + 1);
73 while (data_len > sizeof(*gdata)) {
74 gedata_len = gdata->error_data_length;
75 if (gedata_len > data_len - sizeof(*gdata))
76 return -EINVAL;
77 data_len -= gedata_len + sizeof(*gdata);
78 }
79 if (data_len)
80 return -EINVAL;
81
82 return 0;
83}
84EXPORT_SYMBOL_GPL(apei_estatus_check);
diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c
new file mode 100644
index 000000000000..465c885938ee
--- /dev/null
+++ b/drivers/acpi/apei/einj.c
@@ -0,0 +1,548 @@
1/*
2 * APEI Error INJection support
3 *
4 * EINJ provides a hardware error injection mechanism, this is useful
5 * for debugging and testing of other APEI and RAS features.
6 *
7 * For more information about EINJ, please refer to ACPI Specification
8 * version 4.0, section 17.5.
9 *
10 * Copyright 2009-2010 Intel Corp.
11 * Author: Huang Ying <ying.huang@intel.com>
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License version
15 * 2 as published by the Free Software Foundation.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 */
26
27#include <linux/kernel.h>
28#include <linux/module.h>
29#include <linux/init.h>
30#include <linux/io.h>
31#include <linux/debugfs.h>
32#include <linux/seq_file.h>
33#include <linux/nmi.h>
34#include <linux/delay.h>
35#include <acpi/acpi.h>
36
37#include "apei-internal.h"
38
39#define EINJ_PFX "EINJ: "
40
41#define SPIN_UNIT 100 /* 100ns */
42/* Firmware should respond within 1 miliseconds */
43#define FIRMWARE_TIMEOUT (1 * NSEC_PER_MSEC)
44
45/*
46 * Some BIOSes allow parameters to the SET_ERROR_TYPE entries in the
47 * EINJ table through an unpublished extension. Use with caution as
48 * most will ignore the parameter and make their own choice of address
49 * for error injection.
50 */
51struct einj_parameter {
52 u64 type;
53 u64 reserved1;
54 u64 reserved2;
55 u64 param1;
56 u64 param2;
57};
58
59#define EINJ_OP_BUSY 0x1
60#define EINJ_STATUS_SUCCESS 0x0
61#define EINJ_STATUS_FAIL 0x1
62#define EINJ_STATUS_INVAL 0x2
63
64#define EINJ_TAB_ENTRY(tab) \
65 ((struct acpi_whea_header *)((char *)(tab) + \
66 sizeof(struct acpi_table_einj)))
67
68static struct acpi_table_einj *einj_tab;
69
70static struct apei_resources einj_resources;
71
72static struct apei_exec_ins_type einj_ins_type[] = {
73 [ACPI_EINJ_READ_REGISTER] = {
74 .flags = APEI_EXEC_INS_ACCESS_REGISTER,
75 .run = apei_exec_read_register,
76 },
77 [ACPI_EINJ_READ_REGISTER_VALUE] = {
78 .flags = APEI_EXEC_INS_ACCESS_REGISTER,
79 .run = apei_exec_read_register_value,
80 },
81 [ACPI_EINJ_WRITE_REGISTER] = {
82 .flags = APEI_EXEC_INS_ACCESS_REGISTER,
83 .run = apei_exec_write_register,
84 },
85 [ACPI_EINJ_WRITE_REGISTER_VALUE] = {
86 .flags = APEI_EXEC_INS_ACCESS_REGISTER,
87 .run = apei_exec_write_register_value,
88 },
89 [ACPI_EINJ_NOOP] = {
90 .flags = 0,
91 .run = apei_exec_noop,
92 },
93};
94
95/*
96 * Prevent EINJ interpreter to run simultaneously, because the
97 * corresponding firmware implementation may not work properly when
98 * invoked simultaneously.
99 */
100static DEFINE_MUTEX(einj_mutex);
101
102static struct einj_parameter *einj_param;
103
104static void einj_exec_ctx_init(struct apei_exec_context *ctx)
105{
106 apei_exec_ctx_init(ctx, einj_ins_type, ARRAY_SIZE(einj_ins_type),
107 EINJ_TAB_ENTRY(einj_tab), einj_tab->entries);
108}
109
110static int __einj_get_available_error_type(u32 *type)
111{
112 struct apei_exec_context ctx;
113 int rc;
114
115 einj_exec_ctx_init(&ctx);
116 rc = apei_exec_run(&ctx, ACPI_EINJ_GET_ERROR_TYPE);
117 if (rc)
118 return rc;
119 *type = apei_exec_ctx_get_output(&ctx);
120
121 return 0;
122}
123
124/* Get error injection capabilities of the platform */
125static int einj_get_available_error_type(u32 *type)
126{
127 int rc;
128
129 mutex_lock(&einj_mutex);
130 rc = __einj_get_available_error_type(type);
131 mutex_unlock(&einj_mutex);
132
133 return rc;
134}
135
136static int einj_timedout(u64 *t)
137{
138 if ((s64)*t < SPIN_UNIT) {
139 pr_warning(FW_WARN EINJ_PFX
140 "Firmware does not respond in time\n");
141 return 1;
142 }
143 *t -= SPIN_UNIT;
144 ndelay(SPIN_UNIT);
145 touch_nmi_watchdog();
146 return 0;
147}
148
149static u64 einj_get_parameter_address(void)
150{
151 int i;
152 u64 paddr = 0;
153 struct acpi_whea_header *entry;
154
155 entry = EINJ_TAB_ENTRY(einj_tab);
156 for (i = 0; i < einj_tab->entries; i++) {
157 if (entry->action == ACPI_EINJ_SET_ERROR_TYPE &&
158 entry->instruction == ACPI_EINJ_WRITE_REGISTER &&
159 entry->register_region.space_id ==
160 ACPI_ADR_SPACE_SYSTEM_MEMORY)
161 memcpy(&paddr, &entry->register_region.address,
162 sizeof(paddr));
163 entry++;
164 }
165
166 return paddr;
167}
168
169/* do sanity check to trigger table */
170static int einj_check_trigger_header(struct acpi_einj_trigger *trigger_tab)
171{
172 if (trigger_tab->header_size != sizeof(struct acpi_einj_trigger))
173 return -EINVAL;
174 if (trigger_tab->table_size > PAGE_SIZE ||
175 trigger_tab->table_size <= trigger_tab->header_size)
176 return -EINVAL;
177 if (trigger_tab->entry_count !=
178 (trigger_tab->table_size - trigger_tab->header_size) /
179 sizeof(struct acpi_einj_entry))
180 return -EINVAL;
181
182 return 0;
183}
184
185/* Execute instructions in trigger error action table */
186static int __einj_error_trigger(u64 trigger_paddr)
187{
188 struct acpi_einj_trigger *trigger_tab = NULL;
189 struct apei_exec_context trigger_ctx;
190 struct apei_resources trigger_resources;
191 struct acpi_whea_header *trigger_entry;
192 struct resource *r;
193 u32 table_size;
194 int rc = -EIO;
195
196 r = request_mem_region(trigger_paddr, sizeof(*trigger_tab),
197 "APEI EINJ Trigger Table");
198 if (!r) {
199 pr_err(EINJ_PFX
200 "Can not request iomem region <%016llx-%016llx> for Trigger table.\n",
201 (unsigned long long)trigger_paddr,
202 (unsigned long long)trigger_paddr+sizeof(*trigger_tab));
203 goto out;
204 }
205 trigger_tab = ioremap_cache(trigger_paddr, sizeof(*trigger_tab));
206 if (!trigger_tab) {
207 pr_err(EINJ_PFX "Failed to map trigger table!\n");
208 goto out_rel_header;
209 }
210 rc = einj_check_trigger_header(trigger_tab);
211 if (rc) {
212 pr_warning(FW_BUG EINJ_PFX
213 "The trigger error action table is invalid\n");
214 goto out_rel_header;
215 }
216 rc = -EIO;
217 table_size = trigger_tab->table_size;
218 r = request_mem_region(trigger_paddr + sizeof(*trigger_tab),
219 table_size - sizeof(*trigger_tab),
220 "APEI EINJ Trigger Table");
221 if (!r) {
222 pr_err(EINJ_PFX
223"Can not request iomem region <%016llx-%016llx> for Trigger Table Entry.\n",
224 (unsigned long long)trigger_paddr+sizeof(*trigger_tab),
225 (unsigned long long)trigger_paddr + table_size);
226 goto out_rel_header;
227 }
228 iounmap(trigger_tab);
229 trigger_tab = ioremap_cache(trigger_paddr, table_size);
230 if (!trigger_tab) {
231 pr_err(EINJ_PFX "Failed to map trigger table!\n");
232 goto out_rel_entry;
233 }
234 trigger_entry = (struct acpi_whea_header *)
235 ((char *)trigger_tab + sizeof(struct acpi_einj_trigger));
236 apei_resources_init(&trigger_resources);
237 apei_exec_ctx_init(&trigger_ctx, einj_ins_type,
238 ARRAY_SIZE(einj_ins_type),
239 trigger_entry, trigger_tab->entry_count);
240 rc = apei_exec_collect_resources(&trigger_ctx, &trigger_resources);
241 if (rc)
242 goto out_fini;
243 rc = apei_resources_sub(&trigger_resources, &einj_resources);
244 if (rc)
245 goto out_fini;
246 rc = apei_resources_request(&trigger_resources, "APEI EINJ Trigger");
247 if (rc)
248 goto out_fini;
249 rc = apei_exec_pre_map_gars(&trigger_ctx);
250 if (rc)
251 goto out_release;
252
253 rc = apei_exec_run(&trigger_ctx, ACPI_EINJ_TRIGGER_ERROR);
254
255 apei_exec_post_unmap_gars(&trigger_ctx);
256out_release:
257 apei_resources_release(&trigger_resources);
258out_fini:
259 apei_resources_fini(&trigger_resources);
260out_rel_entry:
261 release_mem_region(trigger_paddr + sizeof(*trigger_tab),
262 table_size - sizeof(*trigger_tab));
263out_rel_header:
264 release_mem_region(trigger_paddr, sizeof(*trigger_tab));
265out:
266 if (trigger_tab)
267 iounmap(trigger_tab);
268
269 return rc;
270}
271
272static int __einj_error_inject(u32 type, u64 param1, u64 param2)
273{
274 struct apei_exec_context ctx;
275 u64 val, trigger_paddr, timeout = FIRMWARE_TIMEOUT;
276 int rc;
277
278 einj_exec_ctx_init(&ctx);
279
280 rc = apei_exec_run(&ctx, ACPI_EINJ_BEGIN_OPERATION);
281 if (rc)
282 return rc;
283 apei_exec_ctx_set_input(&ctx, type);
284 rc = apei_exec_run(&ctx, ACPI_EINJ_SET_ERROR_TYPE);
285 if (rc)
286 return rc;
287 if (einj_param) {
288 writeq(param1, &einj_param->param1);
289 writeq(param2, &einj_param->param2);
290 }
291 rc = apei_exec_run(&ctx, ACPI_EINJ_EXECUTE_OPERATION);
292 if (rc)
293 return rc;
294 for (;;) {
295 rc = apei_exec_run(&ctx, ACPI_EINJ_CHECK_BUSY_STATUS);
296 if (rc)
297 return rc;
298 val = apei_exec_ctx_get_output(&ctx);
299 if (!(val & EINJ_OP_BUSY))
300 break;
301 if (einj_timedout(&timeout))
302 return -EIO;
303 }
304 rc = apei_exec_run(&ctx, ACPI_EINJ_GET_COMMAND_STATUS);
305 if (rc)
306 return rc;
307 val = apei_exec_ctx_get_output(&ctx);
308 if (val != EINJ_STATUS_SUCCESS)
309 return -EBUSY;
310
311 rc = apei_exec_run(&ctx, ACPI_EINJ_GET_TRIGGER_TABLE);
312 if (rc)
313 return rc;
314 trigger_paddr = apei_exec_ctx_get_output(&ctx);
315 rc = __einj_error_trigger(trigger_paddr);
316 if (rc)
317 return rc;
318 rc = apei_exec_run(&ctx, ACPI_EINJ_END_OPERATION);
319
320 return rc;
321}
322
323/* Inject the specified hardware error */
324static int einj_error_inject(u32 type, u64 param1, u64 param2)
325{
326 int rc;
327
328 mutex_lock(&einj_mutex);
329 rc = __einj_error_inject(type, param1, param2);
330 mutex_unlock(&einj_mutex);
331
332 return rc;
333}
334
335static u32 error_type;
336static u64 error_param1;
337static u64 error_param2;
338static struct dentry *einj_debug_dir;
339
340static int available_error_type_show(struct seq_file *m, void *v)
341{
342 int rc;
343 u32 available_error_type = 0;
344
345 rc = einj_get_available_error_type(&available_error_type);
346 if (rc)
347 return rc;
348 if (available_error_type & 0x0001)
349 seq_printf(m, "0x00000001\tProcessor Correctable\n");
350 if (available_error_type & 0x0002)
351 seq_printf(m, "0x00000002\tProcessor Uncorrectable non-fatal\n");
352 if (available_error_type & 0x0004)
353 seq_printf(m, "0x00000004\tProcessor Uncorrectable fatal\n");
354 if (available_error_type & 0x0008)
355 seq_printf(m, "0x00000008\tMemory Correctable\n");
356 if (available_error_type & 0x0010)
357 seq_printf(m, "0x00000010\tMemory Uncorrectable non-fatal\n");
358 if (available_error_type & 0x0020)
359 seq_printf(m, "0x00000020\tMemory Uncorrectable fatal\n");
360 if (available_error_type & 0x0040)
361 seq_printf(m, "0x00000040\tPCI Express Correctable\n");
362 if (available_error_type & 0x0080)
363 seq_printf(m, "0x00000080\tPCI Express Uncorrectable non-fatal\n");
364 if (available_error_type & 0x0100)
365 seq_printf(m, "0x00000100\tPCI Express Uncorrectable fatal\n");
366 if (available_error_type & 0x0200)
367 seq_printf(m, "0x00000200\tPlatform Correctable\n");
368 if (available_error_type & 0x0400)
369 seq_printf(m, "0x00000400\tPlatform Uncorrectable non-fatal\n");
370 if (available_error_type & 0x0800)
371 seq_printf(m, "0x00000800\tPlatform Uncorrectable fatal\n");
372
373 return 0;
374}
375
376static int available_error_type_open(struct inode *inode, struct file *file)
377{
378 return single_open(file, available_error_type_show, NULL);
379}
380
381static const struct file_operations available_error_type_fops = {
382 .open = available_error_type_open,
383 .read = seq_read,
384 .llseek = seq_lseek,
385 .release = single_release,
386};
387
388static int error_type_get(void *data, u64 *val)
389{
390 *val = error_type;
391
392 return 0;
393}
394
395static int error_type_set(void *data, u64 val)
396{
397 int rc;
398 u32 available_error_type = 0;
399
400 /* Only one error type can be specified */
401 if (val & (val - 1))
402 return -EINVAL;
403 rc = einj_get_available_error_type(&available_error_type);
404 if (rc)
405 return rc;
406 if (!(val & available_error_type))
407 return -EINVAL;
408 error_type = val;
409
410 return 0;
411}
412
413DEFINE_SIMPLE_ATTRIBUTE(error_type_fops, error_type_get,
414 error_type_set, "0x%llx\n");
415
416static int error_inject_set(void *data, u64 val)
417{
418 if (!error_type)
419 return -EINVAL;
420
421 return einj_error_inject(error_type, error_param1, error_param2);
422}
423
424DEFINE_SIMPLE_ATTRIBUTE(error_inject_fops, NULL,
425 error_inject_set, "%llu\n");
426
427static int einj_check_table(struct acpi_table_einj *einj_tab)
428{
429 if (einj_tab->header_length != sizeof(struct acpi_table_einj))
430 return -EINVAL;
431 if (einj_tab->header.length < sizeof(struct acpi_table_einj))
432 return -EINVAL;
433 if (einj_tab->entries !=
434 (einj_tab->header.length - sizeof(struct acpi_table_einj)) /
435 sizeof(struct acpi_einj_entry))
436 return -EINVAL;
437
438 return 0;
439}
440
441static int __init einj_init(void)
442{
443 int rc;
444 u64 param_paddr;
445 acpi_status status;
446 struct dentry *fentry;
447 struct apei_exec_context ctx;
448
449 if (acpi_disabled)
450 return -ENODEV;
451
452 status = acpi_get_table(ACPI_SIG_EINJ, 0,
453 (struct acpi_table_header **)&einj_tab);
454 if (status == AE_NOT_FOUND) {
455 pr_info(EINJ_PFX "Table is not found!\n");
456 return -ENODEV;
457 } else if (ACPI_FAILURE(status)) {
458 const char *msg = acpi_format_exception(status);
459 pr_err(EINJ_PFX "Failed to get table, %s\n", msg);
460 return -EINVAL;
461 }
462
463 rc = einj_check_table(einj_tab);
464 if (rc) {
465 pr_warning(FW_BUG EINJ_PFX "EINJ table is invalid\n");
466 return -EINVAL;
467 }
468
469 rc = -ENOMEM;
470 einj_debug_dir = debugfs_create_dir("einj", apei_get_debugfs_dir());
471 if (!einj_debug_dir)
472 goto err_cleanup;
473 fentry = debugfs_create_file("available_error_type", S_IRUSR,
474 einj_debug_dir, NULL,
475 &available_error_type_fops);
476 if (!fentry)
477 goto err_cleanup;
478 fentry = debugfs_create_file("error_type", S_IRUSR | S_IWUSR,
479 einj_debug_dir, NULL, &error_type_fops);
480 if (!fentry)
481 goto err_cleanup;
482 fentry = debugfs_create_x64("param1", S_IRUSR | S_IWUSR,
483 einj_debug_dir, &error_param1);
484 if (!fentry)
485 goto err_cleanup;
486 fentry = debugfs_create_x64("param2", S_IRUSR | S_IWUSR,
487 einj_debug_dir, &error_param2);
488 if (!fentry)
489 goto err_cleanup;
490 fentry = debugfs_create_file("error_inject", S_IWUSR,
491 einj_debug_dir, NULL, &error_inject_fops);
492 if (!fentry)
493 goto err_cleanup;
494
495 apei_resources_init(&einj_resources);
496 einj_exec_ctx_init(&ctx);
497 rc = apei_exec_collect_resources(&ctx, &einj_resources);
498 if (rc)
499 goto err_fini;
500 rc = apei_resources_request(&einj_resources, "APEI EINJ");
501 if (rc)
502 goto err_fini;
503 rc = apei_exec_pre_map_gars(&ctx);
504 if (rc)
505 goto err_release;
506 param_paddr = einj_get_parameter_address();
507 if (param_paddr) {
508 einj_param = ioremap(param_paddr, sizeof(*einj_param));
509 rc = -ENOMEM;
510 if (!einj_param)
511 goto err_unmap;
512 }
513
514 pr_info(EINJ_PFX "Error INJection is initialized.\n");
515
516 return 0;
517
518err_unmap:
519 apei_exec_post_unmap_gars(&ctx);
520err_release:
521 apei_resources_release(&einj_resources);
522err_fini:
523 apei_resources_fini(&einj_resources);
524err_cleanup:
525 debugfs_remove_recursive(einj_debug_dir);
526
527 return rc;
528}
529
530static void __exit einj_exit(void)
531{
532 struct apei_exec_context ctx;
533
534 if (einj_param)
535 iounmap(einj_param);
536 einj_exec_ctx_init(&ctx);
537 apei_exec_post_unmap_gars(&ctx);
538 apei_resources_release(&einj_resources);
539 apei_resources_fini(&einj_resources);
540 debugfs_remove_recursive(einj_debug_dir);
541}
542
543module_init(einj_init);
544module_exit(einj_exit);
545
546MODULE_AUTHOR("Huang Ying");
547MODULE_DESCRIPTION("APEI Error INJection support");
548MODULE_LICENSE("GPL");
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c
new file mode 100644
index 000000000000..2ebc39115507
--- /dev/null
+++ b/drivers/acpi/apei/erst.c
@@ -0,0 +1,855 @@
1/*
2 * APEI Error Record Serialization Table support
3 *
4 * ERST is a way provided by APEI to save and retrieve hardware error
5 * infomation to and from a persistent store.
6 *
7 * For more information about ERST, please refer to ACPI Specification
8 * version 4.0, section 17.4.
9 *
10 * Copyright 2010 Intel Corp.
11 * Author: Huang Ying <ying.huang@intel.com>
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License version
15 * 2 as published by the Free Software Foundation.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 */
26
27#include <linux/kernel.h>
28#include <linux/module.h>
29#include <linux/init.h>
30#include <linux/delay.h>
31#include <linux/io.h>
32#include <linux/acpi.h>
33#include <linux/uaccess.h>
34#include <linux/cper.h>
35#include <linux/nmi.h>
36#include <acpi/apei.h>
37
38#include "apei-internal.h"
39
40#define ERST_PFX "ERST: "
41
42/* ERST command status */
43#define ERST_STATUS_SUCCESS 0x0
44#define ERST_STATUS_NOT_ENOUGH_SPACE 0x1
45#define ERST_STATUS_HARDWARE_NOT_AVAILABLE 0x2
46#define ERST_STATUS_FAILED 0x3
47#define ERST_STATUS_RECORD_STORE_EMPTY 0x4
48#define ERST_STATUS_RECORD_NOT_FOUND 0x5
49
50#define ERST_TAB_ENTRY(tab) \
51 ((struct acpi_whea_header *)((char *)(tab) + \
52 sizeof(struct acpi_table_erst)))
53
54#define SPIN_UNIT 100 /* 100ns */
55/* Firmware should respond within 1 miliseconds */
56#define FIRMWARE_TIMEOUT (1 * NSEC_PER_MSEC)
57#define FIRMWARE_MAX_STALL 50 /* 50us */
58
59int erst_disable;
60EXPORT_SYMBOL_GPL(erst_disable);
61
62static struct acpi_table_erst *erst_tab;
63
64/* ERST Error Log Address Range atrributes */
65#define ERST_RANGE_RESERVED 0x0001
66#define ERST_RANGE_NVRAM 0x0002
67#define ERST_RANGE_SLOW 0x0004
68
69/*
70 * ERST Error Log Address Range, used as buffer for reading/writing
71 * error records.
72 */
73static struct erst_erange {
74 u64 base;
75 u64 size;
76 void __iomem *vaddr;
77 u32 attr;
78} erst_erange;
79
80/*
81 * Prevent ERST interpreter to run simultaneously, because the
82 * corresponding firmware implementation may not work properly when
83 * invoked simultaneously.
84 *
85 * It is used to provide exclusive accessing for ERST Error Log
86 * Address Range too.
87 */
88static DEFINE_SPINLOCK(erst_lock);
89
90static inline int erst_errno(int command_status)
91{
92 switch (command_status) {
93 case ERST_STATUS_SUCCESS:
94 return 0;
95 case ERST_STATUS_HARDWARE_NOT_AVAILABLE:
96 return -ENODEV;
97 case ERST_STATUS_NOT_ENOUGH_SPACE:
98 return -ENOSPC;
99 case ERST_STATUS_RECORD_STORE_EMPTY:
100 case ERST_STATUS_RECORD_NOT_FOUND:
101 return -ENOENT;
102 default:
103 return -EINVAL;
104 }
105}
106
107static int erst_timedout(u64 *t, u64 spin_unit)
108{
109 if ((s64)*t < spin_unit) {
110 pr_warning(FW_WARN ERST_PFX
111 "Firmware does not respond in time\n");
112 return 1;
113 }
114 *t -= spin_unit;
115 ndelay(spin_unit);
116 touch_nmi_watchdog();
117 return 0;
118}
119
120static int erst_exec_load_var1(struct apei_exec_context *ctx,
121 struct acpi_whea_header *entry)
122{
123 return __apei_exec_read_register(entry, &ctx->var1);
124}
125
126static int erst_exec_load_var2(struct apei_exec_context *ctx,
127 struct acpi_whea_header *entry)
128{
129 return __apei_exec_read_register(entry, &ctx->var2);
130}
131
132static int erst_exec_store_var1(struct apei_exec_context *ctx,
133 struct acpi_whea_header *entry)
134{
135 return __apei_exec_write_register(entry, ctx->var1);
136}
137
138static int erst_exec_add(struct apei_exec_context *ctx,
139 struct acpi_whea_header *entry)
140{
141 ctx->var1 += ctx->var2;
142 return 0;
143}
144
145static int erst_exec_subtract(struct apei_exec_context *ctx,
146 struct acpi_whea_header *entry)
147{
148 ctx->var1 -= ctx->var2;
149 return 0;
150}
151
152static int erst_exec_add_value(struct apei_exec_context *ctx,
153 struct acpi_whea_header *entry)
154{
155 int rc;
156 u64 val;
157
158 rc = __apei_exec_read_register(entry, &val);
159 if (rc)
160 return rc;
161 val += ctx->value;
162 rc = __apei_exec_write_register(entry, val);
163 return rc;
164}
165
166static int erst_exec_subtract_value(struct apei_exec_context *ctx,
167 struct acpi_whea_header *entry)
168{
169 int rc;
170 u64 val;
171
172 rc = __apei_exec_read_register(entry, &val);
173 if (rc)
174 return rc;
175 val -= ctx->value;
176 rc = __apei_exec_write_register(entry, val);
177 return rc;
178}
179
180static int erst_exec_stall(struct apei_exec_context *ctx,
181 struct acpi_whea_header *entry)
182{
183 u64 stall_time;
184
185 if (ctx->value > FIRMWARE_MAX_STALL) {
186 if (!in_nmi())
187 pr_warning(FW_WARN ERST_PFX
188 "Too long stall time for stall instruction: %llx.\n",
189 ctx->value);
190 stall_time = FIRMWARE_MAX_STALL;
191 } else
192 stall_time = ctx->value;
193 udelay(stall_time);
194 return 0;
195}
196
197static int erst_exec_stall_while_true(struct apei_exec_context *ctx,
198 struct acpi_whea_header *entry)
199{
200 int rc;
201 u64 val;
202 u64 timeout = FIRMWARE_TIMEOUT;
203 u64 stall_time;
204
205 if (ctx->var1 > FIRMWARE_MAX_STALL) {
206 if (!in_nmi())
207 pr_warning(FW_WARN ERST_PFX
208 "Too long stall time for stall while true instruction: %llx.\n",
209 ctx->var1);
210 stall_time = FIRMWARE_MAX_STALL;
211 } else
212 stall_time = ctx->var1;
213
214 for (;;) {
215 rc = __apei_exec_read_register(entry, &val);
216 if (rc)
217 return rc;
218 if (val != ctx->value)
219 break;
220 if (erst_timedout(&timeout, stall_time * NSEC_PER_USEC))
221 return -EIO;
222 }
223 return 0;
224}
225
226static int erst_exec_skip_next_instruction_if_true(
227 struct apei_exec_context *ctx,
228 struct acpi_whea_header *entry)
229{
230 int rc;
231 u64 val;
232
233 rc = __apei_exec_read_register(entry, &val);
234 if (rc)
235 return rc;
236 if (val == ctx->value) {
237 ctx->ip += 2;
238 return APEI_EXEC_SET_IP;
239 }
240
241 return 0;
242}
243
244static int erst_exec_goto(struct apei_exec_context *ctx,
245 struct acpi_whea_header *entry)
246{
247 ctx->ip = ctx->value;
248 return APEI_EXEC_SET_IP;
249}
250
251static int erst_exec_set_src_address_base(struct apei_exec_context *ctx,
252 struct acpi_whea_header *entry)
253{
254 return __apei_exec_read_register(entry, &ctx->src_base);
255}
256
257static int erst_exec_set_dst_address_base(struct apei_exec_context *ctx,
258 struct acpi_whea_header *entry)
259{
260 return __apei_exec_read_register(entry, &ctx->dst_base);
261}
262
263static int erst_exec_move_data(struct apei_exec_context *ctx,
264 struct acpi_whea_header *entry)
265{
266 int rc;
267 u64 offset;
268
269 rc = __apei_exec_read_register(entry, &offset);
270 if (rc)
271 return rc;
272 memmove((void *)ctx->dst_base + offset,
273 (void *)ctx->src_base + offset,
274 ctx->var2);
275
276 return 0;
277}
278
279static struct apei_exec_ins_type erst_ins_type[] = {
280 [ACPI_ERST_READ_REGISTER] = {
281 .flags = APEI_EXEC_INS_ACCESS_REGISTER,
282 .run = apei_exec_read_register,
283 },
284 [ACPI_ERST_READ_REGISTER_VALUE] = {
285 .flags = APEI_EXEC_INS_ACCESS_REGISTER,
286 .run = apei_exec_read_register_value,
287 },
288 [ACPI_ERST_WRITE_REGISTER] = {
289 .flags = APEI_EXEC_INS_ACCESS_REGISTER,
290 .run = apei_exec_write_register,
291 },
292 [ACPI_ERST_WRITE_REGISTER_VALUE] = {
293 .flags = APEI_EXEC_INS_ACCESS_REGISTER,
294 .run = apei_exec_write_register_value,
295 },
296 [ACPI_ERST_NOOP] = {
297 .flags = 0,
298 .run = apei_exec_noop,
299 },
300 [ACPI_ERST_LOAD_VAR1] = {
301 .flags = APEI_EXEC_INS_ACCESS_REGISTER,
302 .run = erst_exec_load_var1,
303 },
304 [ACPI_ERST_LOAD_VAR2] = {
305 .flags = APEI_EXEC_INS_ACCESS_REGISTER,
306 .run = erst_exec_load_var2,
307 },
308 [ACPI_ERST_STORE_VAR1] = {
309 .flags = APEI_EXEC_INS_ACCESS_REGISTER,
310 .run = erst_exec_store_var1,
311 },
312 [ACPI_ERST_ADD] = {
313 .flags = 0,
314 .run = erst_exec_add,
315 },
316 [ACPI_ERST_SUBTRACT] = {
317 .flags = 0,
318 .run = erst_exec_subtract,
319 },
320 [ACPI_ERST_ADD_VALUE] = {
321 .flags = APEI_EXEC_INS_ACCESS_REGISTER,
322 .run = erst_exec_add_value,
323 },
324 [ACPI_ERST_SUBTRACT_VALUE] = {
325 .flags = APEI_EXEC_INS_ACCESS_REGISTER,
326 .run = erst_exec_subtract_value,
327 },
328 [ACPI_ERST_STALL] = {
329 .flags = 0,
330 .run = erst_exec_stall,
331 },
332 [ACPI_ERST_STALL_WHILE_TRUE] = {
333 .flags = APEI_EXEC_INS_ACCESS_REGISTER,
334 .run = erst_exec_stall_while_true,
335 },
336 [ACPI_ERST_SKIP_NEXT_IF_TRUE] = {
337 .flags = APEI_EXEC_INS_ACCESS_REGISTER,
338 .run = erst_exec_skip_next_instruction_if_true,
339 },
340 [ACPI_ERST_GOTO] = {
341 .flags = 0,
342 .run = erst_exec_goto,
343 },
344 [ACPI_ERST_SET_SRC_ADDRESS_BASE] = {
345 .flags = APEI_EXEC_INS_ACCESS_REGISTER,
346 .run = erst_exec_set_src_address_base,
347 },
348 [ACPI_ERST_SET_DST_ADDRESS_BASE] = {
349 .flags = APEI_EXEC_INS_ACCESS_REGISTER,
350 .run = erst_exec_set_dst_address_base,
351 },
352 [ACPI_ERST_MOVE_DATA] = {
353 .flags = APEI_EXEC_INS_ACCESS_REGISTER,
354 .run = erst_exec_move_data,
355 },
356};
357
358static inline void erst_exec_ctx_init(struct apei_exec_context *ctx)
359{
360 apei_exec_ctx_init(ctx, erst_ins_type, ARRAY_SIZE(erst_ins_type),
361 ERST_TAB_ENTRY(erst_tab), erst_tab->entries);
362}
363
364static int erst_get_erange(struct erst_erange *range)
365{
366 struct apei_exec_context ctx;
367 int rc;
368
369 erst_exec_ctx_init(&ctx);
370 rc = apei_exec_run(&ctx, ACPI_ERST_GET_ERROR_RANGE);
371 if (rc)
372 return rc;
373 range->base = apei_exec_ctx_get_output(&ctx);
374 rc = apei_exec_run(&ctx, ACPI_ERST_GET_ERROR_LENGTH);
375 if (rc)
376 return rc;
377 range->size = apei_exec_ctx_get_output(&ctx);
378 rc = apei_exec_run(&ctx, ACPI_ERST_GET_ERROR_ATTRIBUTES);
379 if (rc)
380 return rc;
381 range->attr = apei_exec_ctx_get_output(&ctx);
382
383 return 0;
384}
385
386static ssize_t __erst_get_record_count(void)
387{
388 struct apei_exec_context ctx;
389 int rc;
390
391 erst_exec_ctx_init(&ctx);
392 rc = apei_exec_run(&ctx, ACPI_ERST_GET_RECORD_COUNT);
393 if (rc)
394 return rc;
395 return apei_exec_ctx_get_output(&ctx);
396}
397
398ssize_t erst_get_record_count(void)
399{
400 ssize_t count;
401 unsigned long flags;
402
403 if (erst_disable)
404 return -ENODEV;
405
406 spin_lock_irqsave(&erst_lock, flags);
407 count = __erst_get_record_count();
408 spin_unlock_irqrestore(&erst_lock, flags);
409
410 return count;
411}
412EXPORT_SYMBOL_GPL(erst_get_record_count);
413
414static int __erst_get_next_record_id(u64 *record_id)
415{
416 struct apei_exec_context ctx;
417 int rc;
418
419 erst_exec_ctx_init(&ctx);
420 rc = apei_exec_run(&ctx, ACPI_ERST_GET_RECORD_ID);
421 if (rc)
422 return rc;
423 *record_id = apei_exec_ctx_get_output(&ctx);
424
425 return 0;
426}
427
428/*
429 * Get the record ID of an existing error record on the persistent
430 * storage. If there is no error record on the persistent storage, the
431 * returned record_id is APEI_ERST_INVALID_RECORD_ID.
432 */
433int erst_get_next_record_id(u64 *record_id)
434{
435 int rc;
436 unsigned long flags;
437
438 if (erst_disable)
439 return -ENODEV;
440
441 spin_lock_irqsave(&erst_lock, flags);
442 rc = __erst_get_next_record_id(record_id);
443 spin_unlock_irqrestore(&erst_lock, flags);
444
445 return rc;
446}
447EXPORT_SYMBOL_GPL(erst_get_next_record_id);
448
449static int __erst_write_to_storage(u64 offset)
450{
451 struct apei_exec_context ctx;
452 u64 timeout = FIRMWARE_TIMEOUT;
453 u64 val;
454 int rc;
455
456 erst_exec_ctx_init(&ctx);
457 rc = apei_exec_run(&ctx, ACPI_ERST_BEGIN_WRITE);
458 if (rc)
459 return rc;
460 apei_exec_ctx_set_input(&ctx, offset);
461 rc = apei_exec_run(&ctx, ACPI_ERST_SET_RECORD_OFFSET);
462 if (rc)
463 return rc;
464 rc = apei_exec_run(&ctx, ACPI_ERST_EXECUTE_OPERATION);
465 if (rc)
466 return rc;
467 for (;;) {
468 rc = apei_exec_run(&ctx, ACPI_ERST_CHECK_BUSY_STATUS);
469 if (rc)
470 return rc;
471 val = apei_exec_ctx_get_output(&ctx);
472 if (!val)
473 break;
474 if (erst_timedout(&timeout, SPIN_UNIT))
475 return -EIO;
476 }
477 rc = apei_exec_run(&ctx, ACPI_ERST_GET_COMMAND_STATUS);
478 if (rc)
479 return rc;
480 val = apei_exec_ctx_get_output(&ctx);
481 rc = apei_exec_run(&ctx, ACPI_ERST_END);
482 if (rc)
483 return rc;
484
485 return erst_errno(val);
486}
487
488static int __erst_read_from_storage(u64 record_id, u64 offset)
489{
490 struct apei_exec_context ctx;
491 u64 timeout = FIRMWARE_TIMEOUT;
492 u64 val;
493 int rc;
494
495 erst_exec_ctx_init(&ctx);
496 rc = apei_exec_run(&ctx, ACPI_ERST_BEGIN_READ);
497 if (rc)
498 return rc;
499 apei_exec_ctx_set_input(&ctx, offset);
500 rc = apei_exec_run(&ctx, ACPI_ERST_SET_RECORD_OFFSET);
501 if (rc)
502 return rc;
503 apei_exec_ctx_set_input(&ctx, record_id);
504 rc = apei_exec_run(&ctx, ACPI_ERST_SET_RECORD_ID);
505 if (rc)
506 return rc;
507 rc = apei_exec_run(&ctx, ACPI_ERST_EXECUTE_OPERATION);
508 if (rc)
509 return rc;
510 for (;;) {
511 rc = apei_exec_run(&ctx, ACPI_ERST_CHECK_BUSY_STATUS);
512 if (rc)
513 return rc;
514 val = apei_exec_ctx_get_output(&ctx);
515 if (!val)
516 break;
517 if (erst_timedout(&timeout, SPIN_UNIT))
518 return -EIO;
519 };
520 rc = apei_exec_run(&ctx, ACPI_ERST_GET_COMMAND_STATUS);
521 if (rc)
522 return rc;
523 val = apei_exec_ctx_get_output(&ctx);
524 rc = apei_exec_run(&ctx, ACPI_ERST_END);
525 if (rc)
526 return rc;
527
528 return erst_errno(val);
529}
530
531static int __erst_clear_from_storage(u64 record_id)
532{
533 struct apei_exec_context ctx;
534 u64 timeout = FIRMWARE_TIMEOUT;
535 u64 val;
536 int rc;
537
538 erst_exec_ctx_init(&ctx);
539 rc = apei_exec_run(&ctx, ACPI_ERST_BEGIN_CLEAR);
540 if (rc)
541 return rc;
542 apei_exec_ctx_set_input(&ctx, record_id);
543 rc = apei_exec_run(&ctx, ACPI_ERST_SET_RECORD_ID);
544 if (rc)
545 return rc;
546 rc = apei_exec_run(&ctx, ACPI_ERST_EXECUTE_OPERATION);
547 if (rc)
548 return rc;
549 for (;;) {
550 rc = apei_exec_run(&ctx, ACPI_ERST_CHECK_BUSY_STATUS);
551 if (rc)
552 return rc;
553 val = apei_exec_ctx_get_output(&ctx);
554 if (!val)
555 break;
556 if (erst_timedout(&timeout, SPIN_UNIT))
557 return -EIO;
558 }
559 rc = apei_exec_run(&ctx, ACPI_ERST_GET_COMMAND_STATUS);
560 if (rc)
561 return rc;
562 val = apei_exec_ctx_get_output(&ctx);
563 rc = apei_exec_run(&ctx, ACPI_ERST_END);
564 if (rc)
565 return rc;
566
567 return erst_errno(val);
568}
569
570/* NVRAM ERST Error Log Address Range is not supported yet */
571static void pr_unimpl_nvram(void)
572{
573 if (printk_ratelimit())
574 pr_warning(ERST_PFX
575 "NVRAM ERST Log Address Range is not implemented yet\n");
576}
577
578static int __erst_write_to_nvram(const struct cper_record_header *record)
579{
580 /* do not print message, because printk is not safe for NMI */
581 return -ENOSYS;
582}
583
584static int __erst_read_to_erange_from_nvram(u64 record_id, u64 *offset)
585{
586 pr_unimpl_nvram();
587 return -ENOSYS;
588}
589
590static int __erst_clear_from_nvram(u64 record_id)
591{
592 pr_unimpl_nvram();
593 return -ENOSYS;
594}
595
596int erst_write(const struct cper_record_header *record)
597{
598 int rc;
599 unsigned long flags;
600 struct cper_record_header *rcd_erange;
601
602 if (erst_disable)
603 return -ENODEV;
604
605 if (memcmp(record->signature, CPER_SIG_RECORD, CPER_SIG_SIZE))
606 return -EINVAL;
607
608 if (erst_erange.attr & ERST_RANGE_NVRAM) {
609 if (!spin_trylock_irqsave(&erst_lock, flags))
610 return -EBUSY;
611 rc = __erst_write_to_nvram(record);
612 spin_unlock_irqrestore(&erst_lock, flags);
613 return rc;
614 }
615
616 if (record->record_length > erst_erange.size)
617 return -EINVAL;
618
619 if (!spin_trylock_irqsave(&erst_lock, flags))
620 return -EBUSY;
621 memcpy(erst_erange.vaddr, record, record->record_length);
622 rcd_erange = erst_erange.vaddr;
623 /* signature for serialization system */
624 memcpy(&rcd_erange->persistence_information, "ER", 2);
625
626 rc = __erst_write_to_storage(0);
627 spin_unlock_irqrestore(&erst_lock, flags);
628
629 return rc;
630}
631EXPORT_SYMBOL_GPL(erst_write);
632
633static int __erst_read_to_erange(u64 record_id, u64 *offset)
634{
635 int rc;
636
637 if (erst_erange.attr & ERST_RANGE_NVRAM)
638 return __erst_read_to_erange_from_nvram(
639 record_id, offset);
640
641 rc = __erst_read_from_storage(record_id, 0);
642 if (rc)
643 return rc;
644 *offset = 0;
645
646 return 0;
647}
648
649static ssize_t __erst_read(u64 record_id, struct cper_record_header *record,
650 size_t buflen)
651{
652 int rc;
653 u64 offset, len = 0;
654 struct cper_record_header *rcd_tmp;
655
656 rc = __erst_read_to_erange(record_id, &offset);
657 if (rc)
658 return rc;
659 rcd_tmp = erst_erange.vaddr + offset;
660 len = rcd_tmp->record_length;
661 if (len <= buflen)
662 memcpy(record, rcd_tmp, len);
663
664 return len;
665}
666
667/*
668 * If return value > buflen, the buffer size is not big enough,
669 * else if return value < 0, something goes wrong,
670 * else everything is OK, and return value is record length
671 */
672ssize_t erst_read(u64 record_id, struct cper_record_header *record,
673 size_t buflen)
674{
675 ssize_t len;
676 unsigned long flags;
677
678 if (erst_disable)
679 return -ENODEV;
680
681 spin_lock_irqsave(&erst_lock, flags);
682 len = __erst_read(record_id, record, buflen);
683 spin_unlock_irqrestore(&erst_lock, flags);
684 return len;
685}
686EXPORT_SYMBOL_GPL(erst_read);
687
688/*
689 * If return value > buflen, the buffer size is not big enough,
690 * else if return value = 0, there is no more record to read,
691 * else if return value < 0, something goes wrong,
692 * else everything is OK, and return value is record length
693 */
694ssize_t erst_read_next(struct cper_record_header *record, size_t buflen)
695{
696 int rc;
697 ssize_t len;
698 unsigned long flags;
699 u64 record_id;
700
701 if (erst_disable)
702 return -ENODEV;
703
704 spin_lock_irqsave(&erst_lock, flags);
705 rc = __erst_get_next_record_id(&record_id);
706 if (rc) {
707 spin_unlock_irqrestore(&erst_lock, flags);
708 return rc;
709 }
710 /* no more record */
711 if (record_id == APEI_ERST_INVALID_RECORD_ID) {
712 spin_unlock_irqrestore(&erst_lock, flags);
713 return 0;
714 }
715
716 len = __erst_read(record_id, record, buflen);
717 spin_unlock_irqrestore(&erst_lock, flags);
718
719 return len;
720}
721EXPORT_SYMBOL_GPL(erst_read_next);
722
723int erst_clear(u64 record_id)
724{
725 int rc;
726 unsigned long flags;
727
728 if (erst_disable)
729 return -ENODEV;
730
731 spin_lock_irqsave(&erst_lock, flags);
732 if (erst_erange.attr & ERST_RANGE_NVRAM)
733 rc = __erst_clear_from_nvram(record_id);
734 else
735 rc = __erst_clear_from_storage(record_id);
736 spin_unlock_irqrestore(&erst_lock, flags);
737
738 return rc;
739}
740EXPORT_SYMBOL_GPL(erst_clear);
741
742static int __init setup_erst_disable(char *str)
743{
744 erst_disable = 1;
745 return 0;
746}
747
748__setup("erst_disable", setup_erst_disable);
749
750static int erst_check_table(struct acpi_table_erst *erst_tab)
751{
752 if (erst_tab->header_length != sizeof(struct acpi_table_erst))
753 return -EINVAL;
754 if (erst_tab->header.length < sizeof(struct acpi_table_erst))
755 return -EINVAL;
756 if (erst_tab->entries !=
757 (erst_tab->header.length - sizeof(struct acpi_table_erst)) /
758 sizeof(struct acpi_erst_entry))
759 return -EINVAL;
760
761 return 0;
762}
763
764static int __init erst_init(void)
765{
766 int rc = 0;
767 acpi_status status;
768 struct apei_exec_context ctx;
769 struct apei_resources erst_resources;
770 struct resource *r;
771
772 if (acpi_disabled)
773 goto err;
774
775 if (erst_disable) {
776 pr_info(ERST_PFX
777 "Error Record Serialization Table (ERST) support is disabled.\n");
778 goto err;
779 }
780
781 status = acpi_get_table(ACPI_SIG_ERST, 0,
782 (struct acpi_table_header **)&erst_tab);
783 if (status == AE_NOT_FOUND) {
784 pr_err(ERST_PFX "Table is not found!\n");
785 goto err;
786 } else if (ACPI_FAILURE(status)) {
787 const char *msg = acpi_format_exception(status);
788 pr_err(ERST_PFX "Failed to get table, %s\n", msg);
789 rc = -EINVAL;
790 goto err;
791 }
792
793 rc = erst_check_table(erst_tab);
794 if (rc) {
795 pr_err(FW_BUG ERST_PFX "ERST table is invalid\n");
796 goto err;
797 }
798
799 apei_resources_init(&erst_resources);
800 erst_exec_ctx_init(&ctx);
801 rc = apei_exec_collect_resources(&ctx, &erst_resources);
802 if (rc)
803 goto err_fini;
804 rc = apei_resources_request(&erst_resources, "APEI ERST");
805 if (rc)
806 goto err_fini;
807 rc = apei_exec_pre_map_gars(&ctx);
808 if (rc)
809 goto err_release;
810 rc = erst_get_erange(&erst_erange);
811 if (rc) {
812 if (rc == -ENODEV)
813 pr_info(ERST_PFX
814 "The corresponding hardware device or firmware implementation "
815 "is not available.\n");
816 else
817 pr_err(ERST_PFX
818 "Failed to get Error Log Address Range.\n");
819 goto err_unmap_reg;
820 }
821
822 r = request_mem_region(erst_erange.base, erst_erange.size, "APEI ERST");
823 if (!r) {
824 pr_err(ERST_PFX
825 "Can not request iomem region <0x%16llx-0x%16llx> for ERST.\n",
826 (unsigned long long)erst_erange.base,
827 (unsigned long long)erst_erange.base + erst_erange.size);
828 rc = -EIO;
829 goto err_unmap_reg;
830 }
831 rc = -ENOMEM;
832 erst_erange.vaddr = ioremap_cache(erst_erange.base,
833 erst_erange.size);
834 if (!erst_erange.vaddr)
835 goto err_release_erange;
836
837 pr_info(ERST_PFX
838 "Error Record Serialization Table (ERST) support is initialized.\n");
839
840 return 0;
841
842err_release_erange:
843 release_mem_region(erst_erange.base, erst_erange.size);
844err_unmap_reg:
845 apei_exec_post_unmap_gars(&ctx);
846err_release:
847 apei_resources_release(&erst_resources);
848err_fini:
849 apei_resources_fini(&erst_resources);
850err:
851 erst_disable = 1;
852 return rc;
853}
854
855device_initcall(erst_init);
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
new file mode 100644
index 000000000000..fd0cc016a099
--- /dev/null
+++ b/drivers/acpi/apei/ghes.c
@@ -0,0 +1,427 @@
1/*
2 * APEI Generic Hardware Error Source support
3 *
4 * Generic Hardware Error Source provides a way to report platform
5 * hardware errors (such as that from chipset). It works in so called
6 * "Firmware First" mode, that is, hardware errors are reported to
7 * firmware firstly, then reported to Linux by firmware. This way,
8 * some non-standard hardware error registers or non-standard hardware
9 * link can be checked by firmware to produce more hardware error
10 * information for Linux.
11 *
12 * For more information about Generic Hardware Error Source, please
13 * refer to ACPI Specification version 4.0, section 17.3.2.6
14 *
15 * Now, only SCI notification type and memory errors are
16 * supported. More notification type and hardware error type will be
17 * added later.
18 *
19 * Copyright 2010 Intel Corp.
20 * Author: Huang Ying <ying.huang@intel.com>
21 *
22 * This program is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU General Public License version
24 * 2 as published by the Free Software Foundation;
25 *
26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details.
30 *
31 * You should have received a copy of the GNU General Public License
32 * along with this program; if not, write to the Free Software
33 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
34 */
35
36#include <linux/kernel.h>
37#include <linux/module.h>
38#include <linux/init.h>
39#include <linux/acpi.h>
40#include <linux/io.h>
41#include <linux/interrupt.h>
42#include <linux/cper.h>
43#include <linux/kdebug.h>
44#include <acpi/apei.h>
45#include <acpi/atomicio.h>
46#include <acpi/hed.h>
47#include <asm/mce.h>
48
49#include "apei-internal.h"
50
51#define GHES_PFX "GHES: "
52
53#define GHES_ESTATUS_MAX_SIZE 65536
54
55/*
56 * One struct ghes is created for each generic hardware error
57 * source.
58 *
59 * It provides the context for APEI hardware error timer/IRQ/SCI/NMI
60 * handler. Handler for one generic hardware error source is only
61 * triggered after the previous one is done. So handler can uses
62 * struct ghes without locking.
63 *
64 * estatus: memory buffer for error status block, allocated during
65 * HEST parsing.
66 */
67#define GHES_TO_CLEAR 0x0001
68
69struct ghes {
70 struct acpi_hest_generic *generic;
71 struct acpi_hest_generic_status *estatus;
72 struct list_head list;
73 u64 buffer_paddr;
74 unsigned long flags;
75};
76
77/*
78 * Error source lists, one list for each notification method. The
79 * members in lists are struct ghes.
80 *
81 * The list members are only added in HEST parsing and deleted during
82 * module_exit, that is, single-threaded. So no lock is needed for
83 * that.
84 *
85 * But the mutual exclusion is needed between members adding/deleting
86 * and timer/IRQ/SCI/NMI handler, which may traverse the list. RCU is
87 * used for that.
88 */
89static LIST_HEAD(ghes_sci);
90
91static struct ghes *ghes_new(struct acpi_hest_generic *generic)
92{
93 struct ghes *ghes;
94 unsigned int error_block_length;
95 int rc;
96
97 ghes = kzalloc(sizeof(*ghes), GFP_KERNEL);
98 if (!ghes)
99 return ERR_PTR(-ENOMEM);
100 ghes->generic = generic;
101 INIT_LIST_HEAD(&ghes->list);
102 rc = acpi_pre_map_gar(&generic->error_status_address);
103 if (rc)
104 goto err_free;
105 error_block_length = generic->error_block_length;
106 if (error_block_length > GHES_ESTATUS_MAX_SIZE) {
107 pr_warning(FW_WARN GHES_PFX
108 "Error status block length is too long: %u for "
109 "generic hardware error source: %d.\n",
110 error_block_length, generic->header.source_id);
111 error_block_length = GHES_ESTATUS_MAX_SIZE;
112 }
113 ghes->estatus = kmalloc(error_block_length, GFP_KERNEL);
114 if (!ghes->estatus) {
115 rc = -ENOMEM;
116 goto err_unmap;
117 }
118
119 return ghes;
120
121err_unmap:
122 acpi_post_unmap_gar(&generic->error_status_address);
123err_free:
124 kfree(ghes);
125 return ERR_PTR(rc);
126}
127
128static void ghes_fini(struct ghes *ghes)
129{
130 kfree(ghes->estatus);
131 acpi_post_unmap_gar(&ghes->generic->error_status_address);
132}
133
134enum {
135 GHES_SER_NO = 0x0,
136 GHES_SER_CORRECTED = 0x1,
137 GHES_SER_RECOVERABLE = 0x2,
138 GHES_SER_PANIC = 0x3,
139};
140
141static inline int ghes_severity(int severity)
142{
143 switch (severity) {
144 case CPER_SER_INFORMATIONAL:
145 return GHES_SER_NO;
146 case CPER_SER_CORRECTED:
147 return GHES_SER_CORRECTED;
148 case CPER_SER_RECOVERABLE:
149 return GHES_SER_RECOVERABLE;
150 case CPER_SER_FATAL:
151 return GHES_SER_PANIC;
152 default:
153 /* Unkown, go panic */
154 return GHES_SER_PANIC;
155 }
156}
157
158/* SCI handler run in work queue, so ioremap can be used here */
159static int ghes_copy_tofrom_phys(void *buffer, u64 paddr, u32 len,
160 int from_phys)
161{
162 void *vaddr;
163
164 vaddr = ioremap_cache(paddr, len);
165 if (!vaddr)
166 return -ENOMEM;
167 if (from_phys)
168 memcpy(buffer, vaddr, len);
169 else
170 memcpy(vaddr, buffer, len);
171 iounmap(vaddr);
172
173 return 0;
174}
175
176static int ghes_read_estatus(struct ghes *ghes, int silent)
177{
178 struct acpi_hest_generic *g = ghes->generic;
179 u64 buf_paddr;
180 u32 len;
181 int rc;
182
183 rc = acpi_atomic_read(&buf_paddr, &g->error_status_address);
184 if (rc) {
185 if (!silent && printk_ratelimit())
186 pr_warning(FW_WARN GHES_PFX
187"Failed to read error status block address for hardware error source: %d.\n",
188 g->header.source_id);
189 return -EIO;
190 }
191 if (!buf_paddr)
192 return -ENOENT;
193
194 rc = ghes_copy_tofrom_phys(ghes->estatus, buf_paddr,
195 sizeof(*ghes->estatus), 1);
196 if (rc)
197 return rc;
198 if (!ghes->estatus->block_status)
199 return -ENOENT;
200
201 ghes->buffer_paddr = buf_paddr;
202 ghes->flags |= GHES_TO_CLEAR;
203
204 rc = -EIO;
205 len = apei_estatus_len(ghes->estatus);
206 if (len < sizeof(*ghes->estatus))
207 goto err_read_block;
208 if (len > ghes->generic->error_block_length)
209 goto err_read_block;
210 if (apei_estatus_check_header(ghes->estatus))
211 goto err_read_block;
212 rc = ghes_copy_tofrom_phys(ghes->estatus + 1,
213 buf_paddr + sizeof(*ghes->estatus),
214 len - sizeof(*ghes->estatus), 1);
215 if (rc)
216 return rc;
217 if (apei_estatus_check(ghes->estatus))
218 goto err_read_block;
219 rc = 0;
220
221err_read_block:
222 if (rc && !silent)
223 pr_warning(FW_WARN GHES_PFX
224 "Failed to read error status block!\n");
225 return rc;
226}
227
228static void ghes_clear_estatus(struct ghes *ghes)
229{
230 ghes->estatus->block_status = 0;
231 if (!(ghes->flags & GHES_TO_CLEAR))
232 return;
233 ghes_copy_tofrom_phys(ghes->estatus, ghes->buffer_paddr,
234 sizeof(ghes->estatus->block_status), 0);
235 ghes->flags &= ~GHES_TO_CLEAR;
236}
237
238static void ghes_do_proc(struct ghes *ghes)
239{
240 int ser, processed = 0;
241 struct acpi_hest_generic_data *gdata;
242
243 ser = ghes_severity(ghes->estatus->error_severity);
244 apei_estatus_for_each_section(ghes->estatus, gdata) {
245#ifdef CONFIG_X86_MCE
246 if (!uuid_le_cmp(*(uuid_le *)gdata->section_type,
247 CPER_SEC_PLATFORM_MEM)) {
248 apei_mce_report_mem_error(
249 ser == GHES_SER_CORRECTED,
250 (struct cper_sec_mem_err *)(gdata+1));
251 processed = 1;
252 }
253#endif
254 }
255
256 if (!processed && printk_ratelimit())
257 pr_warning(GHES_PFX
258 "Unknown error record from generic hardware error source: %d\n",
259 ghes->generic->header.source_id);
260}
261
262static int ghes_proc(struct ghes *ghes)
263{
264 int rc;
265
266 rc = ghes_read_estatus(ghes, 0);
267 if (rc)
268 goto out;
269 ghes_do_proc(ghes);
270
271out:
272 ghes_clear_estatus(ghes);
273 return 0;
274}
275
276static int ghes_notify_sci(struct notifier_block *this,
277 unsigned long event, void *data)
278{
279 struct ghes *ghes;
280 int ret = NOTIFY_DONE;
281
282 rcu_read_lock();
283 list_for_each_entry_rcu(ghes, &ghes_sci, list) {
284 if (!ghes_proc(ghes))
285 ret = NOTIFY_OK;
286 }
287 rcu_read_unlock();
288
289 return ret;
290}
291
292static struct notifier_block ghes_notifier_sci = {
293 .notifier_call = ghes_notify_sci,
294};
295
296static int hest_ghes_parse(struct acpi_hest_header *hest_hdr, void *data)
297{
298 struct acpi_hest_generic *generic;
299 struct ghes *ghes = NULL;
300 int rc = 0;
301
302 if (hest_hdr->type != ACPI_HEST_TYPE_GENERIC_ERROR)
303 return 0;
304
305 generic = (struct acpi_hest_generic *)hest_hdr;
306 if (!generic->enabled)
307 return 0;
308
309 if (generic->error_block_length <
310 sizeof(struct acpi_hest_generic_status)) {
311 pr_warning(FW_BUG GHES_PFX
312"Invalid error block length: %u for generic hardware error source: %d\n",
313 generic->error_block_length,
314 generic->header.source_id);
315 goto err;
316 }
317 if (generic->records_to_preallocate == 0) {
318 pr_warning(FW_BUG GHES_PFX
319"Invalid records to preallocate: %u for generic hardware error source: %d\n",
320 generic->records_to_preallocate,
321 generic->header.source_id);
322 goto err;
323 }
324 ghes = ghes_new(generic);
325 if (IS_ERR(ghes)) {
326 rc = PTR_ERR(ghes);
327 ghes = NULL;
328 goto err;
329 }
330 switch (generic->notify.type) {
331 case ACPI_HEST_NOTIFY_POLLED:
332 pr_warning(GHES_PFX
333"Generic hardware error source: %d notified via POLL is not supported!\n",
334 generic->header.source_id);
335 break;
336 case ACPI_HEST_NOTIFY_EXTERNAL:
337 case ACPI_HEST_NOTIFY_LOCAL:
338 pr_warning(GHES_PFX
339"Generic hardware error source: %d notified via IRQ is not supported!\n",
340 generic->header.source_id);
341 break;
342 case ACPI_HEST_NOTIFY_SCI:
343 if (list_empty(&ghes_sci))
344 register_acpi_hed_notifier(&ghes_notifier_sci);
345 list_add_rcu(&ghes->list, &ghes_sci);
346 break;
347 case ACPI_HEST_NOTIFY_NMI:
348 pr_warning(GHES_PFX
349"Generic hardware error source: %d notified via NMI is not supported!\n",
350 generic->header.source_id);
351 break;
352 default:
353 pr_warning(FW_WARN GHES_PFX
354 "Unknown notification type: %u for generic hardware error source: %d\n",
355 generic->notify.type, generic->header.source_id);
356 break;
357 }
358
359 return 0;
360err:
361 if (ghes)
362 ghes_fini(ghes);
363 return rc;
364}
365
366static void ghes_cleanup(void)
367{
368 struct ghes *ghes, *nghes;
369
370 if (!list_empty(&ghes_sci))
371 unregister_acpi_hed_notifier(&ghes_notifier_sci);
372
373 synchronize_rcu();
374
375 list_for_each_entry_safe(ghes, nghes, &ghes_sci, list) {
376 list_del(&ghes->list);
377 ghes_fini(ghes);
378 kfree(ghes);
379 }
380}
381
382static int __init ghes_init(void)
383{
384 int rc;
385
386 if (acpi_disabled)
387 return -ENODEV;
388
389 if (hest_disable) {
390 pr_info(GHES_PFX "HEST is not enabled!\n");
391 return -EINVAL;
392 }
393
394 rc = apei_hest_parse(hest_ghes_parse, NULL);
395 if (rc) {
396 pr_err(GHES_PFX
397 "Error during parsing HEST generic hardware error sources.\n");
398 goto err_cleanup;
399 }
400
401 if (list_empty(&ghes_sci)) {
402 pr_info(GHES_PFX
403 "No functional generic hardware error sources.\n");
404 rc = -ENODEV;
405 goto err_cleanup;
406 }
407
408 pr_info(GHES_PFX
409 "Generic Hardware Error Source support is initialized.\n");
410
411 return 0;
412err_cleanup:
413 ghes_cleanup();
414 return rc;
415}
416
417static void __exit ghes_exit(void)
418{
419 ghes_cleanup();
420}
421
422module_init(ghes_init);
423module_exit(ghes_exit);
424
425MODULE_AUTHOR("Huang Ying");
426MODULE_DESCRIPTION("APEI Generic Hardware Error Source support");
427MODULE_LICENSE("GPL");
diff --git a/drivers/acpi/apei/hest.c b/drivers/acpi/apei/hest.c
new file mode 100644
index 000000000000..e7f40d362cb3
--- /dev/null
+++ b/drivers/acpi/apei/hest.c
@@ -0,0 +1,173 @@
1/*
2 * APEI Hardware Error Souce Table support
3 *
4 * HEST describes error sources in detail; communicates operational
5 * parameters (i.e. severity levels, masking bits, and threshold
6 * values) to Linux as necessary. It also allows the BIOS to report
7 * non-standard error sources to Linux (for example, chipset-specific
8 * error registers).
9 *
10 * For more information about HEST, please refer to ACPI Specification
11 * version 4.0, section 17.3.2.
12 *
13 * Copyright 2009 Intel Corp.
14 * Author: Huang Ying <ying.huang@intel.com>
15 *
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License version
18 * 2 as published by the Free Software Foundation;
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 */
29
30#include <linux/kernel.h>
31#include <linux/module.h>
32#include <linux/init.h>
33#include <linux/acpi.h>
34#include <linux/kdebug.h>
35#include <linux/highmem.h>
36#include <linux/io.h>
37#include <acpi/apei.h>
38
39#include "apei-internal.h"
40
41#define HEST_PFX "HEST: "
42
43int hest_disable;
44EXPORT_SYMBOL_GPL(hest_disable);
45
46/* HEST table parsing */
47
48static struct acpi_table_hest *hest_tab;
49
50static int hest_void_parse(struct acpi_hest_header *hest_hdr, void *data)
51{
52 return 0;
53}
54
55static int hest_esrc_len_tab[ACPI_HEST_TYPE_RESERVED] = {
56 [ACPI_HEST_TYPE_IA32_CHECK] = -1, /* need further calculation */
57 [ACPI_HEST_TYPE_IA32_CORRECTED_CHECK] = -1,
58 [ACPI_HEST_TYPE_IA32_NMI] = sizeof(struct acpi_hest_ia_nmi),
59 [ACPI_HEST_TYPE_AER_ROOT_PORT] = sizeof(struct acpi_hest_aer_root),
60 [ACPI_HEST_TYPE_AER_ENDPOINT] = sizeof(struct acpi_hest_aer),
61 [ACPI_HEST_TYPE_AER_BRIDGE] = sizeof(struct acpi_hest_aer_bridge),
62 [ACPI_HEST_TYPE_GENERIC_ERROR] = sizeof(struct acpi_hest_generic),
63};
64
65static int hest_esrc_len(struct acpi_hest_header *hest_hdr)
66{
67 u16 hest_type = hest_hdr->type;
68 int len;
69
70 if (hest_type >= ACPI_HEST_TYPE_RESERVED)
71 return 0;
72
73 len = hest_esrc_len_tab[hest_type];
74
75 if (hest_type == ACPI_HEST_TYPE_IA32_CORRECTED_CHECK) {
76 struct acpi_hest_ia_corrected *cmc;
77 cmc = (struct acpi_hest_ia_corrected *)hest_hdr;
78 len = sizeof(*cmc) + cmc->num_hardware_banks *
79 sizeof(struct acpi_hest_ia_error_bank);
80 } else if (hest_type == ACPI_HEST_TYPE_IA32_CHECK) {
81 struct acpi_hest_ia_machine_check *mc;
82 mc = (struct acpi_hest_ia_machine_check *)hest_hdr;
83 len = sizeof(*mc) + mc->num_hardware_banks *
84 sizeof(struct acpi_hest_ia_error_bank);
85 }
86 BUG_ON(len == -1);
87
88 return len;
89};
90
91int apei_hest_parse(apei_hest_func_t func, void *data)
92{
93 struct acpi_hest_header *hest_hdr;
94 int i, rc, len;
95
96 if (hest_disable)
97 return -EINVAL;
98
99 hest_hdr = (struct acpi_hest_header *)(hest_tab + 1);
100 for (i = 0; i < hest_tab->error_source_count; i++) {
101 len = hest_esrc_len(hest_hdr);
102 if (!len) {
103 pr_warning(FW_WARN HEST_PFX
104 "Unknown or unused hardware error source "
105 "type: %d for hardware error source: %d.\n",
106 hest_hdr->type, hest_hdr->source_id);
107 return -EINVAL;
108 }
109 if ((void *)hest_hdr + len >
110 (void *)hest_tab + hest_tab->header.length) {
111 pr_warning(FW_BUG HEST_PFX
112 "Table contents overflow for hardware error source: %d.\n",
113 hest_hdr->source_id);
114 return -EINVAL;
115 }
116
117 rc = func(hest_hdr, data);
118 if (rc)
119 return rc;
120
121 hest_hdr = (void *)hest_hdr + len;
122 }
123
124 return 0;
125}
126EXPORT_SYMBOL_GPL(apei_hest_parse);
127
128static int __init setup_hest_disable(char *str)
129{
130 hest_disable = 1;
131 return 0;
132}
133
134__setup("hest_disable", setup_hest_disable);
135
136static int __init hest_init(void)
137{
138 acpi_status status;
139 int rc = -ENODEV;
140
141 if (acpi_disabled)
142 goto err;
143
144 if (hest_disable) {
145 pr_info(HEST_PFX "HEST tabling parsing is disabled.\n");
146 goto err;
147 }
148
149 status = acpi_get_table(ACPI_SIG_HEST, 0,
150 (struct acpi_table_header **)&hest_tab);
151 if (status == AE_NOT_FOUND) {
152 pr_info(HEST_PFX "Table is not found!\n");
153 goto err;
154 } else if (ACPI_FAILURE(status)) {
155 const char *msg = acpi_format_exception(status);
156 pr_err(HEST_PFX "Failed to get table, %s\n", msg);
157 rc = -EINVAL;
158 goto err;
159 }
160
161 rc = apei_hest_parse(hest_void_parse, NULL);
162 if (rc)
163 goto err;
164
165 pr_info(HEST_PFX "HEST table parsing is initialized.\n");
166
167 return 0;
168err:
169 hest_disable = 1;
170 return rc;
171}
172
173subsys_initcall(hest_init);
diff --git a/drivers/acpi/atomicio.c b/drivers/acpi/atomicio.c
new file mode 100644
index 000000000000..814b19249616
--- /dev/null
+++ b/drivers/acpi/atomicio.c
@@ -0,0 +1,360 @@
1/*
2 * atomicio.c - ACPI IO memory pre-mapping/post-unmapping, then
3 * accessing in atomic context.
4 *
5 * This is used for NMI handler to access IO memory area, because
6 * ioremap/iounmap can not be used in NMI handler. The IO memory area
7 * is pre-mapped in process context and accessed in NMI handler.
8 *
9 * Copyright (C) 2009-2010, Intel Corp.
10 * Author: Huang Ying <ying.huang@intel.com>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License version
14 * 2 as published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25
26#include <linux/kernel.h>
27#include <linux/module.h>
28#include <linux/init.h>
29#include <linux/acpi.h>
30#include <linux/io.h>
31#include <linux/kref.h>
32#include <linux/rculist.h>
33#include <linux/interrupt.h>
34#include <acpi/atomicio.h>
35
36#define ACPI_PFX "ACPI: "
37
38static LIST_HEAD(acpi_iomaps);
39/*
40 * Used for mutual exclusion between writers of acpi_iomaps list, for
41 * synchronization between readers and writer, RCU is used.
42 */
43static DEFINE_SPINLOCK(acpi_iomaps_lock);
44
45struct acpi_iomap {
46 struct list_head list;
47 void __iomem *vaddr;
48 unsigned long size;
49 phys_addr_t paddr;
50 struct kref ref;
51};
52
53/* acpi_iomaps_lock or RCU read lock must be held before calling */
54static struct acpi_iomap *__acpi_find_iomap(phys_addr_t paddr,
55 unsigned long size)
56{
57 struct acpi_iomap *map;
58
59 list_for_each_entry_rcu(map, &acpi_iomaps, list) {
60 if (map->paddr + map->size >= paddr + size &&
61 map->paddr <= paddr)
62 return map;
63 }
64 return NULL;
65}
66
67/*
68 * Atomic "ioremap" used by NMI handler, if the specified IO memory
69 * area is not pre-mapped, NULL will be returned.
70 *
71 * acpi_iomaps_lock or RCU read lock must be held before calling
72 */
73static void __iomem *__acpi_ioremap_fast(phys_addr_t paddr,
74 unsigned long size)
75{
76 struct acpi_iomap *map;
77
78 map = __acpi_find_iomap(paddr, size);
79 if (map)
80 return map->vaddr + (paddr - map->paddr);
81 else
82 return NULL;
83}
84
85/* acpi_iomaps_lock must be held before calling */
86static void __iomem *__acpi_try_ioremap(phys_addr_t paddr,
87 unsigned long size)
88{
89 struct acpi_iomap *map;
90
91 map = __acpi_find_iomap(paddr, size);
92 if (map) {
93 kref_get(&map->ref);
94 return map->vaddr + (paddr - map->paddr);
95 } else
96 return NULL;
97}
98
99/*
100 * Used to pre-map the specified IO memory area. First try to find
101 * whether the area is already pre-mapped, if it is, increase the
102 * reference count (in __acpi_try_ioremap) and return; otherwise, do
103 * the real ioremap, and add the mapping into acpi_iomaps list.
104 */
105static void __iomem *acpi_pre_map(phys_addr_t paddr,
106 unsigned long size)
107{
108 void __iomem *vaddr;
109 struct acpi_iomap *map;
110 unsigned long pg_sz, flags;
111 phys_addr_t pg_off;
112
113 spin_lock_irqsave(&acpi_iomaps_lock, flags);
114 vaddr = __acpi_try_ioremap(paddr, size);
115 spin_unlock_irqrestore(&acpi_iomaps_lock, flags);
116 if (vaddr)
117 return vaddr;
118
119 pg_off = paddr & PAGE_MASK;
120 pg_sz = ((paddr + size + PAGE_SIZE - 1) & PAGE_MASK) - pg_off;
121 vaddr = ioremap(pg_off, pg_sz);
122 if (!vaddr)
123 return NULL;
124 map = kmalloc(sizeof(*map), GFP_KERNEL);
125 if (!map)
126 goto err_unmap;
127 INIT_LIST_HEAD(&map->list);
128 map->paddr = pg_off;
129 map->size = pg_sz;
130 map->vaddr = vaddr;
131 kref_init(&map->ref);
132
133 spin_lock_irqsave(&acpi_iomaps_lock, flags);
134 vaddr = __acpi_try_ioremap(paddr, size);
135 if (vaddr) {
136 spin_unlock_irqrestore(&acpi_iomaps_lock, flags);
137 iounmap(map->vaddr);
138 kfree(map);
139 return vaddr;
140 }
141 list_add_tail_rcu(&map->list, &acpi_iomaps);
142 spin_unlock_irqrestore(&acpi_iomaps_lock, flags);
143
144 return vaddr + (paddr - pg_off);
145err_unmap:
146 iounmap(vaddr);
147 return NULL;
148}
149
150/* acpi_iomaps_lock must be held before calling */
151static void __acpi_kref_del_iomap(struct kref *ref)
152{
153 struct acpi_iomap *map;
154
155 map = container_of(ref, struct acpi_iomap, ref);
156 list_del_rcu(&map->list);
157}
158
159/*
160 * Used to post-unmap the specified IO memory area. The iounmap is
161 * done only if the reference count goes zero.
162 */
163static void acpi_post_unmap(phys_addr_t paddr, unsigned long size)
164{
165 struct acpi_iomap *map;
166 unsigned long flags;
167 int del;
168
169 spin_lock_irqsave(&acpi_iomaps_lock, flags);
170 map = __acpi_find_iomap(paddr, size);
171 BUG_ON(!map);
172 del = kref_put(&map->ref, __acpi_kref_del_iomap);
173 spin_unlock_irqrestore(&acpi_iomaps_lock, flags);
174
175 if (!del)
176 return;
177
178 synchronize_rcu();
179 iounmap(map->vaddr);
180 kfree(map);
181}
182
183/* In NMI handler, should set silent = 1 */
184static int acpi_check_gar(struct acpi_generic_address *reg,
185 u64 *paddr, int silent)
186{
187 u32 width, space_id;
188
189 width = reg->bit_width;
190 space_id = reg->space_id;
191 /* Handle possible alignment issues */
192 memcpy(paddr, &reg->address, sizeof(*paddr));
193 if (!*paddr) {
194 if (!silent)
195 pr_warning(FW_BUG ACPI_PFX
196 "Invalid physical address in GAR [0x%llx/%u/%u]\n",
197 *paddr, width, space_id);
198 return -EINVAL;
199 }
200
201 if ((width != 8) && (width != 16) && (width != 32) && (width != 64)) {
202 if (!silent)
203 pr_warning(FW_BUG ACPI_PFX
204 "Invalid bit width in GAR [0x%llx/%u/%u]\n",
205 *paddr, width, space_id);
206 return -EINVAL;
207 }
208
209 if (space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY &&
210 space_id != ACPI_ADR_SPACE_SYSTEM_IO) {
211 if (!silent)
212 pr_warning(FW_BUG ACPI_PFX
213 "Invalid address space type in GAR [0x%llx/%u/%u]\n",
214 *paddr, width, space_id);
215 return -EINVAL;
216 }
217
218 return 0;
219}
220
221/* Pre-map, working on GAR */
222int acpi_pre_map_gar(struct acpi_generic_address *reg)
223{
224 u64 paddr;
225 void __iomem *vaddr;
226 int rc;
227
228 if (reg->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
229 return 0;
230
231 rc = acpi_check_gar(reg, &paddr, 0);
232 if (rc)
233 return rc;
234
235 vaddr = acpi_pre_map(paddr, reg->bit_width / 8);
236 if (!vaddr)
237 return -EIO;
238
239 return 0;
240}
241EXPORT_SYMBOL_GPL(acpi_pre_map_gar);
242
243/* Post-unmap, working on GAR */
244int acpi_post_unmap_gar(struct acpi_generic_address *reg)
245{
246 u64 paddr;
247 int rc;
248
249 if (reg->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
250 return 0;
251
252 rc = acpi_check_gar(reg, &paddr, 0);
253 if (rc)
254 return rc;
255
256 acpi_post_unmap(paddr, reg->bit_width / 8);
257
258 return 0;
259}
260EXPORT_SYMBOL_GPL(acpi_post_unmap_gar);
261
262/*
263 * Can be used in atomic (including NMI) or process context. RCU read
264 * lock can only be released after the IO memory area accessing.
265 */
266static int acpi_atomic_read_mem(u64 paddr, u64 *val, u32 width)
267{
268 void __iomem *addr;
269
270 rcu_read_lock();
271 addr = __acpi_ioremap_fast(paddr, width);
272 switch (width) {
273 case 8:
274 *val = readb(addr);
275 break;
276 case 16:
277 *val = readw(addr);
278 break;
279 case 32:
280 *val = readl(addr);
281 break;
282 case 64:
283 *val = readq(addr);
284 break;
285 default:
286 return -EINVAL;
287 }
288 rcu_read_unlock();
289
290 return 0;
291}
292
293static int acpi_atomic_write_mem(u64 paddr, u64 val, u32 width)
294{
295 void __iomem *addr;
296
297 rcu_read_lock();
298 addr = __acpi_ioremap_fast(paddr, width);
299 switch (width) {
300 case 8:
301 writeb(val, addr);
302 break;
303 case 16:
304 writew(val, addr);
305 break;
306 case 32:
307 writel(val, addr);
308 break;
309 case 64:
310 writeq(val, addr);
311 break;
312 default:
313 return -EINVAL;
314 }
315 rcu_read_unlock();
316
317 return 0;
318}
319
320/* GAR accessing in atomic (including NMI) or process context */
321int acpi_atomic_read(u64 *val, struct acpi_generic_address *reg)
322{
323 u64 paddr;
324 int rc;
325
326 rc = acpi_check_gar(reg, &paddr, 1);
327 if (rc)
328 return rc;
329
330 *val = 0;
331 switch (reg->space_id) {
332 case ACPI_ADR_SPACE_SYSTEM_MEMORY:
333 return acpi_atomic_read_mem(paddr, val, reg->bit_width);
334 case ACPI_ADR_SPACE_SYSTEM_IO:
335 return acpi_os_read_port(paddr, (u32 *)val, reg->bit_width);
336 default:
337 return -EINVAL;
338 }
339}
340EXPORT_SYMBOL_GPL(acpi_atomic_read);
341
342int acpi_atomic_write(u64 val, struct acpi_generic_address *reg)
343{
344 u64 paddr;
345 int rc;
346
347 rc = acpi_check_gar(reg, &paddr, 1);
348 if (rc)
349 return rc;
350
351 switch (reg->space_id) {
352 case ACPI_ADR_SPACE_SYSTEM_MEMORY:
353 return acpi_atomic_write_mem(paddr, val, reg->bit_width);
354 case ACPI_ADR_SPACE_SYSTEM_IO:
355 return acpi_os_write_port(paddr, val, reg->bit_width);
356 default:
357 return -EINVAL;
358 }
359}
360EXPORT_SYMBOL_GPL(acpi_atomic_write);
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index f2234db85da0..5f2027d782e8 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -79,7 +79,7 @@ enum {
79 EC_FLAGS_GPE_STORM, /* GPE storm detected */ 79 EC_FLAGS_GPE_STORM, /* GPE storm detected */
80 EC_FLAGS_HANDLERS_INSTALLED, /* Handlers for GPE and 80 EC_FLAGS_HANDLERS_INSTALLED, /* Handlers for GPE and
81 * OpReg are installed */ 81 * OpReg are installed */
82 EC_FLAGS_FROZEN, /* Transactions are suspended */ 82 EC_FLAGS_BLOCKED, /* Transactions are blocked */
83}; 83};
84 84
85/* If we find an EC via the ECDT, we need to keep a ptr to its context */ 85/* 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)
293 if (t->rdata) 293 if (t->rdata)
294 memset(t->rdata, 0, t->rlen); 294 memset(t->rdata, 0, t->rlen);
295 mutex_lock(&ec->lock); 295 mutex_lock(&ec->lock);
296 if (test_bit(EC_FLAGS_FROZEN, &ec->flags)) { 296 if (test_bit(EC_FLAGS_BLOCKED, &ec->flags)) {
297 status = -EINVAL; 297 status = -EINVAL;
298 goto unlock; 298 goto unlock;
299 } 299 }
@@ -459,7 +459,7 @@ int ec_transaction(u8 command,
459 459
460EXPORT_SYMBOL(ec_transaction); 460EXPORT_SYMBOL(ec_transaction);
461 461
462void acpi_ec_suspend_transactions(void) 462void acpi_ec_block_transactions(void)
463{ 463{
464 struct acpi_ec *ec = first_ec; 464 struct acpi_ec *ec = first_ec;
465 465
@@ -468,11 +468,11 @@ void acpi_ec_suspend_transactions(void)
468 468
469 mutex_lock(&ec->lock); 469 mutex_lock(&ec->lock);
470 /* Prevent transactions from being carried out */ 470 /* Prevent transactions from being carried out */
471 set_bit(EC_FLAGS_FROZEN, &ec->flags); 471 set_bit(EC_FLAGS_BLOCKED, &ec->flags);
472 mutex_unlock(&ec->lock); 472 mutex_unlock(&ec->lock);
473} 473}
474 474
475void acpi_ec_resume_transactions(void) 475void acpi_ec_unblock_transactions(void)
476{ 476{
477 struct acpi_ec *ec = first_ec; 477 struct acpi_ec *ec = first_ec;
478 478
@@ -481,10 +481,20 @@ void acpi_ec_resume_transactions(void)
481 481
482 mutex_lock(&ec->lock); 482 mutex_lock(&ec->lock);
483 /* Allow transactions to be carried out again */ 483 /* Allow transactions to be carried out again */
484 clear_bit(EC_FLAGS_FROZEN, &ec->flags); 484 clear_bit(EC_FLAGS_BLOCKED, &ec->flags);
485 mutex_unlock(&ec->lock); 485 mutex_unlock(&ec->lock);
486} 486}
487 487
488void acpi_ec_unblock_transactions_early(void)
489{
490 /*
491 * Allow transactions to happen again (this function is called from
492 * atomic context during wakeup, so we don't need to acquire the mutex).
493 */
494 if (first_ec)
495 clear_bit(EC_FLAGS_BLOCKED, &first_ec->flags);
496}
497
488static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 * data) 498static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 * data)
489{ 499{
490 int result; 500 int result;
@@ -1027,10 +1037,9 @@ int __init acpi_ec_ecdt_probe(void)
1027 /* Don't trust ECDT, which comes from ASUSTek */ 1037 /* Don't trust ECDT, which comes from ASUSTek */
1028 if (!EC_FLAGS_VALIDATE_ECDT) 1038 if (!EC_FLAGS_VALIDATE_ECDT)
1029 goto install; 1039 goto install;
1030 saved_ec = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL); 1040 saved_ec = kmemdup(boot_ec, sizeof(struct acpi_ec), GFP_KERNEL);
1031 if (!saved_ec) 1041 if (!saved_ec)
1032 return -ENOMEM; 1042 return -ENOMEM;
1033 memcpy(saved_ec, boot_ec, sizeof(struct acpi_ec));
1034 /* fall through */ 1043 /* fall through */
1035 } 1044 }
1036 1045
diff --git a/drivers/acpi/hed.c b/drivers/acpi/hed.c
new file mode 100644
index 000000000000..d0c1967f7597
--- /dev/null
+++ b/drivers/acpi/hed.c
@@ -0,0 +1,112 @@
1/*
2 * ACPI Hardware Error Device (PNP0C33) Driver
3 *
4 * Copyright (C) 2010, Intel Corp.
5 * Author: Huang Ying <ying.huang@intel.com>
6 *
7 * ACPI Hardware Error Device is used to report some hardware errors
8 * notified via SCI, mainly the corrected errors.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License version
12 * 2 as published by the Free Software Foundation;
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24#include <linux/kernel.h>
25#include <linux/module.h>
26#include <linux/init.h>
27#include <linux/acpi.h>
28#include <acpi/acpi_bus.h>
29#include <acpi/acpi_drivers.h>
30#include <acpi/hed.h>
31
32static struct acpi_device_id acpi_hed_ids[] = {
33 {"PNP0C33", 0},
34 {"", 0},
35};
36MODULE_DEVICE_TABLE(acpi, acpi_hed_ids);
37
38static acpi_handle hed_handle;
39
40static BLOCKING_NOTIFIER_HEAD(acpi_hed_notify_list);
41
42int register_acpi_hed_notifier(struct notifier_block *nb)
43{
44 return blocking_notifier_chain_register(&acpi_hed_notify_list, nb);
45}
46EXPORT_SYMBOL_GPL(register_acpi_hed_notifier);
47
48void unregister_acpi_hed_notifier(struct notifier_block *nb)
49{
50 blocking_notifier_chain_unregister(&acpi_hed_notify_list, nb);
51}
52EXPORT_SYMBOL_GPL(unregister_acpi_hed_notifier);
53
54/*
55 * SCI to report hardware error is forwarded to the listeners of HED,
56 * it is used by HEST Generic Hardware Error Source with notify type
57 * SCI.
58 */
59static void acpi_hed_notify(struct acpi_device *device, u32 event)
60{
61 blocking_notifier_call_chain(&acpi_hed_notify_list, 0, NULL);
62}
63
64static int __devinit acpi_hed_add(struct acpi_device *device)
65{
66 /* Only one hardware error device */
67 if (hed_handle)
68 return -EINVAL;
69 hed_handle = device->handle;
70 return 0;
71}
72
73static int __devexit acpi_hed_remove(struct acpi_device *device, int type)
74{
75 hed_handle = NULL;
76 return 0;
77}
78
79static struct acpi_driver acpi_hed_driver = {
80 .name = "hardware_error_device",
81 .class = "hardware_error",
82 .ids = acpi_hed_ids,
83 .ops = {
84 .add = acpi_hed_add,
85 .remove = acpi_hed_remove,
86 .notify = acpi_hed_notify,
87 },
88};
89
90static int __init acpi_hed_init(void)
91{
92 if (acpi_disabled)
93 return -ENODEV;
94
95 if (acpi_bus_register_driver(&acpi_hed_driver) < 0)
96 return -ENODEV;
97
98 return 0;
99}
100
101static void __exit acpi_hed_exit(void)
102{
103 acpi_bus_unregister_driver(&acpi_hed_driver);
104}
105
106module_init(acpi_hed_init);
107module_exit(acpi_hed_exit);
108
109ACPI_MODULE_NAME("hed");
110MODULE_AUTHOR("Huang Ying");
111MODULE_DESCRIPTION("ACPI Hardware Error Device Driver");
112MODULE_LICENSE("GPL");
diff --git a/drivers/acpi/hest.c b/drivers/acpi/hest.c
deleted file mode 100644
index 1c527a192872..000000000000
--- a/drivers/acpi/hest.c
+++ /dev/null
@@ -1,139 +0,0 @@
1#include <linux/acpi.h>
2#include <linux/pci.h>
3
4#define PREFIX "ACPI: "
5
6static inline unsigned long parse_acpi_hest_ia_machine_check(struct acpi_hest_ia_machine_check *p)
7{
8 return sizeof(*p) +
9 (sizeof(struct acpi_hest_ia_error_bank) * p->num_hardware_banks);
10}
11
12static inline unsigned long parse_acpi_hest_ia_corrected(struct acpi_hest_ia_corrected *p)
13{
14 return sizeof(*p) +
15 (sizeof(struct acpi_hest_ia_error_bank) * p->num_hardware_banks);
16}
17
18static inline unsigned long parse_acpi_hest_ia_nmi(struct acpi_hest_ia_nmi *p)
19{
20 return sizeof(*p);
21}
22
23static inline unsigned long parse_acpi_hest_generic(struct acpi_hest_generic *p)
24{
25 return sizeof(*p);
26}
27
28static inline unsigned int hest_match_pci(struct acpi_hest_aer_common *p, struct pci_dev *pci)
29{
30 return (0 == pci_domain_nr(pci->bus) &&
31 p->bus == pci->bus->number &&
32 p->device == PCI_SLOT(pci->devfn) &&
33 p->function == PCI_FUNC(pci->devfn));
34}
35
36static unsigned long parse_acpi_hest_aer(void *hdr, int type, struct pci_dev *pci, int *firmware_first)
37{
38 struct acpi_hest_aer_common *p = hdr + sizeof(struct acpi_hest_header);
39 unsigned long rc=0;
40 u8 pcie_type = 0;
41 u8 bridge = 0;
42 switch (type) {
43 case ACPI_HEST_TYPE_AER_ROOT_PORT:
44 rc = sizeof(struct acpi_hest_aer_root);
45 pcie_type = PCI_EXP_TYPE_ROOT_PORT;
46 break;
47 case ACPI_HEST_TYPE_AER_ENDPOINT:
48 rc = sizeof(struct acpi_hest_aer);
49 pcie_type = PCI_EXP_TYPE_ENDPOINT;
50 break;
51 case ACPI_HEST_TYPE_AER_BRIDGE:
52 rc = sizeof(struct acpi_hest_aer_bridge);
53 if ((pci->class >> 16) == PCI_BASE_CLASS_BRIDGE)
54 bridge = 1;
55 break;
56 }
57
58 if (p->flags & ACPI_HEST_GLOBAL) {
59 if ((pci->is_pcie && (pci->pcie_type == pcie_type)) || bridge)
60 *firmware_first = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST);
61 }
62 else
63 if (hest_match_pci(p, pci))
64 *firmware_first = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST);
65 return rc;
66}
67
68static int acpi_hest_firmware_first(struct acpi_table_header *stdheader, struct pci_dev *pci)
69{
70 struct acpi_table_hest *hest = (struct acpi_table_hest *)stdheader;
71 void *p = (void *)hest + sizeof(*hest); /* defined by the ACPI 4.0 spec */
72 struct acpi_hest_header *hdr = p;
73
74 int i;
75 int firmware_first = 0;
76 static unsigned char printed_unused = 0;
77 static unsigned char printed_reserved = 0;
78
79 for (i=0, hdr=p; p < (((void *)hest) + hest->header.length) && i < hest->error_source_count; i++) {
80 switch (hdr->type) {
81 case ACPI_HEST_TYPE_IA32_CHECK:
82 p += parse_acpi_hest_ia_machine_check(p);
83 break;
84 case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK:
85 p += parse_acpi_hest_ia_corrected(p);
86 break;
87 case ACPI_HEST_TYPE_IA32_NMI:
88 p += parse_acpi_hest_ia_nmi(p);
89 break;
90 /* These three should never appear */
91 case ACPI_HEST_TYPE_NOT_USED3:
92 case ACPI_HEST_TYPE_NOT_USED4:
93 case ACPI_HEST_TYPE_NOT_USED5:
94 if (!printed_unused) {
95 printk(KERN_DEBUG PREFIX
96 "HEST Error Source list contains an obsolete type (%d).\n", hdr->type);
97 printed_unused = 1;
98 }
99 break;
100 case ACPI_HEST_TYPE_AER_ROOT_PORT:
101 case ACPI_HEST_TYPE_AER_ENDPOINT:
102 case ACPI_HEST_TYPE_AER_BRIDGE:
103 p += parse_acpi_hest_aer(p, hdr->type, pci, &firmware_first);
104 break;
105 case ACPI_HEST_TYPE_GENERIC_ERROR:
106 p += parse_acpi_hest_generic(p);
107 break;
108 /* These should never appear either */
109 case ACPI_HEST_TYPE_RESERVED:
110 default:
111 if (!printed_reserved) {
112 printk(KERN_DEBUG PREFIX
113 "HEST Error Source list contains a reserved type (%d).\n", hdr->type);
114 printed_reserved = 1;
115 }
116 break;
117 }
118 }
119 return firmware_first;
120}
121
122int acpi_hest_firmware_first_pci(struct pci_dev *pci)
123{
124 acpi_status status = AE_NOT_FOUND;
125 struct acpi_table_header *hest = NULL;
126
127 if (acpi_disabled)
128 return 0;
129
130 status = acpi_get_table(ACPI_SIG_HEST, 1, &hest);
131
132 if (ACPI_SUCCESS(status)) {
133 if (acpi_hest_firmware_first(hest, pci)) {
134 return 1;
135 }
136 }
137 return 0;
138}
139EXPORT_SYMBOL_GPL(acpi_hest_firmware_first_pci);
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index e28411367239..f8f190ec066e 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -49,8 +49,9 @@ void acpi_early_processor_set_pdc(void);
49int acpi_ec_init(void); 49int acpi_ec_init(void);
50int acpi_ec_ecdt_probe(void); 50int acpi_ec_ecdt_probe(void);
51int acpi_boot_ec_enable(void); 51int acpi_boot_ec_enable(void);
52void acpi_ec_suspend_transactions(void); 52void acpi_ec_block_transactions(void);
53void acpi_ec_resume_transactions(void); 53void acpi_ec_unblock_transactions(void);
54void acpi_ec_unblock_transactions_early(void);
54 55
55/*-------------------------------------------------------------------------- 56/*--------------------------------------------------------------------------
56 Suspend/Resume 57 Suspend/Resume
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 4bc1c4178f50..78418ce4fc78 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -1207,6 +1207,15 @@ int acpi_check_mem_region(resource_size_t start, resource_size_t n,
1207EXPORT_SYMBOL(acpi_check_mem_region); 1207EXPORT_SYMBOL(acpi_check_mem_region);
1208 1208
1209/* 1209/*
1210 * Let drivers know whether the resource checks are effective
1211 */
1212int acpi_resources_are_enforced(void)
1213{
1214 return acpi_enforce_resources == ENFORCE_RESOURCES_STRICT;
1215}
1216EXPORT_SYMBOL(acpi_resources_are_enforced);
1217
1218/*
1210 * Acquire a spinlock. 1219 * Acquire a spinlock.
1211 * 1220 *
1212 * handle is a pointer to the spinlock_t. 1221 * handle is a pointer to the spinlock_t.
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index aefce33f2a09..4eac59393edc 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -120,7 +120,8 @@ acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus)
120 struct acpi_pci_root *root; 120 struct acpi_pci_root *root;
121 121
122 list_for_each_entry(root, &acpi_pci_roots, node) 122 list_for_each_entry(root, &acpi_pci_roots, node)
123 if ((root->segment == (u16) seg) && (root->bus_nr == (u16) bus)) 123 if ((root->segment == (u16) seg) &&
124 (root->secondary.start == (u16) bus))
124 return root->device->handle; 125 return root->device->handle;
125 return NULL; 126 return NULL;
126} 127}
@@ -154,7 +155,7 @@ EXPORT_SYMBOL_GPL(acpi_is_root_bridge);
154static acpi_status 155static acpi_status
155get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data) 156get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data)
156{ 157{
157 int *busnr = data; 158 struct resource *res = data;
158 struct acpi_resource_address64 address; 159 struct acpi_resource_address64 address;
159 160
160 if (resource->type != ACPI_RESOURCE_TYPE_ADDRESS16 && 161 if (resource->type != ACPI_RESOURCE_TYPE_ADDRESS16 &&
@@ -164,28 +165,27 @@ get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data)
164 165
165 acpi_resource_to_address64(resource, &address); 166 acpi_resource_to_address64(resource, &address);
166 if ((address.address_length > 0) && 167 if ((address.address_length > 0) &&
167 (address.resource_type == ACPI_BUS_NUMBER_RANGE)) 168 (address.resource_type == ACPI_BUS_NUMBER_RANGE)) {
168 *busnr = address.minimum; 169 res->start = address.minimum;
170 res->end = address.minimum + address.address_length - 1;
171 }
169 172
170 return AE_OK; 173 return AE_OK;
171} 174}
172 175
173static acpi_status try_get_root_bridge_busnr(acpi_handle handle, 176static acpi_status try_get_root_bridge_busnr(acpi_handle handle,
174 unsigned long long *bus) 177 struct resource *res)
175{ 178{
176 acpi_status status; 179 acpi_status status;
177 int busnum;
178 180
179 busnum = -1; 181 res->start = -1;
180 status = 182 status =
181 acpi_walk_resources(handle, METHOD_NAME__CRS, 183 acpi_walk_resources(handle, METHOD_NAME__CRS,
182 get_root_bridge_busnr_callback, &busnum); 184 get_root_bridge_busnr_callback, res);
183 if (ACPI_FAILURE(status)) 185 if (ACPI_FAILURE(status))
184 return status; 186 return status;
185 /* Check if we really get a bus number from _CRS */ 187 if (res->start == -1)
186 if (busnum == -1)
187 return AE_ERROR; 188 return AE_ERROR;
188 *bus = busnum;
189 return AE_OK; 189 return AE_OK;
190} 190}
191 191
@@ -429,34 +429,47 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
429 struct acpi_device *child; 429 struct acpi_device *child;
430 u32 flags, base_flags; 430 u32 flags, base_flags;
431 431
432 root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
433 if (!root)
434 return -ENOMEM;
435
432 segment = 0; 436 segment = 0;
433 status = acpi_evaluate_integer(device->handle, METHOD_NAME__SEG, NULL, 437 status = acpi_evaluate_integer(device->handle, METHOD_NAME__SEG, NULL,
434 &segment); 438 &segment);
435 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { 439 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
436 printk(KERN_ERR PREFIX "can't evaluate _SEG\n"); 440 printk(KERN_ERR PREFIX "can't evaluate _SEG\n");
437 return -ENODEV; 441 result = -ENODEV;
442 goto end;
438 } 443 }
439 444
440 /* Check _CRS first, then _BBN. If no _BBN, default to zero. */ 445 /* Check _CRS first, then _BBN. If no _BBN, default to zero. */
441 bus = 0; 446 root->secondary.flags = IORESOURCE_BUS;
442 status = try_get_root_bridge_busnr(device->handle, &bus); 447 status = try_get_root_bridge_busnr(device->handle, &root->secondary);
443 if (ACPI_FAILURE(status)) { 448 if (ACPI_FAILURE(status)) {
449 /*
450 * We need both the start and end of the downstream bus range
451 * to interpret _CBA (MMCONFIG base address), so it really is
452 * supposed to be in _CRS. If we don't find it there, all we
453 * can do is assume [_BBN-0xFF] or [0-0xFF].
454 */
455 root->secondary.end = 0xFF;
456 printk(KERN_WARNING FW_BUG PREFIX
457 "no secondary bus range in _CRS\n");
444 status = acpi_evaluate_integer(device->handle, METHOD_NAME__BBN, NULL, &bus); 458 status = acpi_evaluate_integer(device->handle, METHOD_NAME__BBN, NULL, &bus);
445 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { 459 if (ACPI_SUCCESS(status))
446 printk(KERN_ERR PREFIX 460 root->secondary.start = bus;
447 "no bus number in _CRS and can't evaluate _BBN\n"); 461 else if (status == AE_NOT_FOUND)
448 return -ENODEV; 462 root->secondary.start = 0;
463 else {
464 printk(KERN_ERR PREFIX "can't evaluate _BBN\n");
465 result = -ENODEV;
466 goto end;
449 } 467 }
450 } 468 }
451 469
452 root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
453 if (!root)
454 return -ENOMEM;
455
456 INIT_LIST_HEAD(&root->node); 470 INIT_LIST_HEAD(&root->node);
457 root->device = device; 471 root->device = device;
458 root->segment = segment & 0xFFFF; 472 root->segment = segment & 0xFFFF;
459 root->bus_nr = bus & 0xFF;
460 strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME); 473 strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME);
461 strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS); 474 strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
462 device->driver_data = root; 475 device->driver_data = root;
@@ -475,9 +488,9 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
475 /* TBD: Locking */ 488 /* TBD: Locking */
476 list_add_tail(&root->node, &acpi_pci_roots); 489 list_add_tail(&root->node, &acpi_pci_roots);
477 490
478 printk(KERN_INFO PREFIX "%s [%s] (%04x:%02x)\n", 491 printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n",
479 acpi_device_name(device), acpi_device_bid(device), 492 acpi_device_name(device), acpi_device_bid(device),
480 root->segment, root->bus_nr); 493 root->segment, &root->secondary);
481 494
482 /* 495 /*
483 * Scan the Root Bridge 496 * Scan the Root Bridge
@@ -486,11 +499,11 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
486 * PCI namespace does not get created until this call is made (and 499 * PCI namespace does not get created until this call is made (and
487 * thus the root bridge's pci_dev does not exist). 500 * thus the root bridge's pci_dev does not exist).
488 */ 501 */
489 root->bus = pci_acpi_scan_root(device, segment, bus); 502 root->bus = pci_acpi_scan_root(root);
490 if (!root->bus) { 503 if (!root->bus) {
491 printk(KERN_ERR PREFIX 504 printk(KERN_ERR PREFIX
492 "Bus %04x:%02x not present in PCI namespace\n", 505 "Bus %04x:%02x not present in PCI namespace\n",
493 root->segment, root->bus_nr); 506 root->segment, (unsigned int)root->secondary.start);
494 result = -ENODEV; 507 result = -ENODEV;
495 goto end; 508 goto end;
496 } 509 }
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
index 5675d9747e87..b1034a9ada4e 100644
--- a/drivers/acpi/processor_driver.c
+++ b/drivers/acpi/processor_driver.c
@@ -616,7 +616,8 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device)
616 acpi_processor_get_limit_info(pr); 616 acpi_processor_get_limit_info(pr);
617 617
618 618
619 acpi_processor_power_init(pr, device); 619 if (cpuidle_get_driver() == &acpi_idle_driver)
620 acpi_processor_power_init(pr, device);
620 621
621 pr->cdev = thermal_cooling_device_register("Processor", device, 622 pr->cdev = thermal_cooling_device_register("Processor", device,
622 &processor_cooling_ops); 623 &processor_cooling_ops);
@@ -920,9 +921,14 @@ static int __init acpi_processor_init(void)
920 if (!acpi_processor_dir) 921 if (!acpi_processor_dir)
921 return -ENOMEM; 922 return -ENOMEM;
922#endif 923#endif
923 result = cpuidle_register_driver(&acpi_idle_driver); 924
924 if (result < 0) 925 if (!cpuidle_register_driver(&acpi_idle_driver)) {
925 goto out_proc; 926 printk(KERN_DEBUG "ACPI: %s registered with cpuidle\n",
927 acpi_idle_driver.name);
928 } else {
929 printk(KERN_DEBUG "ACPI: acpi_idle yielding to %s",
930 cpuidle_get_driver()->name);
931 }
926 932
927 result = acpi_bus_register_driver(&acpi_processor_driver); 933 result = acpi_bus_register_driver(&acpi_processor_driver);
928 if (result < 0) 934 if (result < 0)
@@ -941,7 +947,6 @@ static int __init acpi_processor_init(void)
941out_cpuidle: 947out_cpuidle:
942 cpuidle_unregister_driver(&acpi_idle_driver); 948 cpuidle_unregister_driver(&acpi_idle_driver);
943 949
944out_proc:
945#ifdef CONFIG_ACPI_PROCFS 950#ifdef CONFIG_ACPI_PROCFS
946 remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir); 951 remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
947#endif 952#endif
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index c3817e1f32c7..b1b385692f46 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -80,7 +80,7 @@ module_param(nocst, uint, 0000);
80static unsigned int latency_factor __read_mostly = 2; 80static unsigned int latency_factor __read_mostly = 2;
81module_param(latency_factor, uint, 0644); 81module_param(latency_factor, uint, 0644);
82 82
83static s64 us_to_pm_timer_ticks(s64 t) 83static u64 us_to_pm_timer_ticks(s64 t)
84{ 84{
85 return div64_u64(t * PM_TIMER_FREQUENCY, 1000000); 85 return div64_u64(t * PM_TIMER_FREQUENCY, 1000000);
86} 86}
@@ -727,24 +727,14 @@ static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset)
727 break; 727 break;
728 } 728 }
729 729
730 if (pr->power.states[i].promotion.state) 730 seq_puts(seq, "promotion[--] ");
731 seq_printf(seq, "promotion[C%zd] ", 731
732 (pr->power.states[i].promotion.state - 732 seq_puts(seq, "demotion[--] ");
733 pr->power.states)); 733
734 else 734 seq_printf(seq, "latency[%03d] usage[%08d] duration[%020Lu]\n",
735 seq_puts(seq, "promotion[--] ");
736
737 if (pr->power.states[i].demotion.state)
738 seq_printf(seq, "demotion[C%zd] ",
739 (pr->power.states[i].demotion.state -
740 pr->power.states));
741 else
742 seq_puts(seq, "demotion[--] ");
743
744 seq_printf(seq, "latency[%03d] usage[%08d] duration[%020llu]\n",
745 pr->power.states[i].latency, 735 pr->power.states[i].latency,
746 pr->power.states[i].usage, 736 pr->power.states[i].usage,
747 (unsigned long long)pr->power.states[i].time); 737 us_to_pm_timer_ticks(pr->power.states[i].time));
748 } 738 }
749 739
750 end: 740 end:
@@ -869,8 +859,8 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
869 struct acpi_processor *pr; 859 struct acpi_processor *pr;
870 struct acpi_processor_cx *cx = cpuidle_get_statedata(state); 860 struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
871 ktime_t kt1, kt2; 861 ktime_t kt1, kt2;
862 s64 idle_time_ns;
872 s64 idle_time; 863 s64 idle_time;
873 s64 sleep_ticks = 0;
874 864
875 pr = __get_cpu_var(processors); 865 pr = __get_cpu_var(processors);
876 866
@@ -881,6 +871,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
881 return(acpi_idle_enter_c1(dev, state)); 871 return(acpi_idle_enter_c1(dev, state));
882 872
883 local_irq_disable(); 873 local_irq_disable();
874
884 if (cx->entry_method != ACPI_CSTATE_FFH) { 875 if (cx->entry_method != ACPI_CSTATE_FFH) {
885 current_thread_info()->status &= ~TS_POLLING; 876 current_thread_info()->status &= ~TS_POLLING;
886 /* 877 /*
@@ -888,12 +879,12 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
888 * NEED_RESCHED: 879 * NEED_RESCHED:
889 */ 880 */
890 smp_mb(); 881 smp_mb();
891 }
892 882
893 if (unlikely(need_resched())) { 883 if (unlikely(need_resched())) {
894 current_thread_info()->status |= TS_POLLING; 884 current_thread_info()->status |= TS_POLLING;
895 local_irq_enable(); 885 local_irq_enable();
896 return 0; 886 return 0;
887 }
897 } 888 }
898 889
899 /* 890 /*
@@ -910,20 +901,21 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
910 sched_clock_idle_sleep_event(); 901 sched_clock_idle_sleep_event();
911 acpi_idle_do_entry(cx); 902 acpi_idle_do_entry(cx);
912 kt2 = ktime_get_real(); 903 kt2 = ktime_get_real();
913 idle_time = ktime_to_us(ktime_sub(kt2, kt1)); 904 idle_time_ns = ktime_to_ns(ktime_sub(kt2, kt1));
914 905 idle_time = idle_time_ns;
915 sleep_ticks = us_to_pm_timer_ticks(idle_time); 906 do_div(idle_time, NSEC_PER_USEC);
916 907
917 /* Tell the scheduler how much we idled: */ 908 /* Tell the scheduler how much we idled: */
918 sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS); 909 sched_clock_idle_wakeup_event(idle_time_ns);
919 910
920 local_irq_enable(); 911 local_irq_enable();
921 current_thread_info()->status |= TS_POLLING; 912 if (cx->entry_method != ACPI_CSTATE_FFH)
913 current_thread_info()->status |= TS_POLLING;
922 914
923 cx->usage++; 915 cx->usage++;
924 916
925 lapic_timer_state_broadcast(pr, cx, 0); 917 lapic_timer_state_broadcast(pr, cx, 0);
926 cx->time += sleep_ticks; 918 cx->time += idle_time;
927 return idle_time; 919 return idle_time;
928} 920}
929 921
@@ -943,8 +935,8 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
943 struct acpi_processor *pr; 935 struct acpi_processor *pr;
944 struct acpi_processor_cx *cx = cpuidle_get_statedata(state); 936 struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
945 ktime_t kt1, kt2; 937 ktime_t kt1, kt2;
938 s64 idle_time_ns;
946 s64 idle_time; 939 s64 idle_time;
947 s64 sleep_ticks = 0;
948 940
949 941
950 pr = __get_cpu_var(processors); 942 pr = __get_cpu_var(processors);
@@ -968,6 +960,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
968 } 960 }
969 961
970 local_irq_disable(); 962 local_irq_disable();
963
971 if (cx->entry_method != ACPI_CSTATE_FFH) { 964 if (cx->entry_method != ACPI_CSTATE_FFH) {
972 current_thread_info()->status &= ~TS_POLLING; 965 current_thread_info()->status &= ~TS_POLLING;
973 /* 966 /*
@@ -975,12 +968,12 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
975 * NEED_RESCHED: 968 * NEED_RESCHED:
976 */ 969 */
977 smp_mb(); 970 smp_mb();
978 }
979 971
980 if (unlikely(need_resched())) { 972 if (unlikely(need_resched())) {
981 current_thread_info()->status |= TS_POLLING; 973 current_thread_info()->status |= TS_POLLING;
982 local_irq_enable(); 974 local_irq_enable();
983 return 0; 975 return 0;
976 }
984 } 977 }
985 978
986 acpi_unlazy_tlb(smp_processor_id()); 979 acpi_unlazy_tlb(smp_processor_id());
@@ -1025,19 +1018,21 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
1025 spin_unlock(&c3_lock); 1018 spin_unlock(&c3_lock);
1026 } 1019 }
1027 kt2 = ktime_get_real(); 1020 kt2 = ktime_get_real();
1028 idle_time = ktime_to_us(ktime_sub(kt2, kt1)); 1021 idle_time_ns = ktime_to_ns(ktime_sub(kt2, kt1));
1022 idle_time = idle_time_ns;
1023 do_div(idle_time, NSEC_PER_USEC);
1029 1024
1030 sleep_ticks = us_to_pm_timer_ticks(idle_time);
1031 /* Tell the scheduler how much we idled: */ 1025 /* Tell the scheduler how much we idled: */
1032 sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS); 1026 sched_clock_idle_wakeup_event(idle_time_ns);
1033 1027
1034 local_irq_enable(); 1028 local_irq_enable();
1035 current_thread_info()->status |= TS_POLLING; 1029 if (cx->entry_method != ACPI_CSTATE_FFH)
1030 current_thread_info()->status |= TS_POLLING;
1036 1031
1037 cx->usage++; 1032 cx->usage++;
1038 1033
1039 lapic_timer_state_broadcast(pr, cx, 0); 1034 lapic_timer_state_broadcast(pr, cx, 0);
1040 cx->time += sleep_ticks; 1035 cx->time += idle_time;
1041 return idle_time; 1036 return idle_time;
1042} 1037}
1043 1038
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index baa76bbf244a..3fb4bdea7e06 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -80,22 +80,6 @@ static int acpi_sleep_prepare(u32 acpi_state)
80 80
81#ifdef CONFIG_ACPI_SLEEP 81#ifdef CONFIG_ACPI_SLEEP
82static u32 acpi_target_sleep_state = ACPI_STATE_S0; 82static u32 acpi_target_sleep_state = ACPI_STATE_S0;
83/*
84 * According to the ACPI specification the BIOS should make sure that ACPI is
85 * enabled and SCI_EN bit is set on wake-up from S1 - S3 sleep states. Still,
86 * some BIOSes don't do that and therefore we use acpi_enable() to enable ACPI
87 * on such systems during resume. Unfortunately that doesn't help in
88 * particularly pathological cases in which SCI_EN has to be set directly on
89 * resume, although the specification states very clearly that this flag is
90 * owned by the hardware. The set_sci_en_on_resume variable will be set in such
91 * cases.
92 */
93static bool set_sci_en_on_resume;
94
95void __init acpi_set_sci_en_on_resume(void)
96{
97 set_sci_en_on_resume = true;
98}
99 83
100/* 84/*
101 * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the 85 * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the
@@ -110,11 +94,13 @@ void __init acpi_old_suspend_ordering(void)
110} 94}
111 95
112/** 96/**
113 * acpi_pm_disable_gpes - Disable the GPEs. 97 * acpi_pm_freeze - Disable the GPEs and suspend EC transactions.
114 */ 98 */
115static int acpi_pm_disable_gpes(void) 99static int acpi_pm_freeze(void)
116{ 100{
117 acpi_disable_all_gpes(); 101 acpi_disable_all_gpes();
102 acpi_os_wait_events_complete(NULL);
103 acpi_ec_block_transactions();
118 return 0; 104 return 0;
119} 105}
120 106
@@ -142,7 +128,8 @@ static int acpi_pm_prepare(void)
142 int error = __acpi_pm_prepare(); 128 int error = __acpi_pm_prepare();
143 129
144 if (!error) 130 if (!error)
145 acpi_disable_all_gpes(); 131 acpi_pm_freeze();
132
146 return error; 133 return error;
147} 134}
148 135
@@ -253,11 +240,8 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
253 break; 240 break;
254 } 241 }
255 242
256 /* If ACPI is not enabled by the BIOS, we need to enable it here. */ 243 /* This violates the spec but is required for bug compatibility. */
257 if (set_sci_en_on_resume) 244 acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1);
258 acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1);
259 else
260 acpi_enable();
261 245
262 /* Reprogram control registers and execute _BFS */ 246 /* Reprogram control registers and execute _BFS */
263 acpi_leave_sleep_state_prep(acpi_state); 247 acpi_leave_sleep_state_prep(acpi_state);
@@ -275,6 +259,8 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
275 * acpi_leave_sleep_state will reenable specific GPEs later 259 * acpi_leave_sleep_state will reenable specific GPEs later
276 */ 260 */
277 acpi_disable_all_gpes(); 261 acpi_disable_all_gpes();
262 /* Allow EC transactions to happen. */
263 acpi_ec_unblock_transactions_early();
278 264
279 local_irq_restore(flags); 265 local_irq_restore(flags);
280 printk(KERN_DEBUG "Back to C!\n"); 266 printk(KERN_DEBUG "Back to C!\n");
@@ -286,6 +272,12 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
286 return ACPI_SUCCESS(status) ? 0 : -EFAULT; 272 return ACPI_SUCCESS(status) ? 0 : -EFAULT;
287} 273}
288 274
275static void acpi_suspend_finish(void)
276{
277 acpi_ec_unblock_transactions();
278 acpi_pm_finish();
279}
280
289static int acpi_suspend_state_valid(suspend_state_t pm_state) 281static int acpi_suspend_state_valid(suspend_state_t pm_state)
290{ 282{
291 u32 acpi_state; 283 u32 acpi_state;
@@ -307,7 +299,7 @@ static struct platform_suspend_ops acpi_suspend_ops = {
307 .begin = acpi_suspend_begin, 299 .begin = acpi_suspend_begin,
308 .prepare_late = acpi_pm_prepare, 300 .prepare_late = acpi_pm_prepare,
309 .enter = acpi_suspend_enter, 301 .enter = acpi_suspend_enter,
310 .wake = acpi_pm_finish, 302 .wake = acpi_suspend_finish,
311 .end = acpi_pm_end, 303 .end = acpi_pm_end,
312}; 304};
313 305
@@ -333,9 +325,9 @@ static int acpi_suspend_begin_old(suspend_state_t pm_state)
333static struct platform_suspend_ops acpi_suspend_ops_old = { 325static struct platform_suspend_ops acpi_suspend_ops_old = {
334 .valid = acpi_suspend_state_valid, 326 .valid = acpi_suspend_state_valid,
335 .begin = acpi_suspend_begin_old, 327 .begin = acpi_suspend_begin_old,
336 .prepare_late = acpi_pm_disable_gpes, 328 .prepare_late = acpi_pm_freeze,
337 .enter = acpi_suspend_enter, 329 .enter = acpi_suspend_enter,
338 .wake = acpi_pm_finish, 330 .wake = acpi_suspend_finish,
339 .end = acpi_pm_end, 331 .end = acpi_pm_end,
340 .recover = acpi_pm_finish, 332 .recover = acpi_pm_finish,
341}; 333};
@@ -346,12 +338,6 @@ static int __init init_old_suspend_ordering(const struct dmi_system_id *d)
346 return 0; 338 return 0;
347} 339}
348 340
349static int __init init_set_sci_en_on_resume(const struct dmi_system_id *d)
350{
351 set_sci_en_on_resume = true;
352 return 0;
353}
354
355static struct dmi_system_id __initdata acpisleep_dmi_table[] = { 341static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
356 { 342 {
357 .callback = init_old_suspend_ordering, 343 .callback = init_old_suspend_ordering,
@@ -370,22 +356,6 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
370 }, 356 },
371 }, 357 },
372 { 358 {
373 .callback = init_set_sci_en_on_resume,
374 .ident = "Apple MacBook 1,1",
375 .matches = {
376 DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."),
377 DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"),
378 },
379 },
380 {
381 .callback = init_set_sci_en_on_resume,
382 .ident = "Apple MacMini 1,1",
383 .matches = {
384 DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."),
385 DMI_MATCH(DMI_PRODUCT_NAME, "Macmini1,1"),
386 },
387 },
388 {
389 .callback = init_old_suspend_ordering, 359 .callback = init_old_suspend_ordering,
390 .ident = "Asus Pundit P1-AH2 (M2N8L motherboard)", 360 .ident = "Asus Pundit P1-AH2 (M2N8L motherboard)",
391 .matches = { 361 .matches = {
@@ -394,94 +364,6 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
394 }, 364 },
395 }, 365 },
396 { 366 {
397 .callback = init_set_sci_en_on_resume,
398 .ident = "Toshiba Satellite L300",
399 .matches = {
400 DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
401 DMI_MATCH(DMI_PRODUCT_NAME, "Satellite L300"),
402 },
403 },
404 {
405 .callback = init_set_sci_en_on_resume,
406 .ident = "Hewlett-Packard HP G7000 Notebook PC",
407 .matches = {
408 DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
409 DMI_MATCH(DMI_PRODUCT_NAME, "HP G7000 Notebook PC"),
410 },
411 },
412 {
413 .callback = init_set_sci_en_on_resume,
414 .ident = "Hewlett-Packard HP Pavilion dv3 Notebook PC",
415 .matches = {
416 DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
417 DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv3 Notebook PC"),
418 },
419 },
420 {
421 .callback = init_set_sci_en_on_resume,
422 .ident = "Hewlett-Packard Pavilion dv4",
423 .matches = {
424 DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
425 DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4"),
426 },
427 },
428 {
429 .callback = init_set_sci_en_on_resume,
430 .ident = "Hewlett-Packard Pavilion dv7",
431 .matches = {
432 DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
433 DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv7"),
434 },
435 },
436 {
437 .callback = init_set_sci_en_on_resume,
438 .ident = "Hewlett-Packard Compaq Presario C700 Notebook PC",
439 .matches = {
440 DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
441 DMI_MATCH(DMI_PRODUCT_NAME, "Compaq Presario C700 Notebook PC"),
442 },
443 },
444 {
445 .callback = init_set_sci_en_on_resume,
446 .ident = "Hewlett-Packard Compaq Presario CQ40 Notebook PC",
447 .matches = {
448 DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
449 DMI_MATCH(DMI_PRODUCT_NAME, "Compaq Presario CQ40 Notebook PC"),
450 },
451 },
452 {
453 .callback = init_set_sci_en_on_resume,
454 .ident = "Lenovo ThinkPad T410",
455 .matches = {
456 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
457 DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T410"),
458 },
459 },
460 {
461 .callback = init_set_sci_en_on_resume,
462 .ident = "Lenovo ThinkPad T510",
463 .matches = {
464 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
465 DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T510"),
466 },
467 },
468 {
469 .callback = init_set_sci_en_on_resume,
470 .ident = "Lenovo ThinkPad W510",
471 .matches = {
472 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
473 DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W510"),
474 },
475 },
476 {
477 .callback = init_set_sci_en_on_resume,
478 .ident = "Lenovo ThinkPad X201[s]",
479 .matches = {
480 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
481 DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201"),
482 },
483 },
484 {
485 .callback = init_old_suspend_ordering, 367 .callback = init_old_suspend_ordering,
486 .ident = "Panasonic CF51-2L", 368 .ident = "Panasonic CF51-2L",
487 .matches = { 369 .matches = {
@@ -490,30 +372,6 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
490 DMI_MATCH(DMI_BOARD_NAME, "CF51-2L"), 372 DMI_MATCH(DMI_BOARD_NAME, "CF51-2L"),
491 }, 373 },
492 }, 374 },
493 {
494 .callback = init_set_sci_en_on_resume,
495 .ident = "Dell Studio 1558",
496 .matches = {
497 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
498 DMI_MATCH(DMI_PRODUCT_NAME, "Studio 1558"),
499 },
500 },
501 {
502 .callback = init_set_sci_en_on_resume,
503 .ident = "Dell Studio 1557",
504 .matches = {
505 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
506 DMI_MATCH(DMI_PRODUCT_NAME, "Studio 1557"),
507 },
508 },
509 {
510 .callback = init_set_sci_en_on_resume,
511 .ident = "Dell Studio 1555",
512 .matches = {
513 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
514 DMI_MATCH(DMI_PRODUCT_NAME, "Studio 1555"),
515 },
516 },
517 {}, 375 {},
518}; 376};
519#endif /* CONFIG_SUSPEND */ 377#endif /* CONFIG_SUSPEND */
@@ -586,6 +444,7 @@ static int acpi_hibernation_enter(void)
586static void acpi_hibernation_finish(void) 444static void acpi_hibernation_finish(void)
587{ 445{
588 hibernate_nvs_free(); 446 hibernate_nvs_free();
447 acpi_ec_unblock_transactions();
589 acpi_pm_finish(); 448 acpi_pm_finish();
590} 449}
591 450
@@ -606,19 +465,13 @@ static void acpi_hibernation_leave(void)
606 } 465 }
607 /* Restore the NVS memory area */ 466 /* Restore the NVS memory area */
608 hibernate_nvs_restore(); 467 hibernate_nvs_restore();
468 /* Allow EC transactions to happen. */
469 acpi_ec_unblock_transactions_early();
609} 470}
610 471
611static int acpi_pm_pre_restore(void) 472static void acpi_pm_thaw(void)
612{ 473{
613 acpi_disable_all_gpes(); 474 acpi_ec_unblock_transactions();
614 acpi_os_wait_events_complete(NULL);
615 acpi_ec_suspend_transactions();
616 return 0;
617}
618
619static void acpi_pm_restore_cleanup(void)
620{
621 acpi_ec_resume_transactions();
622 acpi_enable_all_runtime_gpes(); 475 acpi_enable_all_runtime_gpes();
623} 476}
624 477
@@ -630,8 +483,8 @@ static struct platform_hibernation_ops acpi_hibernation_ops = {
630 .prepare = acpi_pm_prepare, 483 .prepare = acpi_pm_prepare,
631 .enter = acpi_hibernation_enter, 484 .enter = acpi_hibernation_enter,
632 .leave = acpi_hibernation_leave, 485 .leave = acpi_hibernation_leave,
633 .pre_restore = acpi_pm_pre_restore, 486 .pre_restore = acpi_pm_freeze,
634 .restore_cleanup = acpi_pm_restore_cleanup, 487 .restore_cleanup = acpi_pm_thaw,
635}; 488};
636 489
637/** 490/**
@@ -663,12 +516,9 @@ static int acpi_hibernation_begin_old(void)
663 516
664static int acpi_hibernation_pre_snapshot_old(void) 517static int acpi_hibernation_pre_snapshot_old(void)
665{ 518{
666 int error = acpi_pm_disable_gpes(); 519 acpi_pm_freeze();
667 520 hibernate_nvs_save();
668 if (!error) 521 return 0;
669 hibernate_nvs_save();
670
671 return error;
672} 522}
673 523
674/* 524/*
@@ -680,11 +530,11 @@ static struct platform_hibernation_ops acpi_hibernation_ops_old = {
680 .end = acpi_pm_end, 530 .end = acpi_pm_end,
681 .pre_snapshot = acpi_hibernation_pre_snapshot_old, 531 .pre_snapshot = acpi_hibernation_pre_snapshot_old,
682 .finish = acpi_hibernation_finish, 532 .finish = acpi_hibernation_finish,
683 .prepare = acpi_pm_disable_gpes, 533 .prepare = acpi_pm_freeze,
684 .enter = acpi_hibernation_enter, 534 .enter = acpi_hibernation_enter,
685 .leave = acpi_hibernation_leave, 535 .leave = acpi_hibernation_leave,
686 .pre_restore = acpi_pm_pre_restore, 536 .pre_restore = acpi_pm_freeze,
687 .restore_cleanup = acpi_pm_restore_cleanup, 537 .restore_cleanup = acpi_pm_thaw,
688 .recover = acpi_pm_finish, 538 .recover = acpi_pm_finish,
689}; 539};
690#endif /* CONFIG_HIBERNATION */ 540#endif /* CONFIG_HIBERNATION */
diff --git a/drivers/acpi/sleep.h b/drivers/acpi/sleep.h
index 8a8f3b3382a6..25b8bd149284 100644
--- a/drivers/acpi/sleep.h
+++ b/drivers/acpi/sleep.h
@@ -1,6 +1,6 @@
1 1
2extern u8 sleep_states[]; 2extern u8 sleep_states[];
3extern int acpi_suspend (u32 state); 3extern int acpi_suspend(u32 state);
4 4
5extern void acpi_enable_wakeup_device_prep(u8 sleep_state); 5extern void acpi_enable_wakeup_device_prep(u8 sleep_state);
6extern void acpi_enable_wakeup_device(u8 sleep_state); 6extern void acpi_enable_wakeup_device(u8 sleep_state);
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index 8a0ed2800e63..f336bca7c450 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -213,7 +213,7 @@ acpi_table_parse_entries(char *id,
213 unsigned long table_end; 213 unsigned long table_end;
214 acpi_size tbl_size; 214 acpi_size tbl_size;
215 215
216 if (acpi_disabled && !acpi_ht) 216 if (acpi_disabled)
217 return -ENODEV; 217 return -ENODEV;
218 218
219 if (!handler) 219 if (!handler)
@@ -280,7 +280,7 @@ int __init acpi_table_parse(char *id, acpi_table_handler handler)
280 struct acpi_table_header *table = NULL; 280 struct acpi_table_header *table = NULL;
281 acpi_size tbl_size; 281 acpi_size tbl_size;
282 282
283 if (acpi_disabled && !acpi_ht) 283 if (acpi_disabled)
284 return -ENODEV; 284 return -ENODEV;
285 285
286 if (!handler) 286 if (!handler)
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index a0c93b321482..9865d46f49a8 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -45,6 +45,7 @@
45#include <acpi/acpi_bus.h> 45#include <acpi/acpi_bus.h>
46#include <acpi/acpi_drivers.h> 46#include <acpi/acpi_drivers.h>
47#include <linux/suspend.h> 47#include <linux/suspend.h>
48#include <acpi/video.h>
48 49
49#define PREFIX "ACPI: " 50#define PREFIX "ACPI: "
50 51
@@ -65,11 +66,6 @@
65 66
66#define MAX_NAME_LEN 20 67#define MAX_NAME_LEN 20
67 68
68#define ACPI_VIDEO_DISPLAY_CRT 1
69#define ACPI_VIDEO_DISPLAY_TV 2
70#define ACPI_VIDEO_DISPLAY_DVI 3
71#define ACPI_VIDEO_DISPLAY_LCD 4
72
73#define _COMPONENT ACPI_VIDEO_COMPONENT 69#define _COMPONENT ACPI_VIDEO_COMPONENT
74ACPI_MODULE_NAME("video"); 70ACPI_MODULE_NAME("video");
75 71
@@ -1007,11 +1003,11 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
1007 result = acpi_video_init_brightness(device); 1003 result = acpi_video_init_brightness(device);
1008 if (result) 1004 if (result)
1009 return; 1005 return;
1010 name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); 1006 name = kasprintf(GFP_KERNEL, "acpi_video%d", count);
1011 if (!name) 1007 if (!name)
1012 return; 1008 return;
1009 count++;
1013 1010
1014 sprintf(name, "acpi_video%d", count++);
1015 memset(&props, 0, sizeof(struct backlight_properties)); 1011 memset(&props, 0, sizeof(struct backlight_properties));
1016 props.max_brightness = device->brightness->count - 3; 1012 props.max_brightness = device->brightness->count - 3;
1017 device->backlight = backlight_device_register(name, NULL, device, 1013 device->backlight = backlight_device_register(name, NULL, device,
@@ -1067,10 +1063,10 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
1067 if (device->cap._DCS && device->cap._DSS) { 1063 if (device->cap._DCS && device->cap._DSS) {
1068 static int count; 1064 static int count;
1069 char *name; 1065 char *name;
1070 name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); 1066 name = kasprintf(GFP_KERNEL, "acpi_video%d", count);
1071 if (!name) 1067 if (!name)
1072 return; 1068 return;
1073 sprintf(name, "acpi_video%d", count++); 1069 count++;
1074 device->output_dev = video_output_register(name, 1070 device->output_dev = video_output_register(name,
1075 NULL, device, &acpi_output_properties); 1071 NULL, device, &acpi_output_properties);
1076 kfree(name); 1072 kfree(name);
@@ -1748,11 +1744,27 @@ acpi_video_get_device_attr(struct acpi_video_bus *video, unsigned long device_id
1748} 1744}
1749 1745
1750static int 1746static int
1747acpi_video_get_device_type(struct acpi_video_bus *video,
1748 unsigned long device_id)
1749{
1750 struct acpi_video_enumerated_device *ids;
1751 int i;
1752
1753 for (i = 0; i < video->attached_count; i++) {
1754 ids = &video->attached_array[i];
1755 if ((ids->value.int_val & 0xffff) == device_id)
1756 return ids->value.int_val;
1757 }
1758
1759 return 0;
1760}
1761
1762static int
1751acpi_video_bus_get_one_device(struct acpi_device *device, 1763acpi_video_bus_get_one_device(struct acpi_device *device,
1752 struct acpi_video_bus *video) 1764 struct acpi_video_bus *video)
1753{ 1765{
1754 unsigned long long device_id; 1766 unsigned long long device_id;
1755 int status; 1767 int status, device_type;
1756 struct acpi_video_device *data; 1768 struct acpi_video_device *data;
1757 struct acpi_video_device_attrib* attribute; 1769 struct acpi_video_device_attrib* attribute;
1758 1770
@@ -1797,8 +1809,25 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
1797 } 1809 }
1798 if(attribute->bios_can_detect) 1810 if(attribute->bios_can_detect)
1799 data->flags.bios = 1; 1811 data->flags.bios = 1;
1800 } else 1812 } else {
1801 data->flags.unknown = 1; 1813 /* Check for legacy IDs */
1814 device_type = acpi_video_get_device_type(video,
1815 device_id);
1816 /* Ignore bits 16 and 18-20 */
1817 switch (device_type & 0xffe2ffff) {
1818 case ACPI_VIDEO_DISPLAY_LEGACY_MONITOR:
1819 data->flags.crt = 1;
1820 break;
1821 case ACPI_VIDEO_DISPLAY_LEGACY_PANEL:
1822 data->flags.lcd = 1;
1823 break;
1824 case ACPI_VIDEO_DISPLAY_LEGACY_TV:
1825 data->flags.tvout = 1;
1826 break;
1827 default:
1828 data->flags.unknown = 1;
1829 }
1830 }
1802 1831
1803 acpi_video_device_bind(video, data); 1832 acpi_video_device_bind(video, data);
1804 acpi_video_device_find_cap(data); 1833 acpi_video_device_find_cap(data);
@@ -2032,6 +2061,71 @@ out:
2032 return result; 2061 return result;
2033} 2062}
2034 2063
2064int acpi_video_get_edid(struct acpi_device *device, int type, int device_id,
2065 void **edid)
2066{
2067 struct acpi_video_bus *video;
2068 struct acpi_video_device *video_device;
2069 union acpi_object *buffer = NULL;
2070 acpi_status status;
2071 int i, length;
2072
2073 if (!device || !acpi_driver_data(device))
2074 return -EINVAL;
2075
2076 video = acpi_driver_data(device);
2077
2078 for (i = 0; i < video->attached_count; i++) {
2079 video_device = video->attached_array[i].bind_info;
2080 length = 256;
2081
2082 if (!video_device)
2083 continue;
2084
2085 if (type) {
2086 switch (type) {
2087 case ACPI_VIDEO_DISPLAY_CRT:
2088 if (!video_device->flags.crt)
2089 continue;
2090 break;
2091 case ACPI_VIDEO_DISPLAY_TV:
2092 if (!video_device->flags.tvout)
2093 continue;
2094 break;
2095 case ACPI_VIDEO_DISPLAY_DVI:
2096 if (!video_device->flags.dvi)
2097 continue;
2098 break;
2099 case ACPI_VIDEO_DISPLAY_LCD:
2100 if (!video_device->flags.lcd)
2101 continue;
2102 break;
2103 }
2104 } else if (video_device->device_id != device_id) {
2105 continue;
2106 }
2107
2108 status = acpi_video_device_EDID(video_device, &buffer, length);
2109
2110 if (ACPI_FAILURE(status) || !buffer ||
2111 buffer->type != ACPI_TYPE_BUFFER) {
2112 length = 128;
2113 status = acpi_video_device_EDID(video_device, &buffer,
2114 length);
2115 if (ACPI_FAILURE(status) || !buffer ||
2116 buffer->type != ACPI_TYPE_BUFFER) {
2117 continue;
2118 }
2119 }
2120
2121 *edid = buffer->buffer.pointer;
2122 return length;
2123 }
2124
2125 return -ENODEV;
2126}
2127EXPORT_SYMBOL(acpi_video_get_edid);
2128
2035static int 2129static int
2036acpi_video_bus_get_devices(struct acpi_video_bus *video, 2130acpi_video_bus_get_devices(struct acpi_video_bus *video,
2037 struct acpi_device *device) 2131 struct acpi_device *device)
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
index fc2f26b9b407..c5fef01b3c95 100644
--- a/drivers/acpi/video_detect.c
+++ b/drivers/acpi/video_detect.c
@@ -250,7 +250,7 @@ static int __init acpi_backlight(char *str)
250 ACPI_VIDEO_BACKLIGHT_FORCE_VENDOR; 250 ACPI_VIDEO_BACKLIGHT_FORCE_VENDOR;
251 if (!strcmp("video", str)) 251 if (!strcmp("video", str))
252 acpi_video_support |= 252 acpi_video_support |=
253 ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VIDEO; 253 ACPI_VIDEO_BACKLIGHT_FORCE_VIDEO;
254 } 254 }
255 return 1; 255 return 1;
256} 256}
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index e68541f662b9..aa85a98d3a4f 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -57,6 +57,8 @@ config SATA_PMP
57 This option adds support for SATA Port Multipliers 57 This option adds support for SATA Port Multipliers
58 (the SATA version of an ethernet hub, or SAS expander). 58 (the SATA version of an ethernet hub, or SAS expander).
59 59
60comment "Controllers with non-SFF native interface"
61
60config SATA_AHCI 62config SATA_AHCI
61 tristate "AHCI SATA support" 63 tristate "AHCI SATA support"
62 depends on PCI 64 depends on PCI
@@ -73,11 +75,12 @@ config SATA_AHCI_PLATFORM
73 75
74 If unsure, say N. 76 If unsure, say N.
75 77
76config SATA_SIL24 78config SATA_FSL
77 tristate "Silicon Image 3124/3132 SATA support" 79 tristate "Freescale 3.0Gbps SATA support"
78 depends on PCI 80 depends on FSL_SOC
79 help 81 help
80 This option enables support for Silicon Image 3124/3132 Serial ATA. 82 This option enables support for Freescale 3.0Gbps SATA controller.
83 It can be found on MPC837x and MPC8315.
81 84
82 If unsure, say N. 85 If unsure, say N.
83 86
@@ -87,12 +90,11 @@ config SATA_INIC162X
87 help 90 help
88 This option enables support for Initio 162x Serial ATA. 91 This option enables support for Initio 162x Serial ATA.
89 92
90config SATA_FSL 93config SATA_SIL24
91 tristate "Freescale 3.0Gbps SATA support" 94 tristate "Silicon Image 3124/3132 SATA support"
92 depends on FSL_SOC 95 depends on PCI
93 help 96 help
94 This option enables support for Freescale 3.0Gbps SATA controller. 97 This option enables support for Silicon Image 3124/3132 Serial ATA.
95 It can be found on MPC837x and MPC8315.
96 98
97 If unsure, say N. 99 If unsure, say N.
98 100
@@ -116,15 +118,65 @@ config ATA_SFF
116 118
117if ATA_SFF 119if ATA_SFF
118 120
119config SATA_SVW 121comment "SFF controllers with custom DMA interface"
120 tristate "ServerWorks Frodo / Apple K2 SATA support" 122
123config PDC_ADMA
124 tristate "Pacific Digital ADMA support"
121 depends on PCI 125 depends on PCI
122 help 126 help
123 This option enables support for Broadcom/Serverworks/Apple K2 127 This option enables support for Pacific Digital ADMA controllers
124 SATA support. 128
129 If unsure, say N.
130
131config PATA_MPC52xx
132 tristate "Freescale MPC52xx SoC internal IDE"
133 depends on PPC_MPC52xx && PPC_BESTCOMM
134 select PPC_BESTCOMM_ATA
135 help
136 This option enables support for integrated IDE controller
137 of the Freescale MPC52xx SoC.
138
139 If unsure, say N.
140
141config PATA_OCTEON_CF
142 tristate "OCTEON Boot Bus Compact Flash support"
143 depends on CPU_CAVIUM_OCTEON
144 help
145 This option enables a polled compact flash driver for use with
146 compact flash cards attached to the OCTEON boot bus.
147
148 If unsure, say N.
149
150config SATA_QSTOR
151 tristate "Pacific Digital SATA QStor support"
152 depends on PCI
153 help
154 This option enables support for Pacific Digital Serial ATA QStor.
155
156 If unsure, say N.
157
158config SATA_SX4
159 tristate "Promise SATA SX4 support (Experimental)"
160 depends on PCI && EXPERIMENTAL
161 help
162 This option enables support for Promise Serial ATA SX4.
125 163
126 If unsure, say N. 164 If unsure, say N.
127 165
166config ATA_BMDMA
167 bool "ATA BMDMA support"
168 default y
169 help
170 This option adds support for SFF ATA controllers with BMDMA
171 capability. BMDMA stands for bus-master DMA and is the
172 de facto DMA interface for SFF controllers.
173
174 If unsure, say Y.
175
176if ATA_BMDMA
177
178comment "SATA SFF controllers with BMDMA"
179
128config ATA_PIIX 180config ATA_PIIX
129 tristate "Intel ESB, ICH, PIIX3, PIIX4 PATA/SATA support" 181 tristate "Intel ESB, ICH, PIIX3, PIIX4 PATA/SATA support"
130 depends on PCI 182 depends on PCI
@@ -152,22 +204,6 @@ config SATA_NV
152 204
153 If unsure, say N. 205 If unsure, say N.
154 206
155config PDC_ADMA
156 tristate "Pacific Digital ADMA support"
157 depends on PCI
158 help
159 This option enables support for Pacific Digital ADMA controllers
160
161 If unsure, say N.
162
163config SATA_QSTOR
164 tristate "Pacific Digital SATA QStor support"
165 depends on PCI
166 help
167 This option enables support for Pacific Digital Serial ATA QStor.
168
169 If unsure, say N.
170
171config SATA_PROMISE 207config SATA_PROMISE
172 tristate "Promise SATA TX2/TX4 support" 208 tristate "Promise SATA TX2/TX4 support"
173 depends on PCI 209 depends on PCI
@@ -176,14 +212,6 @@ config SATA_PROMISE
176 212
177 If unsure, say N. 213 If unsure, say N.
178 214
179config SATA_SX4
180 tristate "Promise SATA SX4 support (Experimental)"
181 depends on PCI && EXPERIMENTAL
182 help
183 This option enables support for Promise Serial ATA SX4.
184
185 If unsure, say N.
186
187config SATA_SIL 215config SATA_SIL
188 tristate "Silicon Image SATA support" 216 tristate "Silicon Image SATA support"
189 depends on PCI 217 depends on PCI
@@ -203,6 +231,15 @@ config SATA_SIS
203 enable the PATA_SIS driver in the config. 231 enable the PATA_SIS driver in the config.
204 If unsure, say N. 232 If unsure, say N.
205 233
234config SATA_SVW
235 tristate "ServerWorks Frodo / Apple K2 SATA support"
236 depends on PCI
237 help
238 This option enables support for Broadcom/Serverworks/Apple K2
239 SATA support.
240
241 If unsure, say N.
242
206config SATA_ULI 243config SATA_ULI
207 tristate "ULi Electronics SATA support" 244 tristate "ULi Electronics SATA support"
208 depends on PCI 245 depends on PCI
@@ -227,14 +264,7 @@ config SATA_VITESSE
227 264
228 If unsure, say N. 265 If unsure, say N.
229 266
230config PATA_ACPI 267comment "PATA SFF controllers with BMDMA"
231 tristate "ACPI firmware driver for PATA"
232 depends on ATA_ACPI
233 help
234 This option enables an ACPI method driver which drives
235 motherboard PATA controller interfaces through the ACPI
236 firmware in the BIOS. This driver can sometimes handle
237 otherwise unsupported hardware.
238 268
239config PATA_ALI 269config PATA_ALI
240 tristate "ALi PATA support" 270 tristate "ALi PATA support"
@@ -262,40 +292,30 @@ config PATA_ARTOP
262 292
263 If unsure, say N. 293 If unsure, say N.
264 294
265config PATA_ATP867X 295config PATA_ATIIXP
266 tristate "ARTOP/Acard ATP867X PATA support" 296 tristate "ATI PATA support"
267 depends on PCI 297 depends on PCI
268 help 298 help
269 This option enables support for ARTOP/Acard ATP867X PATA 299 This option enables support for the ATI ATA interfaces
270 controllers. 300 found on the many ATI chipsets.
271
272 If unsure, say N.
273
274config PATA_AT32
275 tristate "Atmel AVR32 PATA support (Experimental)"
276 depends on AVR32 && PLATFORM_AT32AP && EXPERIMENTAL
277 help
278 This option enables support for the IDE devices on the
279 Atmel AT32AP platform.
280 301
281 If unsure, say N. 302 If unsure, say N.
282 303
283config PATA_ATIIXP 304config PATA_ATP867X
284 tristate "ATI PATA support" 305 tristate "ARTOP/Acard ATP867X PATA support"
285 depends on PCI 306 depends on PCI
286 help 307 help
287 This option enables support for the ATI ATA interfaces 308 This option enables support for ARTOP/Acard ATP867X PATA
288 found on the many ATI chipsets. 309 controllers.
289 310
290 If unsure, say N. 311 If unsure, say N.
291 312
292config PATA_CMD640_PCI 313config PATA_BF54X
293 tristate "CMD640 PCI PATA support (Experimental)" 314 tristate "Blackfin 54x ATAPI support"
294 depends on PCI && EXPERIMENTAL 315 depends on BF542 || BF548 || BF549
295 help 316 help
296 This option enables support for the CMD640 PCI IDE 317 This option enables support for the built-in ATAPI controller on
297 interface chip. Only the primary channel is currently 318 Blackfin 54x family chips.
298 supported.
299 319
300 If unsure, say N. 320 If unsure, say N.
301 321
@@ -362,15 +382,6 @@ config PATA_EFAR
362 382
363 If unsure, say N. 383 If unsure, say N.
364 384
365config ATA_GENERIC
366 tristate "Generic ATA support"
367 depends on PCI
368 help
369 This option enables support for generic BIOS configured
370 ATA controllers via the new ATA layer
371
372 If unsure, say N.
373
374config PATA_HPT366 385config PATA_HPT366
375 tristate "HPT 366/368 PATA support" 386 tristate "HPT 366/368 PATA support"
376 depends on PCI 387 depends on PCI
@@ -415,12 +426,20 @@ config PATA_HPT3X3_DMA
415 controllers. Enable with care as there are still some 426 controllers. Enable with care as there are still some
416 problems with DMA on this chipset. 427 problems with DMA on this chipset.
417 428
418config PATA_ISAPNP 429config PATA_ICSIDE
419 tristate "ISA Plug and Play PATA support" 430 tristate "Acorn ICS PATA support"
420 depends on ISAPNP 431 depends on ARM && ARCH_ACORN
421 help 432 help
422 This option enables support for ISA plug & play ATA 433 On Acorn systems, say Y here if you wish to use the ICS PATA
423 controllers such as those found on old soundcards. 434 interface card. This is not required for ICS partition support.
435 If you are unsure, say N to this.
436
437config PATA_IT8213
438 tristate "IT8213 PATA support (Experimental)"
439 depends on PCI && EXPERIMENTAL
440 help
441 This option enables support for the ITE 821 PATA
442 controllers via the new ATA layer.
424 443
425 If unsure, say N. 444 If unsure, say N.
426 445
@@ -434,15 +453,6 @@ config PATA_IT821X
434 453
435 If unsure, say N. 454 If unsure, say N.
436 455
437config PATA_IT8213
438 tristate "IT8213 PATA support (Experimental)"
439 depends on PCI && EXPERIMENTAL
440 help
441 This option enables support for the ITE 821 PATA
442 controllers via the new ATA layer.
443
444 If unsure, say N.
445
446config PATA_JMICRON 456config PATA_JMICRON
447 tristate "JMicron PATA support" 457 tristate "JMicron PATA support"
448 depends on PCI 458 depends on PCI
@@ -452,23 +462,14 @@ config PATA_JMICRON
452 462
453 If unsure, say N. 463 If unsure, say N.
454 464
455config PATA_LEGACY 465config PATA_MACIO
456 tristate "Legacy ISA PATA support (Experimental)" 466 tristate "Apple PowerMac/PowerBook internal 'MacIO' IDE"
457 depends on (ISA || PCI) && EXPERIMENTAL 467 depends on PPC_PMAC
458 help
459 This option enables support for ISA/VLB/PCI bus legacy PATA
460 ports and allows them to be accessed via the new ATA layer.
461
462 If unsure, say N.
463
464config PATA_TRIFLEX
465 tristate "Compaq Triflex PATA support"
466 depends on PCI
467 help 468 help
468 Enable support for the Compaq 'Triflex' IDE controller as found 469 Most IDE capable PowerMacs have IDE busses driven by a variant
469 on many Compaq Pentium-Pro systems, via the new ATA layer. 470 of this controller which is part of the Apple chipset used on
470 471 most PowerMac models. Some models have multiple busses using
471 If unsure, say N. 472 different chipsets, though generally, MacIO is one of them.
472 473
473config PATA_MARVELL 474config PATA_MARVELL
474 tristate "Marvell PATA support via legacy mode" 475 tristate "Marvell PATA support via legacy mode"
@@ -481,32 +482,6 @@ config PATA_MARVELL
481 482
482 If unsure, say N. 483 If unsure, say N.
483 484
484config PATA_MPC52xx
485 tristate "Freescale MPC52xx SoC internal IDE"
486 depends on PPC_MPC52xx && PPC_BESTCOMM
487 select PPC_BESTCOMM_ATA
488 help
489 This option enables support for integrated IDE controller
490 of the Freescale MPC52xx SoC.
491
492 If unsure, say N.
493
494config PATA_MPIIX
495 tristate "Intel PATA MPIIX support"
496 depends on PCI
497 help
498 This option enables support for MPIIX PATA support.
499
500 If unsure, say N.
501
502config PATA_OLDPIIX
503 tristate "Intel PATA old PIIX support"
504 depends on PCI
505 help
506 This option enables support for early PIIX PATA support.
507
508 If unsure, say N.
509
510config PATA_NETCELL 485config PATA_NETCELL
511 tristate "NETCELL Revolution RAID support" 486 tristate "NETCELL Revolution RAID support"
512 depends on PCI 487 depends on PCI
@@ -525,15 +500,6 @@ config PATA_NINJA32
525 500
526 If unsure, say N. 501 If unsure, say N.
527 502
528config PATA_NS87410
529 tristate "Nat Semi NS87410 PATA support"
530 depends on PCI
531 help
532 This option enables support for the National Semiconductor
533 NS87410 PCI-IDE controller.
534
535 If unsure, say N.
536
537config PATA_NS87415 503config PATA_NS87415
538 tristate "Nat Semi NS87415 PATA support" 504 tristate "Nat Semi NS87415 PATA support"
539 depends on PCI 505 depends on PCI
@@ -543,12 +509,11 @@ config PATA_NS87415
543 509
544 If unsure, say N. 510 If unsure, say N.
545 511
546config PATA_OPTI 512config PATA_OLDPIIX
547 tristate "OPTI621/6215 PATA support (Very Experimental)" 513 tristate "Intel PATA old PIIX support"
548 depends on PCI && EXPERIMENTAL 514 depends on PCI
549 help 515 help
550 This option enables full PIO support for the early Opti ATA 516 This option enables support for early PIIX PATA support.
551 controllers found on some old motherboards.
552 517
553 If unsure, say N. 518 If unsure, say N.
554 519
@@ -562,24 +527,6 @@ config PATA_OPTIDMA
562 527
563 If unsure, say N. 528 If unsure, say N.
564 529
565config PATA_PALMLD
566 tristate "Palm LifeDrive PATA support"
567 depends on MACH_PALMLD
568 help
569 This option enables support for Palm LifeDrive's internal ATA
570 port via the new ATA layer.
571
572 If unsure, say N.
573
574config PATA_PCMCIA
575 tristate "PCMCIA PATA support"
576 depends on PCMCIA
577 help
578 This option enables support for PCMCIA ATA interfaces, including
579 compact flash card adapters via the new ATA layer.
580
581 If unsure, say N.
582
583config PATA_PDC2027X 530config PATA_PDC2027X
584 tristate "Promise PATA 2027x support" 531 tristate "Promise PATA 2027x support"
585 depends on PCI 532 depends on PCI
@@ -597,12 +544,6 @@ config PATA_PDC_OLD
597 544
598 If unsure, say N. 545 If unsure, say N.
599 546
600config PATA_QDI
601 tristate "QDI VLB PATA support"
602 depends on ISA
603 help
604 Support for QDI 6500 and 6580 PATA controllers on VESA local bus.
605
606config PATA_RADISYS 547config PATA_RADISYS
607 tristate "RADISYS 82600 PATA support (Experimental)" 548 tristate "RADISYS 82600 PATA support (Experimental)"
608 depends on PCI && EXPERIMENTAL 549 depends on PCI && EXPERIMENTAL
@@ -612,15 +553,6 @@ config PATA_RADISYS
612 553
613 If unsure, say N. 554 If unsure, say N.
614 555
615config PATA_RB532
616 tristate "RouterBoard 532 PATA CompactFlash support"
617 depends on MIKROTIK_RB532
618 help
619 This option enables support for the RouterBoard 532
620 PATA CompactFlash controller.
621
622 If unsure, say N.
623
624config PATA_RDC 556config PATA_RDC
625 tristate "RDC PATA support" 557 tristate "RDC PATA support"
626 depends on PCI 558 depends on PCI
@@ -631,21 +563,30 @@ config PATA_RDC
631 563
632 If unsure, say N. 564 If unsure, say N.
633 565
634config PATA_RZ1000 566config PATA_SC1200
635 tristate "PC Tech RZ1000 PATA support" 567 tristate "SC1200 PATA support"
636 depends on PCI 568 depends on PCI
637 help 569 help
638 This option enables basic support for the PC Tech RZ1000/1 570 This option enables support for the NatSemi/AMD SC1200 SoC
639 PATA controllers via the new ATA layer 571 companion chip used with the Geode processor family.
640 572
641 If unsure, say N. 573 If unsure, say N.
642 574
643config PATA_SC1200 575config PATA_SCC
644 tristate "SC1200 PATA support" 576 tristate "Toshiba's Cell Reference Set IDE support"
577 depends on PCI && PPC_CELLEB
578 help
579 This option enables support for the built-in IDE controller on
580 Toshiba Cell Reference Board.
581
582 If unsure, say N.
583
584config PATA_SCH
585 tristate "Intel SCH PATA support"
645 depends on PCI 586 depends on PCI
646 help 587 help
647 This option enables support for the NatSemi/AMD SC1200 SoC 588 This option enables support for Intel SCH PATA on the Intel
648 companion chip used with the Geode processor family. 589 SCH (US15W, US15L, UL11L) series host controllers.
649 590
650 If unsure, say N. 591 If unsure, say N.
651 592
@@ -683,6 +624,15 @@ config PATA_TOSHIBA
683 624
684 If unsure, say N. 625 If unsure, say N.
685 626
627config PATA_TRIFLEX
628 tristate "Compaq Triflex PATA support"
629 depends on PCI
630 help
631 Enable support for the Compaq 'Triflex' IDE controller as found
632 on many Compaq Pentium-Pro systems, via the new ATA layer.
633
634 If unsure, say N.
635
686config PATA_VIA 636config PATA_VIA
687 tristate "VIA PATA support" 637 tristate "VIA PATA support"
688 depends on PCI 638 depends on PCI
@@ -701,12 +651,99 @@ config PATA_WINBOND
701 651
702 If unsure, say N. 652 If unsure, say N.
703 653
704config PATA_WINBOND_VLB 654endif # ATA_BMDMA
705 tristate "Winbond W83759A VLB PATA support (Experimental)" 655
706 depends on ISA && EXPERIMENTAL 656comment "PIO-only SFF controllers"
657
658config PATA_AT32
659 tristate "Atmel AVR32 PATA support (Experimental)"
660 depends on AVR32 && PLATFORM_AT32AP && EXPERIMENTAL
707 help 661 help
708 Support for the Winbond W83759A controller on Vesa Local Bus 662 This option enables support for the IDE devices on the
709 systems. 663 Atmel AT32AP platform.
664
665 If unsure, say N.
666
667config PATA_AT91
668 tristate "PATA support for AT91SAM9260"
669 depends on ARM && ARCH_AT91
670 help
671 This option enables support for IDE devices on the Atmel AT91SAM9260 SoC.
672
673 If unsure, say N.
674
675config PATA_CMD640_PCI
676 tristate "CMD640 PCI PATA support (Experimental)"
677 depends on PCI && EXPERIMENTAL
678 help
679 This option enables support for the CMD640 PCI IDE
680 interface chip. Only the primary channel is currently
681 supported.
682
683 If unsure, say N.
684
685config PATA_ISAPNP
686 tristate "ISA Plug and Play PATA support"
687 depends on ISAPNP
688 help
689 This option enables support for ISA plug & play ATA
690 controllers such as those found on old soundcards.
691
692 If unsure, say N.
693
694config PATA_IXP4XX_CF
695 tristate "IXP4XX Compact Flash support"
696 depends on ARCH_IXP4XX
697 help
698 This option enables support for a Compact Flash connected on
699 the ixp4xx expansion bus. This driver had been written for
700 Loft/Avila boards in mind but can work with others.
701
702 If unsure, say N.
703
704config PATA_MPIIX
705 tristate "Intel PATA MPIIX support"
706 depends on PCI
707 help
708 This option enables support for MPIIX PATA support.
709
710 If unsure, say N.
711
712config PATA_NS87410
713 tristate "Nat Semi NS87410 PATA support"
714 depends on PCI
715 help
716 This option enables support for the National Semiconductor
717 NS87410 PCI-IDE controller.
718
719 If unsure, say N.
720
721config PATA_OPTI
722 tristate "OPTI621/6215 PATA support (Very Experimental)"
723 depends on PCI && EXPERIMENTAL
724 help
725 This option enables full PIO support for the early Opti ATA
726 controllers found on some old motherboards.
727
728 If unsure, say N.
729
730config PATA_PALMLD
731 tristate "Palm LifeDrive PATA support"
732 depends on MACH_PALMLD
733 help
734 This option enables support for Palm LifeDrive's internal ATA
735 port via the new ATA layer.
736
737 If unsure, say N.
738
739config PATA_PCMCIA
740 tristate "PCMCIA PATA support"
741 depends on PCMCIA
742 help
743 This option enables support for PCMCIA ATA interfaces, including
744 compact flash card adapters via the new ATA layer.
745
746 If unsure, say N.
710 747
711config HAVE_PATA_PLATFORM 748config HAVE_PATA_PLATFORM
712 bool 749 bool
@@ -725,14 +762,6 @@ config PATA_PLATFORM
725 762
726 If unsure, say N. 763 If unsure, say N.
727 764
728config PATA_AT91
729 tristate "PATA support for AT91SAM9260"
730 depends on ARM && ARCH_AT91
731 help
732 This option enables support for IDE devices on the Atmel AT91SAM9260 SoC.
733
734 If unsure, say N.
735
736config PATA_OF_PLATFORM 765config PATA_OF_PLATFORM
737 tristate "OpenFirmware platform device PATA support" 766 tristate "OpenFirmware platform device PATA support"
738 depends on PATA_PLATFORM && PPC_OF 767 depends on PATA_PLATFORM && PPC_OF
@@ -743,69 +772,65 @@ config PATA_OF_PLATFORM
743 772
744 If unsure, say N. 773 If unsure, say N.
745 774
746config PATA_ICSIDE 775config PATA_QDI
747 tristate "Acorn ICS PATA support" 776 tristate "QDI VLB PATA support"
748 depends on ARM && ARCH_ACORN 777 depends on ISA
749 help 778 help
750 On Acorn systems, say Y here if you wish to use the ICS PATA 779 Support for QDI 6500 and 6580 PATA controllers on VESA local bus.
751 interface card. This is not required for ICS partition support.
752 If you are unsure, say N to this.
753 780
754config PATA_IXP4XX_CF 781config PATA_RB532
755 tristate "IXP4XX Compact Flash support" 782 tristate "RouterBoard 532 PATA CompactFlash support"
756 depends on ARCH_IXP4XX 783 depends on MIKROTIK_RB532
757 help 784 help
758 This option enables support for a Compact Flash connected on 785 This option enables support for the RouterBoard 532
759 the ixp4xx expansion bus. This driver had been written for 786 PATA CompactFlash controller.
760 Loft/Avila boards in mind but can work with others.
761 787
762 If unsure, say N. 788 If unsure, say N.
763 789
764config PATA_OCTEON_CF 790config PATA_RZ1000
765 tristate "OCTEON Boot Bus Compact Flash support" 791 tristate "PC Tech RZ1000 PATA support"
766 depends on CPU_CAVIUM_OCTEON 792 depends on PCI
767 help 793 help
768 This option enables a polled compact flash driver for use with 794 This option enables basic support for the PC Tech RZ1000/1
769 compact flash cards attached to the OCTEON boot bus. 795 PATA controllers via the new ATA layer
770 796
771 If unsure, say N. 797 If unsure, say N.
772 798
773config PATA_SCC 799config PATA_WINBOND_VLB
774 tristate "Toshiba's Cell Reference Set IDE support" 800 tristate "Winbond W83759A VLB PATA support (Experimental)"
775 depends on PCI && PPC_CELLEB 801 depends on ISA && EXPERIMENTAL
776 help 802 help
777 This option enables support for the built-in IDE controller on 803 Support for the Winbond W83759A controller on Vesa Local Bus
778 Toshiba Cell Reference Board. 804 systems.
779 805
780 If unsure, say N. 806comment "Generic fallback / legacy drivers"
781 807
782config PATA_SCH 808config PATA_ACPI
783 tristate "Intel SCH PATA support" 809 tristate "ACPI firmware driver for PATA"
784 depends on PCI 810 depends on ATA_ACPI && ATA_BMDMA
785 help 811 help
786 This option enables support for Intel SCH PATA on the Intel 812 This option enables an ACPI method driver which drives
787 SCH (US15W, US15L, UL11L) series host controllers. 813 motherboard PATA controller interfaces through the ACPI
788 814 firmware in the BIOS. This driver can sometimes handle
789 If unsure, say N. 815 otherwise unsupported hardware.
790 816
791config PATA_BF54X 817config ATA_GENERIC
792 tristate "Blackfin 54x ATAPI support" 818 tristate "Generic ATA support"
793 depends on BF542 || BF548 || BF549 819 depends on PCI && ATA_BMDMA
794 help 820 help
795 This option enables support for the built-in ATAPI controller on 821 This option enables support for generic BIOS configured
796 Blackfin 54x family chips. 822 ATA controllers via the new ATA layer
797 823
798 If unsure, say N. 824 If unsure, say N.
799 825
800config PATA_MACIO 826config PATA_LEGACY
801 tristate "Apple PowerMac/PowerBook internal 'MacIO' IDE" 827 tristate "Legacy ISA PATA support (Experimental)"
802 depends on PPC_PMAC 828 depends on (ISA || PCI) && EXPERIMENTAL
803 help 829 help
804 Most IDE capable PowerMacs have IDE busses driven by a variant 830 This option enables support for ISA/VLB/PCI bus legacy PATA
805 of this controller which is part of the Apple chipset used on 831 ports and allows them to be accessed via the new ATA layer.
806 most PowerMac models. Some models have multiple busses using
807 different chipsets, though generally, MacIO is one of them.
808 832
833 If unsure, say N.
809 834
810endif # ATA_SFF 835endif # ATA_SFF
811endif # ATA 836endif # ATA
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index d0a93c4ad3ec..7ef89d73df63 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -1,33 +1,39 @@
1 1
2obj-$(CONFIG_ATA) += libata.o 2obj-$(CONFIG_ATA) += libata.o
3 3
4# non-SFF interface
4obj-$(CONFIG_SATA_AHCI) += ahci.o libahci.o 5obj-$(CONFIG_SATA_AHCI) += ahci.o libahci.o
5obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o 6obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o
6obj-$(CONFIG_SATA_SVW) += sata_svw.o 7obj-$(CONFIG_SATA_FSL) += sata_fsl.o
8obj-$(CONFIG_SATA_INIC162X) += sata_inic162x.o
9obj-$(CONFIG_SATA_SIL24) += sata_sil24.o
10
11# SFF w/ custom DMA
12obj-$(CONFIG_PDC_ADMA) += pdc_adma.o
13obj-$(CONFIG_PATA_MPC52xx) += pata_mpc52xx.o
14obj-$(CONFIG_PATA_OCTEON_CF) += pata_octeon_cf.o
15obj-$(CONFIG_SATA_QSTOR) += sata_qstor.o
16obj-$(CONFIG_SATA_SX4) += sata_sx4.o
17
18# SFF SATA w/ BMDMA
7obj-$(CONFIG_ATA_PIIX) += ata_piix.o 19obj-$(CONFIG_ATA_PIIX) += ata_piix.o
20obj-$(CONFIG_SATA_MV) += sata_mv.o
21obj-$(CONFIG_SATA_NV) += sata_nv.o
8obj-$(CONFIG_SATA_PROMISE) += sata_promise.o 22obj-$(CONFIG_SATA_PROMISE) += sata_promise.o
9obj-$(CONFIG_SATA_QSTOR) += sata_qstor.o
10obj-$(CONFIG_SATA_SIL) += sata_sil.o 23obj-$(CONFIG_SATA_SIL) += sata_sil.o
11obj-$(CONFIG_SATA_SIL24) += sata_sil24.o
12obj-$(CONFIG_SATA_VIA) += sata_via.o
13obj-$(CONFIG_SATA_VITESSE) += sata_vsc.o
14obj-$(CONFIG_SATA_SIS) += sata_sis.o 24obj-$(CONFIG_SATA_SIS) += sata_sis.o
15obj-$(CONFIG_SATA_SX4) += sata_sx4.o 25obj-$(CONFIG_SATA_SVW) += sata_svw.o
16obj-$(CONFIG_SATA_NV) += sata_nv.o
17obj-$(CONFIG_SATA_ULI) += sata_uli.o 26obj-$(CONFIG_SATA_ULI) += sata_uli.o
18obj-$(CONFIG_SATA_MV) += sata_mv.o 27obj-$(CONFIG_SATA_VIA) += sata_via.o
19obj-$(CONFIG_SATA_INIC162X) += sata_inic162x.o 28obj-$(CONFIG_SATA_VITESSE) += sata_vsc.o
20obj-$(CONFIG_PDC_ADMA) += pdc_adma.o
21obj-$(CONFIG_SATA_FSL) += sata_fsl.o
22obj-$(CONFIG_PATA_MACIO) += pata_macio.o
23 29
30# SFF PATA w/ BMDMA
24obj-$(CONFIG_PATA_ALI) += pata_ali.o 31obj-$(CONFIG_PATA_ALI) += pata_ali.o
25obj-$(CONFIG_PATA_AMD) += pata_amd.o 32obj-$(CONFIG_PATA_AMD) += pata_amd.o
26obj-$(CONFIG_PATA_ARTOP) += pata_artop.o 33obj-$(CONFIG_PATA_ARTOP) += pata_artop.o
27obj-$(CONFIG_PATA_ATP867X) += pata_atp867x.o
28obj-$(CONFIG_PATA_AT32) += pata_at32.o
29obj-$(CONFIG_PATA_ATIIXP) += pata_atiixp.o 34obj-$(CONFIG_PATA_ATIIXP) += pata_atiixp.o
30obj-$(CONFIG_PATA_CMD640_PCI) += pata_cmd640.o 35obj-$(CONFIG_PATA_ATP867X) += pata_atp867x.o
36obj-$(CONFIG_PATA_BF54X) += pata_bf54x.o
31obj-$(CONFIG_PATA_CMD64X) += pata_cmd64x.o 37obj-$(CONFIG_PATA_CMD64X) += pata_cmd64x.o
32obj-$(CONFIG_PATA_CS5520) += pata_cs5520.o 38obj-$(CONFIG_PATA_CS5520) += pata_cs5520.o
33obj-$(CONFIG_PATA_CS5530) += pata_cs5530.o 39obj-$(CONFIG_PATA_CS5530) += pata_cs5530.o
@@ -39,47 +45,50 @@ obj-$(CONFIG_PATA_HPT366) += pata_hpt366.o
39obj-$(CONFIG_PATA_HPT37X) += pata_hpt37x.o 45obj-$(CONFIG_PATA_HPT37X) += pata_hpt37x.o
40obj-$(CONFIG_PATA_HPT3X2N) += pata_hpt3x2n.o 46obj-$(CONFIG_PATA_HPT3X2N) += pata_hpt3x2n.o
41obj-$(CONFIG_PATA_HPT3X3) += pata_hpt3x3.o 47obj-$(CONFIG_PATA_HPT3X3) += pata_hpt3x3.o
42obj-$(CONFIG_PATA_ISAPNP) += pata_isapnp.o 48obj-$(CONFIG_PATA_ICSIDE) += pata_icside.o
43obj-$(CONFIG_PATA_IT821X) += pata_it821x.o
44obj-$(CONFIG_PATA_IT8213) += pata_it8213.o 49obj-$(CONFIG_PATA_IT8213) += pata_it8213.o
50obj-$(CONFIG_PATA_IT821X) += pata_it821x.o
45obj-$(CONFIG_PATA_JMICRON) += pata_jmicron.o 51obj-$(CONFIG_PATA_JMICRON) += pata_jmicron.o
52obj-$(CONFIG_PATA_MACIO) += pata_macio.o
53obj-$(CONFIG_PATA_MARVELL) += pata_marvell.o
46obj-$(CONFIG_PATA_NETCELL) += pata_netcell.o 54obj-$(CONFIG_PATA_NETCELL) += pata_netcell.o
47obj-$(CONFIG_PATA_NINJA32) += pata_ninja32.o 55obj-$(CONFIG_PATA_NINJA32) += pata_ninja32.o
48obj-$(CONFIG_PATA_NS87410) += pata_ns87410.o
49obj-$(CONFIG_PATA_NS87415) += pata_ns87415.o 56obj-$(CONFIG_PATA_NS87415) += pata_ns87415.o
50obj-$(CONFIG_PATA_OPTI) += pata_opti.o
51obj-$(CONFIG_PATA_OPTIDMA) += pata_optidma.o
52obj-$(CONFIG_PATA_MPC52xx) += pata_mpc52xx.o
53obj-$(CONFIG_PATA_MARVELL) += pata_marvell.o
54obj-$(CONFIG_PATA_MPIIX) += pata_mpiix.o
55obj-$(CONFIG_PATA_OLDPIIX) += pata_oldpiix.o 57obj-$(CONFIG_PATA_OLDPIIX) += pata_oldpiix.o
56obj-$(CONFIG_PATA_PALMLD) += pata_palmld.o 58obj-$(CONFIG_PATA_OPTIDMA) += pata_optidma.o
57obj-$(CONFIG_PATA_PCMCIA) += pata_pcmcia.o
58obj-$(CONFIG_PATA_PDC2027X) += pata_pdc2027x.o 59obj-$(CONFIG_PATA_PDC2027X) += pata_pdc2027x.o
59obj-$(CONFIG_PATA_PDC_OLD) += pata_pdc202xx_old.o 60obj-$(CONFIG_PATA_PDC_OLD) += pata_pdc202xx_old.o
60obj-$(CONFIG_PATA_QDI) += pata_qdi.o
61obj-$(CONFIG_PATA_RADISYS) += pata_radisys.o 61obj-$(CONFIG_PATA_RADISYS) += pata_radisys.o
62obj-$(CONFIG_PATA_RB532) += pata_rb532_cf.o
63obj-$(CONFIG_PATA_RDC) += pata_rdc.o 62obj-$(CONFIG_PATA_RDC) += pata_rdc.o
64obj-$(CONFIG_PATA_RZ1000) += pata_rz1000.o
65obj-$(CONFIG_PATA_SC1200) += pata_sc1200.o 63obj-$(CONFIG_PATA_SC1200) += pata_sc1200.o
64obj-$(CONFIG_PATA_SCC) += pata_scc.o
65obj-$(CONFIG_PATA_SCH) += pata_sch.o
66obj-$(CONFIG_PATA_SERVERWORKS) += pata_serverworks.o 66obj-$(CONFIG_PATA_SERVERWORKS) += pata_serverworks.o
67obj-$(CONFIG_PATA_SIL680) += pata_sil680.o 67obj-$(CONFIG_PATA_SIL680) += pata_sil680.o
68obj-$(CONFIG_PATA_SIS) += pata_sis.o
68obj-$(CONFIG_PATA_TOSHIBA) += pata_piccolo.o 69obj-$(CONFIG_PATA_TOSHIBA) += pata_piccolo.o
70obj-$(CONFIG_PATA_TRIFLEX) += pata_triflex.o
69obj-$(CONFIG_PATA_VIA) += pata_via.o 71obj-$(CONFIG_PATA_VIA) += pata_via.o
70obj-$(CONFIG_PATA_WINBOND) += pata_sl82c105.o 72obj-$(CONFIG_PATA_WINBOND) += pata_sl82c105.o
71obj-$(CONFIG_PATA_WINBOND_VLB) += pata_winbond.o 73
72obj-$(CONFIG_PATA_SIS) += pata_sis.o 74# SFF PIO only
73obj-$(CONFIG_PATA_TRIFLEX) += pata_triflex.o 75obj-$(CONFIG_PATA_AT32) += pata_at32.o
76obj-$(CONFIG_PATA_AT91) += pata_at91.o
77obj-$(CONFIG_PATA_CMD640_PCI) += pata_cmd640.o
78obj-$(CONFIG_PATA_ISAPNP) += pata_isapnp.o
74obj-$(CONFIG_PATA_IXP4XX_CF) += pata_ixp4xx_cf.o 79obj-$(CONFIG_PATA_IXP4XX_CF) += pata_ixp4xx_cf.o
75obj-$(CONFIG_PATA_SCC) += pata_scc.o 80obj-$(CONFIG_PATA_MPIIX) += pata_mpiix.o
76obj-$(CONFIG_PATA_SCH) += pata_sch.o 81obj-$(CONFIG_PATA_NS87410) += pata_ns87410.o
77obj-$(CONFIG_PATA_BF54X) += pata_bf54x.o 82obj-$(CONFIG_PATA_OPTI) += pata_opti.o
78obj-$(CONFIG_PATA_OCTEON_CF) += pata_octeon_cf.o 83obj-$(CONFIG_PATA_PCMCIA) += pata_pcmcia.o
84obj-$(CONFIG_PATA_PALMLD) += pata_palmld.o
79obj-$(CONFIG_PATA_PLATFORM) += pata_platform.o 85obj-$(CONFIG_PATA_PLATFORM) += pata_platform.o
80obj-$(CONFIG_PATA_AT91) += pata_at91.o
81obj-$(CONFIG_PATA_OF_PLATFORM) += pata_of_platform.o 86obj-$(CONFIG_PATA_OF_PLATFORM) += pata_of_platform.o
82obj-$(CONFIG_PATA_ICSIDE) += pata_icside.o 87obj-$(CONFIG_PATA_QDI) += pata_qdi.o
88obj-$(CONFIG_PATA_RB532) += pata_rb532_cf.o
89obj-$(CONFIG_PATA_RZ1000) += pata_rz1000.o
90obj-$(CONFIG_PATA_WINBOND_VLB) += pata_winbond.o
91
83# Should be last but two libata driver 92# Should be last but two libata driver
84obj-$(CONFIG_PATA_ACPI) += pata_acpi.o 93obj-$(CONFIG_PATA_ACPI) += pata_acpi.o
85# Should be last but one libata driver 94# Should be last but one libata driver
diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c
index 33fb614f9784..573158a9668d 100644
--- a/drivers/ata/ata_generic.c
+++ b/drivers/ata/ata_generic.c
@@ -155,7 +155,7 @@ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id
155 return rc; 155 return rc;
156 pcim_pin_device(dev); 156 pcim_pin_device(dev);
157 } 157 }
158 return ata_pci_sff_init_one(dev, ppi, &generic_sht, NULL, 0); 158 return ata_pci_bmdma_init_one(dev, ppi, &generic_sht, NULL, 0);
159} 159}
160 160
161static struct pci_device_id ata_generic[] = { 161static struct pci_device_id ata_generic[] = {
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index ec52fc618763..7409f98d2ae6 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -1589,7 +1589,7 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
1589 hpriv->map = piix_init_sata_map(pdev, port_info, 1589 hpriv->map = piix_init_sata_map(pdev, port_info,
1590 piix_map_db_table[ent->driver_data]); 1590 piix_map_db_table[ent->driver_data]);
1591 1591
1592 rc = ata_pci_sff_prepare_host(pdev, ppi, &host); 1592 rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host);
1593 if (rc) 1593 if (rc)
1594 return rc; 1594 return rc;
1595 host->private_data = hpriv; 1595 host->private_data = hpriv;
@@ -1626,7 +1626,7 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
1626 host->flags |= ATA_HOST_PARALLEL_SCAN; 1626 host->flags |= ATA_HOST_PARALLEL_SCAN;
1627 1627
1628 pci_set_master(pdev); 1628 pci_set_master(pdev);
1629 return ata_pci_sff_activate_host(host, ata_sff_interrupt, &piix_sht); 1629 return ata_pci_sff_activate_host(host, ata_bmdma_interrupt, &piix_sht);
1630} 1630}
1631 1631
1632static void piix_remove_one(struct pci_dev *pdev) 1632static void piix_remove_one(struct pci_dev *pdev)
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 1984a6e89e84..261f86d102e8 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -541,29 +541,11 @@ static int ahci_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
541 return -EINVAL; 541 return -EINVAL;
542} 542}
543 543
544static int ahci_is_device_present(void __iomem *port_mmio)
545{
546 u8 status = readl(port_mmio + PORT_TFDATA) & 0xff;
547
548 /* Make sure PxTFD.STS.BSY and PxTFD.STS.DRQ are 0 */
549 if (status & (ATA_BUSY | ATA_DRQ))
550 return 0;
551
552 /* Make sure PxSSTS.DET is 3h */
553 status = readl(port_mmio + PORT_SCR_STAT) & 0xf;
554 if (status != 3)
555 return 0;
556 return 1;
557}
558
559void ahci_start_engine(struct ata_port *ap) 544void ahci_start_engine(struct ata_port *ap)
560{ 545{
561 void __iomem *port_mmio = ahci_port_base(ap); 546 void __iomem *port_mmio = ahci_port_base(ap);
562 u32 tmp; 547 u32 tmp;
563 548
564 if (!ahci_is_device_present(port_mmio))
565 return;
566
567 /* start DMA */ 549 /* start DMA */
568 tmp = readl(port_mmio + PORT_CMD); 550 tmp = readl(port_mmio + PORT_CMD);
569 tmp |= PORT_CMD_START; 551 tmp |= PORT_CMD_START;
@@ -1892,6 +1874,9 @@ static void ahci_error_handler(struct ata_port *ap)
1892 } 1874 }
1893 1875
1894 sata_pmp_error_handler(ap); 1876 sata_pmp_error_handler(ap);
1877
1878 if (!ata_dev_enabled(ap->link.device))
1879 ahci_stop_engine(ap);
1895} 1880}
1896 1881
1897static void ahci_post_internal_cmd(struct ata_queued_cmd *qc) 1882static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index c47373f01f89..ddf8e4862787 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -160,6 +160,10 @@ int libata_allow_tpm = 0;
160module_param_named(allow_tpm, libata_allow_tpm, int, 0444); 160module_param_named(allow_tpm, libata_allow_tpm, int, 0444);
161MODULE_PARM_DESC(allow_tpm, "Permit the use of TPM commands (0=off [default], 1=on)"); 161MODULE_PARM_DESC(allow_tpm, "Permit the use of TPM commands (0=off [default], 1=on)");
162 162
163static int atapi_an;
164module_param(atapi_an, int, 0444);
165MODULE_PARM_DESC(atapi_an, "Enable ATAPI AN media presence notification (0=0ff [default], 1=on)");
166
163MODULE_AUTHOR("Jeff Garzik"); 167MODULE_AUTHOR("Jeff Garzik");
164MODULE_DESCRIPTION("Library module for ATA devices"); 168MODULE_DESCRIPTION("Library module for ATA devices");
165MODULE_LICENSE("GPL"); 169MODULE_LICENSE("GPL");
@@ -2122,6 +2126,14 @@ retry:
2122 goto err_out; 2126 goto err_out;
2123 } 2127 }
2124 2128
2129 if (dev->horkage & ATA_HORKAGE_DUMP_ID) {
2130 ata_dev_printk(dev, KERN_DEBUG, "dumping IDENTIFY data, "
2131 "class=%d may_fallback=%d tried_spinup=%d\n",
2132 class, may_fallback, tried_spinup);
2133 print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET,
2134 16, 2, id, ATA_ID_WORDS * sizeof(*id), true);
2135 }
2136
2125 /* Falling back doesn't make sense if ID data was read 2137 /* Falling back doesn't make sense if ID data was read
2126 * successfully at least once. 2138 * successfully at least once.
2127 */ 2139 */
@@ -2510,7 +2522,8 @@ int ata_dev_configure(struct ata_device *dev)
2510 * to enable ATAPI AN to discern between PHY status 2522 * to enable ATAPI AN to discern between PHY status
2511 * changed notifications and ATAPI ANs. 2523 * changed notifications and ATAPI ANs.
2512 */ 2524 */
2513 if ((ap->flags & ATA_FLAG_AN) && ata_id_has_atapi_AN(id) && 2525 if (atapi_an &&
2526 (ap->flags & ATA_FLAG_AN) && ata_id_has_atapi_AN(id) &&
2514 (!sata_pmp_attached(ap) || 2527 (!sata_pmp_attached(ap) ||
2515 sata_scr_read(&ap->link, SCR_NOTIFICATION, &sntf) == 0)) { 2528 sata_scr_read(&ap->link, SCR_NOTIFICATION, &sntf) == 0)) {
2516 unsigned int err_mask; 2529 unsigned int err_mask;
@@ -4106,9 +4119,8 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
4106 dev->n_sectors > n_sectors && dev->n_sectors == n_native_sectors) { 4119 dev->n_sectors > n_sectors && dev->n_sectors == n_native_sectors) {
4107 ata_dev_printk(dev, KERN_WARNING, 4120 ata_dev_printk(dev, KERN_WARNING,
4108 "new n_sectors matches native, probably " 4121 "new n_sectors matches native, probably "
4109 "late HPA unlock, continuing\n"); 4122 "late HPA unlock, n_sectors updated\n");
4110 /* keep using the old n_sectors */ 4123 /* use the larger n_sectors */
4111 dev->n_sectors = n_sectors;
4112 return 0; 4124 return 0;
4113 } 4125 }
4114 4126
@@ -6372,6 +6384,7 @@ static int __init ata_parse_force_one(char **cur,
6372 { "3.0Gbps", .spd_limit = 2 }, 6384 { "3.0Gbps", .spd_limit = 2 },
6373 { "noncq", .horkage_on = ATA_HORKAGE_NONCQ }, 6385 { "noncq", .horkage_on = ATA_HORKAGE_NONCQ },
6374 { "ncq", .horkage_off = ATA_HORKAGE_NONCQ }, 6386 { "ncq", .horkage_off = ATA_HORKAGE_NONCQ },
6387 { "dump_id", .horkage_on = ATA_HORKAGE_DUMP_ID },
6375 { "pio0", .xfer_mask = 1 << (ATA_SHIFT_PIO + 0) }, 6388 { "pio0", .xfer_mask = 1 << (ATA_SHIFT_PIO + 0) },
6376 { "pio1", .xfer_mask = 1 << (ATA_SHIFT_PIO + 1) }, 6389 { "pio1", .xfer_mask = 1 << (ATA_SHIFT_PIO + 1) },
6377 { "pio2", .xfer_mask = 1 << (ATA_SHIFT_PIO + 2) }, 6390 { "pio2", .xfer_mask = 1 << (ATA_SHIFT_PIO + 2) },
@@ -6655,6 +6668,7 @@ EXPORT_SYMBOL_GPL(ata_dummy_port_info);
6655EXPORT_SYMBOL_GPL(ata_link_next); 6668EXPORT_SYMBOL_GPL(ata_link_next);
6656EXPORT_SYMBOL_GPL(ata_dev_next); 6669EXPORT_SYMBOL_GPL(ata_dev_next);
6657EXPORT_SYMBOL_GPL(ata_std_bios_param); 6670EXPORT_SYMBOL_GPL(ata_std_bios_param);
6671EXPORT_SYMBOL_GPL(ata_scsi_unlock_native_capacity);
6658EXPORT_SYMBOL_GPL(ata_host_init); 6672EXPORT_SYMBOL_GPL(ata_host_init);
6659EXPORT_SYMBOL_GPL(ata_host_alloc); 6673EXPORT_SYMBOL_GPL(ata_host_alloc);
6660EXPORT_SYMBOL_GPL(ata_host_alloc_pinfo); 6674EXPORT_SYMBOL_GPL(ata_host_alloc_pinfo);
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index cfa9dd3d7253..a54273d2c3c6 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -415,6 +415,35 @@ int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev,
415} 415}
416 416
417/** 417/**
418 * ata_scsi_unlock_native_capacity - unlock native capacity
419 * @sdev: SCSI device to adjust device capacity for
420 *
421 * This function is called if a partition on @sdev extends beyond
422 * the end of the device. It requests EH to unlock HPA.
423 *
424 * LOCKING:
425 * Defined by the SCSI layer. Might sleep.
426 */
427void ata_scsi_unlock_native_capacity(struct scsi_device *sdev)
428{
429 struct ata_port *ap = ata_shost_to_port(sdev->host);
430 struct ata_device *dev;
431 unsigned long flags;
432
433 spin_lock_irqsave(ap->lock, flags);
434
435 dev = ata_scsi_find_dev(ap, sdev);
436 if (dev && dev->n_sectors < dev->n_native_sectors) {
437 dev->flags |= ATA_DFLAG_UNLOCK_HPA;
438 dev->link->eh_info.action |= ATA_EH_RESET;
439 ata_port_schedule_eh(ap);
440 }
441
442 spin_unlock_irqrestore(ap->lock, flags);
443 ata_port_wait_eh(ap);
444}
445
446/**
418 * ata_get_identity - Handler for HDIO_GET_IDENTITY ioctl 447 * ata_get_identity - Handler for HDIO_GET_IDENTITY ioctl
419 * @ap: target port 448 * @ap: target port
420 * @sdev: SCSI device to get identify data for 449 * @sdev: SCSI device to get identify data for
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 19ddf924944f..efa4a18cfb9d 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -63,7 +63,6 @@ const struct ata_port_operations ata_sff_port_ops = {
63 .sff_tf_read = ata_sff_tf_read, 63 .sff_tf_read = ata_sff_tf_read,
64 .sff_exec_command = ata_sff_exec_command, 64 .sff_exec_command = ata_sff_exec_command,
65 .sff_data_xfer = ata_sff_data_xfer, 65 .sff_data_xfer = ata_sff_data_xfer,
66 .sff_irq_clear = ata_sff_irq_clear,
67 .sff_drain_fifo = ata_sff_drain_fifo, 66 .sff_drain_fifo = ata_sff_drain_fifo,
68 67
69 .lost_interrupt = ata_sff_lost_interrupt, 68 .lost_interrupt = ata_sff_lost_interrupt,
@@ -395,33 +394,12 @@ void ata_sff_irq_on(struct ata_port *ap)
395 ata_sff_set_devctl(ap, ap->ctl); 394 ata_sff_set_devctl(ap, ap->ctl);
396 ata_wait_idle(ap); 395 ata_wait_idle(ap);
397 396
398 ap->ops->sff_irq_clear(ap); 397 if (ap->ops->sff_irq_clear)
398 ap->ops->sff_irq_clear(ap);
399} 399}
400EXPORT_SYMBOL_GPL(ata_sff_irq_on); 400EXPORT_SYMBOL_GPL(ata_sff_irq_on);
401 401
402/** 402/**
403 * ata_sff_irq_clear - Clear PCI IDE BMDMA interrupt.
404 * @ap: Port associated with this ATA transaction.
405 *
406 * Clear interrupt and error flags in DMA status register.
407 *
408 * May be used as the irq_clear() entry in ata_port_operations.
409 *
410 * LOCKING:
411 * spin_lock_irqsave(host lock)
412 */
413void ata_sff_irq_clear(struct ata_port *ap)
414{
415 void __iomem *mmio = ap->ioaddr.bmdma_addr;
416
417 if (!mmio)
418 return;
419
420 iowrite8(ioread8(mmio + ATA_DMA_STATUS), mmio + ATA_DMA_STATUS);
421}
422EXPORT_SYMBOL_GPL(ata_sff_irq_clear);
423
424/**
425 * ata_sff_tf_load - send taskfile registers to host controller 403 * ata_sff_tf_load - send taskfile registers to host controller
426 * @ap: Port to which output is sent 404 * @ap: Port to which output is sent
427 * @tf: ATA taskfile register set 405 * @tf: ATA taskfile register set
@@ -820,11 +798,15 @@ static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc)
820 case ATAPI_PROT_NODATA: 798 case ATAPI_PROT_NODATA:
821 ap->hsm_task_state = HSM_ST_LAST; 799 ap->hsm_task_state = HSM_ST_LAST;
822 break; 800 break;
801#ifdef CONFIG_ATA_BMDMA
823 case ATAPI_PROT_DMA: 802 case ATAPI_PROT_DMA:
824 ap->hsm_task_state = HSM_ST_LAST; 803 ap->hsm_task_state = HSM_ST_LAST;
825 /* initiate bmdma */ 804 /* initiate bmdma */
826 ap->ops->bmdma_start(qc); 805 ap->ops->bmdma_start(qc);
827 break; 806 break;
807#endif /* CONFIG_ATA_BMDMA */
808 default:
809 BUG();
828 } 810 }
829} 811}
830 812
@@ -1491,27 +1473,27 @@ bool ata_sff_qc_fill_rtf(struct ata_queued_cmd *qc)
1491} 1473}
1492EXPORT_SYMBOL_GPL(ata_sff_qc_fill_rtf); 1474EXPORT_SYMBOL_GPL(ata_sff_qc_fill_rtf);
1493 1475
1494/** 1476static unsigned int ata_sff_idle_irq(struct ata_port *ap)
1495 * ata_sff_host_intr - Handle host interrupt for given (port, task)
1496 * @ap: Port on which interrupt arrived (possibly...)
1497 * @qc: Taskfile currently active in engine
1498 *
1499 * Handle host interrupt for given queued command. Currently,
1500 * only DMA interrupts are handled. All other commands are
1501 * handled via polling with interrupts disabled (nIEN bit).
1502 *
1503 * LOCKING:
1504 * spin_lock_irqsave(host lock)
1505 *
1506 * RETURNS:
1507 * One if interrupt was handled, zero if not (shared irq).
1508 */
1509unsigned int ata_sff_host_intr(struct ata_port *ap,
1510 struct ata_queued_cmd *qc)
1511{ 1477{
1512 struct ata_eh_info *ehi = &ap->link.eh_info; 1478 ap->stats.idle_irq++;
1513 u8 status, host_stat = 0; 1479
1514 bool bmdma_stopped = false; 1480#ifdef ATA_IRQ_TRAP
1481 if ((ap->stats.idle_irq % 1000) == 0) {
1482 ap->ops->sff_check_status(ap);
1483 if (ap->ops->sff_irq_clear)
1484 ap->ops->sff_irq_clear(ap);
1485 ata_port_printk(ap, KERN_WARNING, "irq trap\n");
1486 return 1;
1487 }
1488#endif
1489 return 0; /* irq not handled */
1490}
1491
1492static unsigned int __ata_sff_port_intr(struct ata_port *ap,
1493 struct ata_queued_cmd *qc,
1494 bool hsmv_on_idle)
1495{
1496 u8 status;
1515 1497
1516 VPRINTK("ata%u: protocol %d task_state %d\n", 1498 VPRINTK("ata%u: protocol %d task_state %d\n",
1517 ap->print_id, qc->tf.protocol, ap->hsm_task_state); 1499 ap->print_id, qc->tf.protocol, ap->hsm_task_state);
@@ -1528,90 +1510,56 @@ unsigned int ata_sff_host_intr(struct ata_port *ap,
1528 * need to check ata_is_atapi(qc->tf.protocol) again. 1510 * need to check ata_is_atapi(qc->tf.protocol) again.
1529 */ 1511 */
1530 if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) 1512 if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
1531 goto idle_irq; 1513 return ata_sff_idle_irq(ap);
1532 break;
1533 case HSM_ST_LAST:
1534 if (qc->tf.protocol == ATA_PROT_DMA ||
1535 qc->tf.protocol == ATAPI_PROT_DMA) {
1536 /* check status of DMA engine */
1537 host_stat = ap->ops->bmdma_status(ap);
1538 VPRINTK("ata%u: host_stat 0x%X\n",
1539 ap->print_id, host_stat);
1540
1541 /* if it's not our irq... */
1542 if (!(host_stat & ATA_DMA_INTR))
1543 goto idle_irq;
1544
1545 /* before we do anything else, clear DMA-Start bit */
1546 ap->ops->bmdma_stop(qc);
1547 bmdma_stopped = true;
1548
1549 if (unlikely(host_stat & ATA_DMA_ERR)) {
1550 /* error when transfering data to/from memory */
1551 qc->err_mask |= AC_ERR_HOST_BUS;
1552 ap->hsm_task_state = HSM_ST_ERR;
1553 }
1554 }
1555 break; 1514 break;
1556 case HSM_ST: 1515 case HSM_ST:
1516 case HSM_ST_LAST:
1557 break; 1517 break;
1558 default: 1518 default:
1559 goto idle_irq; 1519 return ata_sff_idle_irq(ap);
1560 } 1520 }
1561 1521
1562
1563 /* check main status, clearing INTRQ if needed */ 1522 /* check main status, clearing INTRQ if needed */
1564 status = ata_sff_irq_status(ap); 1523 status = ata_sff_irq_status(ap);
1565 if (status & ATA_BUSY) { 1524 if (status & ATA_BUSY) {
1566 if (bmdma_stopped) { 1525 if (hsmv_on_idle) {
1567 /* BMDMA engine is already stopped, we're screwed */ 1526 /* BMDMA engine is already stopped, we're screwed */
1568 qc->err_mask |= AC_ERR_HSM; 1527 qc->err_mask |= AC_ERR_HSM;
1569 ap->hsm_task_state = HSM_ST_ERR; 1528 ap->hsm_task_state = HSM_ST_ERR;
1570 } else 1529 } else
1571 goto idle_irq; 1530 return ata_sff_idle_irq(ap);
1572 } 1531 }
1573 1532
1574 /* clear irq events */ 1533 /* clear irq events */
1575 ap->ops->sff_irq_clear(ap); 1534 if (ap->ops->sff_irq_clear)
1535 ap->ops->sff_irq_clear(ap);
1576 1536
1577 ata_sff_hsm_move(ap, qc, status, 0); 1537 ata_sff_hsm_move(ap, qc, status, 0);
1578 1538
1579 if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA ||
1580 qc->tf.protocol == ATAPI_PROT_DMA))
1581 ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat);
1582
1583 return 1; /* irq handled */ 1539 return 1; /* irq handled */
1584
1585idle_irq:
1586 ap->stats.idle_irq++;
1587
1588#ifdef ATA_IRQ_TRAP
1589 if ((ap->stats.idle_irq % 1000) == 0) {
1590 ap->ops->sff_check_status(ap);
1591 ap->ops->sff_irq_clear(ap);
1592 ata_port_printk(ap, KERN_WARNING, "irq trap\n");
1593 return 1;
1594 }
1595#endif
1596 return 0; /* irq not handled */
1597} 1540}
1598EXPORT_SYMBOL_GPL(ata_sff_host_intr);
1599 1541
1600/** 1542/**
1601 * ata_sff_interrupt - Default ATA host interrupt handler 1543 * ata_sff_port_intr - Handle SFF port interrupt
1602 * @irq: irq line (unused) 1544 * @ap: Port on which interrupt arrived (possibly...)
1603 * @dev_instance: pointer to our ata_host information structure 1545 * @qc: Taskfile currently active in engine
1604 * 1546 *
1605 * Default interrupt handler for PCI IDE devices. Calls 1547 * Handle port interrupt for given queued command.
1606 * ata_sff_host_intr() for each port that is not disabled.
1607 * 1548 *
1608 * LOCKING: 1549 * LOCKING:
1609 * Obtains host lock during operation. 1550 * spin_lock_irqsave(host lock)
1610 * 1551 *
1611 * RETURNS: 1552 * RETURNS:
1612 * IRQ_NONE or IRQ_HANDLED. 1553 * One if interrupt was handled, zero if not (shared irq).
1613 */ 1554 */
1614irqreturn_t ata_sff_interrupt(int irq, void *dev_instance) 1555unsigned int ata_sff_port_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
1556{
1557 return __ata_sff_port_intr(ap, qc, false);
1558}
1559EXPORT_SYMBOL_GPL(ata_sff_port_intr);
1560
1561static inline irqreturn_t __ata_sff_interrupt(int irq, void *dev_instance,
1562 unsigned int (*port_intr)(struct ata_port *, struct ata_queued_cmd *))
1615{ 1563{
1616 struct ata_host *host = dev_instance; 1564 struct ata_host *host = dev_instance;
1617 bool retried = false; 1565 bool retried = false;
@@ -1631,7 +1579,7 @@ retry:
1631 qc = ata_qc_from_tag(ap, ap->link.active_tag); 1579 qc = ata_qc_from_tag(ap, ap->link.active_tag);
1632 if (qc) { 1580 if (qc) {
1633 if (!(qc->tf.flags & ATA_TFLAG_POLLING)) 1581 if (!(qc->tf.flags & ATA_TFLAG_POLLING))
1634 handled |= ata_sff_host_intr(ap, qc); 1582 handled |= port_intr(ap, qc);
1635 else 1583 else
1636 polling |= 1 << i; 1584 polling |= 1 << i;
1637 } else 1585 } else
@@ -1658,7 +1606,8 @@ retry:
1658 1606
1659 if (idle & (1 << i)) { 1607 if (idle & (1 << i)) {
1660 ap->ops->sff_check_status(ap); 1608 ap->ops->sff_check_status(ap);
1661 ap->ops->sff_irq_clear(ap); 1609 if (ap->ops->sff_irq_clear)
1610 ap->ops->sff_irq_clear(ap);
1662 } else { 1611 } else {
1663 /* clear INTRQ and check if BUSY cleared */ 1612 /* clear INTRQ and check if BUSY cleared */
1664 if (!(ap->ops->sff_check_status(ap) & ATA_BUSY)) 1613 if (!(ap->ops->sff_check_status(ap) & ATA_BUSY))
@@ -1680,6 +1629,25 @@ retry:
1680 1629
1681 return IRQ_RETVAL(handled); 1630 return IRQ_RETVAL(handled);
1682} 1631}
1632
1633/**
1634 * ata_sff_interrupt - Default SFF ATA host interrupt handler
1635 * @irq: irq line (unused)
1636 * @dev_instance: pointer to our ata_host information structure
1637 *
1638 * Default interrupt handler for PCI IDE devices. Calls
1639 * ata_sff_port_intr() for each port that is not disabled.
1640 *
1641 * LOCKING:
1642 * Obtains host lock during operation.
1643 *
1644 * RETURNS:
1645 * IRQ_NONE or IRQ_HANDLED.
1646 */
1647irqreturn_t ata_sff_interrupt(int irq, void *dev_instance)
1648{
1649 return __ata_sff_interrupt(irq, dev_instance, ata_sff_port_intr);
1650}
1683EXPORT_SYMBOL_GPL(ata_sff_interrupt); 1651EXPORT_SYMBOL_GPL(ata_sff_interrupt);
1684 1652
1685/** 1653/**
@@ -1717,7 +1685,7 @@ void ata_sff_lost_interrupt(struct ata_port *ap)
1717 status); 1685 status);
1718 /* Run the host interrupt logic as if the interrupt had not been 1686 /* Run the host interrupt logic as if the interrupt had not been
1719 lost */ 1687 lost */
1720 ata_sff_host_intr(ap, qc); 1688 ata_sff_port_intr(ap, qc);
1721} 1689}
1722EXPORT_SYMBOL_GPL(ata_sff_lost_interrupt); 1690EXPORT_SYMBOL_GPL(ata_sff_lost_interrupt);
1723 1691
@@ -1744,7 +1712,8 @@ void ata_sff_freeze(struct ata_port *ap)
1744 */ 1712 */
1745 ap->ops->sff_check_status(ap); 1713 ap->ops->sff_check_status(ap);
1746 1714
1747 ap->ops->sff_irq_clear(ap); 1715 if (ap->ops->sff_irq_clear)
1716 ap->ops->sff_irq_clear(ap);
1748} 1717}
1749EXPORT_SYMBOL_GPL(ata_sff_freeze); 1718EXPORT_SYMBOL_GPL(ata_sff_freeze);
1750 1719
@@ -1761,7 +1730,8 @@ void ata_sff_thaw(struct ata_port *ap)
1761{ 1730{
1762 /* clear & re-enable interrupts */ 1731 /* clear & re-enable interrupts */
1763 ap->ops->sff_check_status(ap); 1732 ap->ops->sff_check_status(ap);
1764 ap->ops->sff_irq_clear(ap); 1733 if (ap->ops->sff_irq_clear)
1734 ap->ops->sff_irq_clear(ap);
1765 ata_sff_irq_on(ap); 1735 ata_sff_irq_on(ap);
1766} 1736}
1767EXPORT_SYMBOL_GPL(ata_sff_thaw); 1737EXPORT_SYMBOL_GPL(ata_sff_thaw);
@@ -2349,13 +2319,13 @@ int ata_pci_sff_init_host(struct ata_host *host)
2349EXPORT_SYMBOL_GPL(ata_pci_sff_init_host); 2319EXPORT_SYMBOL_GPL(ata_pci_sff_init_host);
2350 2320
2351/** 2321/**
2352 * ata_pci_sff_prepare_host - helper to prepare native PCI ATA host 2322 * ata_pci_sff_prepare_host - helper to prepare PCI PIO-only SFF ATA host
2353 * @pdev: target PCI device 2323 * @pdev: target PCI device
2354 * @ppi: array of port_info, must be enough for two ports 2324 * @ppi: array of port_info, must be enough for two ports
2355 * @r_host: out argument for the initialized ATA host 2325 * @r_host: out argument for the initialized ATA host
2356 * 2326 *
2357 * Helper to allocate ATA host for @pdev, acquire all native PCI 2327 * Helper to allocate PIO-only SFF ATA host for @pdev, acquire
2358 * resources and initialize it accordingly in one go. 2328 * all PCI resources and initialize it accordingly in one go.
2359 * 2329 *
2360 * LOCKING: 2330 * LOCKING:
2361 * Inherited from calling layer (may sleep). 2331 * Inherited from calling layer (may sleep).
@@ -2385,9 +2355,6 @@ int ata_pci_sff_prepare_host(struct pci_dev *pdev,
2385 if (rc) 2355 if (rc)
2386 goto err_out; 2356 goto err_out;
2387 2357
2388 /* init DMA related stuff */
2389 ata_pci_bmdma_init(host);
2390
2391 devres_remove_group(&pdev->dev, NULL); 2358 devres_remove_group(&pdev->dev, NULL);
2392 *r_host = host; 2359 *r_host = host;
2393 return 0; 2360 return 0;
@@ -2492,8 +2459,21 @@ out:
2492} 2459}
2493EXPORT_SYMBOL_GPL(ata_pci_sff_activate_host); 2460EXPORT_SYMBOL_GPL(ata_pci_sff_activate_host);
2494 2461
2462static const struct ata_port_info *ata_sff_find_valid_pi(
2463 const struct ata_port_info * const *ppi)
2464{
2465 int i;
2466
2467 /* look up the first valid port_info */
2468 for (i = 0; i < 2 && ppi[i]; i++)
2469 if (ppi[i]->port_ops != &ata_dummy_port_ops)
2470 return ppi[i];
2471
2472 return NULL;
2473}
2474
2495/** 2475/**
2496 * ata_pci_sff_init_one - Initialize/register PCI IDE host controller 2476 * ata_pci_sff_init_one - Initialize/register PIO-only PCI IDE controller
2497 * @pdev: Controller to be initialized 2477 * @pdev: Controller to be initialized
2498 * @ppi: array of port_info, must be enough for two ports 2478 * @ppi: array of port_info, must be enough for two ports
2499 * @sht: scsi_host_template to use when registering the host 2479 * @sht: scsi_host_template to use when registering the host
@@ -2502,11 +2482,7 @@ EXPORT_SYMBOL_GPL(ata_pci_sff_activate_host);
2502 * 2482 *
2503 * This is a helper function which can be called from a driver's 2483 * This is a helper function which can be called from a driver's
2504 * xxx_init_one() probe function if the hardware uses traditional 2484 * xxx_init_one() probe function if the hardware uses traditional
2505 * IDE taskfile registers. 2485 * IDE taskfile registers and is PIO only.
2506 *
2507 * This function calls pci_enable_device(), reserves its register
2508 * regions, sets the dma mask, enables bus master mode, and calls
2509 * ata_device_add()
2510 * 2486 *
2511 * ASSUMPTION: 2487 * ASSUMPTION:
2512 * Nobody makes a single channel controller that appears solely as 2488 * Nobody makes a single channel controller that appears solely as
@@ -2523,20 +2499,13 @@ int ata_pci_sff_init_one(struct pci_dev *pdev,
2523 struct scsi_host_template *sht, void *host_priv, int hflag) 2499 struct scsi_host_template *sht, void *host_priv, int hflag)
2524{ 2500{
2525 struct device *dev = &pdev->dev; 2501 struct device *dev = &pdev->dev;
2526 const struct ata_port_info *pi = NULL; 2502 const struct ata_port_info *pi;
2527 struct ata_host *host = NULL; 2503 struct ata_host *host = NULL;
2528 int i, rc; 2504 int rc;
2529 2505
2530 DPRINTK("ENTER\n"); 2506 DPRINTK("ENTER\n");
2531 2507
2532 /* look up the first valid port_info */ 2508 pi = ata_sff_find_valid_pi(ppi);
2533 for (i = 0; i < 2 && ppi[i]; i++) {
2534 if (ppi[i]->port_ops != &ata_dummy_port_ops) {
2535 pi = ppi[i];
2536 break;
2537 }
2538 }
2539
2540 if (!pi) { 2509 if (!pi) {
2541 dev_printk(KERN_ERR, &pdev->dev, 2510 dev_printk(KERN_ERR, &pdev->dev,
2542 "no valid port_info specified\n"); 2511 "no valid port_info specified\n");
@@ -2557,7 +2526,6 @@ int ata_pci_sff_init_one(struct pci_dev *pdev,
2557 host->private_data = host_priv; 2526 host->private_data = host_priv;
2558 host->flags |= hflag; 2527 host->flags |= hflag;
2559 2528
2560 pci_set_master(pdev);
2561 rc = ata_pci_sff_activate_host(host, ata_sff_interrupt, sht); 2529 rc = ata_pci_sff_activate_host(host, ata_sff_interrupt, sht);
2562out: 2530out:
2563 if (rc == 0) 2531 if (rc == 0)
@@ -2571,6 +2539,12 @@ EXPORT_SYMBOL_GPL(ata_pci_sff_init_one);
2571 2539
2572#endif /* CONFIG_PCI */ 2540#endif /* CONFIG_PCI */
2573 2541
2542/*
2543 * BMDMA support
2544 */
2545
2546#ifdef CONFIG_ATA_BMDMA
2547
2574const struct ata_port_operations ata_bmdma_port_ops = { 2548const struct ata_port_operations ata_bmdma_port_ops = {
2575 .inherits = &ata_sff_port_ops, 2549 .inherits = &ata_sff_port_ops,
2576 2550
@@ -2580,6 +2554,7 @@ const struct ata_port_operations ata_bmdma_port_ops = {
2580 .qc_prep = ata_bmdma_qc_prep, 2554 .qc_prep = ata_bmdma_qc_prep,
2581 .qc_issue = ata_bmdma_qc_issue, 2555 .qc_issue = ata_bmdma_qc_issue,
2582 2556
2557 .sff_irq_clear = ata_bmdma_irq_clear,
2583 .bmdma_setup = ata_bmdma_setup, 2558 .bmdma_setup = ata_bmdma_setup,
2584 .bmdma_start = ata_bmdma_start, 2559 .bmdma_start = ata_bmdma_start,
2585 .bmdma_stop = ata_bmdma_stop, 2560 .bmdma_stop = ata_bmdma_stop,
@@ -2804,6 +2779,75 @@ unsigned int ata_bmdma_qc_issue(struct ata_queued_cmd *qc)
2804EXPORT_SYMBOL_GPL(ata_bmdma_qc_issue); 2779EXPORT_SYMBOL_GPL(ata_bmdma_qc_issue);
2805 2780
2806/** 2781/**
2782 * ata_bmdma_port_intr - Handle BMDMA port interrupt
2783 * @ap: Port on which interrupt arrived (possibly...)
2784 * @qc: Taskfile currently active in engine
2785 *
2786 * Handle port interrupt for given queued command.
2787 *
2788 * LOCKING:
2789 * spin_lock_irqsave(host lock)
2790 *
2791 * RETURNS:
2792 * One if interrupt was handled, zero if not (shared irq).
2793 */
2794unsigned int ata_bmdma_port_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
2795{
2796 struct ata_eh_info *ehi = &ap->link.eh_info;
2797 u8 host_stat = 0;
2798 bool bmdma_stopped = false;
2799 unsigned int handled;
2800
2801 if (ap->hsm_task_state == HSM_ST_LAST && ata_is_dma(qc->tf.protocol)) {
2802 /* check status of DMA engine */
2803 host_stat = ap->ops->bmdma_status(ap);
2804 VPRINTK("ata%u: host_stat 0x%X\n", ap->print_id, host_stat);
2805
2806 /* if it's not our irq... */
2807 if (!(host_stat & ATA_DMA_INTR))
2808 return ata_sff_idle_irq(ap);
2809
2810 /* before we do anything else, clear DMA-Start bit */
2811 ap->ops->bmdma_stop(qc);
2812 bmdma_stopped = true;
2813
2814 if (unlikely(host_stat & ATA_DMA_ERR)) {
2815 /* error when transfering data to/from memory */
2816 qc->err_mask |= AC_ERR_HOST_BUS;
2817 ap->hsm_task_state = HSM_ST_ERR;
2818 }
2819 }
2820
2821 handled = __ata_sff_port_intr(ap, qc, bmdma_stopped);
2822
2823 if (unlikely(qc->err_mask) && ata_is_dma(qc->tf.protocol))
2824 ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat);
2825
2826 return handled;
2827}
2828EXPORT_SYMBOL_GPL(ata_bmdma_port_intr);
2829
2830/**
2831 * ata_bmdma_interrupt - Default BMDMA ATA host interrupt handler
2832 * @irq: irq line (unused)
2833 * @dev_instance: pointer to our ata_host information structure
2834 *
2835 * Default interrupt handler for PCI IDE devices. Calls
2836 * ata_bmdma_port_intr() for each port that is not disabled.
2837 *
2838 * LOCKING:
2839 * Obtains host lock during operation.
2840 *
2841 * RETURNS:
2842 * IRQ_NONE or IRQ_HANDLED.
2843 */
2844irqreturn_t ata_bmdma_interrupt(int irq, void *dev_instance)
2845{
2846 return __ata_sff_interrupt(irq, dev_instance, ata_bmdma_port_intr);
2847}
2848EXPORT_SYMBOL_GPL(ata_bmdma_interrupt);
2849
2850/**
2807 * ata_bmdma_error_handler - Stock error handler for BMDMA controller 2851 * ata_bmdma_error_handler - Stock error handler for BMDMA controller
2808 * @ap: port to handle error for 2852 * @ap: port to handle error for
2809 * 2853 *
@@ -2848,7 +2892,8 @@ void ata_bmdma_error_handler(struct ata_port *ap)
2848 /* if we're gonna thaw, make sure IRQ is clear */ 2892 /* if we're gonna thaw, make sure IRQ is clear */
2849 if (thaw) { 2893 if (thaw) {
2850 ap->ops->sff_check_status(ap); 2894 ap->ops->sff_check_status(ap);
2851 ap->ops->sff_irq_clear(ap); 2895 if (ap->ops->sff_irq_clear)
2896 ap->ops->sff_irq_clear(ap);
2852 } 2897 }
2853 } 2898 }
2854 2899
@@ -2882,6 +2927,28 @@ void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc)
2882EXPORT_SYMBOL_GPL(ata_bmdma_post_internal_cmd); 2927EXPORT_SYMBOL_GPL(ata_bmdma_post_internal_cmd);
2883 2928
2884/** 2929/**
2930 * ata_bmdma_irq_clear - Clear PCI IDE BMDMA interrupt.
2931 * @ap: Port associated with this ATA transaction.
2932 *
2933 * Clear interrupt and error flags in DMA status register.
2934 *
2935 * May be used as the irq_clear() entry in ata_port_operations.
2936 *
2937 * LOCKING:
2938 * spin_lock_irqsave(host lock)
2939 */
2940void ata_bmdma_irq_clear(struct ata_port *ap)
2941{
2942 void __iomem *mmio = ap->ioaddr.bmdma_addr;
2943
2944 if (!mmio)
2945 return;
2946
2947 iowrite8(ioread8(mmio + ATA_DMA_STATUS), mmio + ATA_DMA_STATUS);
2948}
2949EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear);
2950
2951/**
2885 * ata_bmdma_setup - Set up PCI IDE BMDMA transaction 2952 * ata_bmdma_setup - Set up PCI IDE BMDMA transaction
2886 * @qc: Info associated with this ATA transaction. 2953 * @qc: Info associated with this ATA transaction.
2887 * 2954 *
@@ -3137,7 +3204,100 @@ void ata_pci_bmdma_init(struct ata_host *host)
3137} 3204}
3138EXPORT_SYMBOL_GPL(ata_pci_bmdma_init); 3205EXPORT_SYMBOL_GPL(ata_pci_bmdma_init);
3139 3206
3207/**
3208 * ata_pci_bmdma_prepare_host - helper to prepare PCI BMDMA ATA host
3209 * @pdev: target PCI device
3210 * @ppi: array of port_info, must be enough for two ports
3211 * @r_host: out argument for the initialized ATA host
3212 *
3213 * Helper to allocate BMDMA ATA host for @pdev, acquire all PCI
3214 * resources and initialize it accordingly in one go.
3215 *
3216 * LOCKING:
3217 * Inherited from calling layer (may sleep).
3218 *
3219 * RETURNS:
3220 * 0 on success, -errno otherwise.
3221 */
3222int ata_pci_bmdma_prepare_host(struct pci_dev *pdev,
3223 const struct ata_port_info * const * ppi,
3224 struct ata_host **r_host)
3225{
3226 int rc;
3227
3228 rc = ata_pci_sff_prepare_host(pdev, ppi, r_host);
3229 if (rc)
3230 return rc;
3231
3232 ata_pci_bmdma_init(*r_host);
3233 return 0;
3234}
3235EXPORT_SYMBOL_GPL(ata_pci_bmdma_prepare_host);
3236
3237/**
3238 * ata_pci_bmdma_init_one - Initialize/register BMDMA PCI IDE controller
3239 * @pdev: Controller to be initialized
3240 * @ppi: array of port_info, must be enough for two ports
3241 * @sht: scsi_host_template to use when registering the host
3242 * @host_priv: host private_data
3243 * @hflags: host flags
3244 *
3245 * This function is similar to ata_pci_sff_init_one() but also
3246 * takes care of BMDMA initialization.
3247 *
3248 * LOCKING:
3249 * Inherited from PCI layer (may sleep).
3250 *
3251 * RETURNS:
3252 * Zero on success, negative on errno-based value on error.
3253 */
3254int ata_pci_bmdma_init_one(struct pci_dev *pdev,
3255 const struct ata_port_info * const * ppi,
3256 struct scsi_host_template *sht, void *host_priv,
3257 int hflags)
3258{
3259 struct device *dev = &pdev->dev;
3260 const struct ata_port_info *pi;
3261 struct ata_host *host = NULL;
3262 int rc;
3263
3264 DPRINTK("ENTER\n");
3265
3266 pi = ata_sff_find_valid_pi(ppi);
3267 if (!pi) {
3268 dev_printk(KERN_ERR, &pdev->dev,
3269 "no valid port_info specified\n");
3270 return -EINVAL;
3271 }
3272
3273 if (!devres_open_group(dev, NULL, GFP_KERNEL))
3274 return -ENOMEM;
3275
3276 rc = pcim_enable_device(pdev);
3277 if (rc)
3278 goto out;
3279
3280 /* prepare and activate BMDMA host */
3281 rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host);
3282 if (rc)
3283 goto out;
3284 host->private_data = host_priv;
3285 host->flags |= hflags;
3286
3287 pci_set_master(pdev);
3288 rc = ata_pci_sff_activate_host(host, ata_bmdma_interrupt, sht);
3289 out:
3290 if (rc == 0)
3291 devres_remove_group(&pdev->dev, NULL);
3292 else
3293 devres_release_group(&pdev->dev, NULL);
3294
3295 return rc;
3296}
3297EXPORT_SYMBOL_GPL(ata_pci_bmdma_init_one);
3298
3140#endif /* CONFIG_PCI */ 3299#endif /* CONFIG_PCI */
3300#endif /* CONFIG_ATA_BMDMA */
3141 3301
3142/** 3302/**
3143 * ata_sff_port_init - Initialize SFF/BMDMA ATA port 3303 * ata_sff_port_init - Initialize SFF/BMDMA ATA port
diff --git a/drivers/ata/pata_acpi.c b/drivers/ata/pata_acpi.c
index 066b9f301ed5..c8d47034d5e9 100644
--- a/drivers/ata/pata_acpi.c
+++ b/drivers/ata/pata_acpi.c
@@ -260,7 +260,7 @@ static int pacpi_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
260 return rc; 260 return rc;
261 pcim_pin_device(pdev); 261 pcim_pin_device(pdev);
262 } 262 }
263 return ata_pci_sff_init_one(pdev, ppi, &pacpi_sht, NULL, 0); 263 return ata_pci_bmdma_init_one(pdev, ppi, &pacpi_sht, NULL, 0);
264} 264}
265 265
266static const struct pci_device_id pacpi_pci_tbl[] = { 266static const struct pci_device_id pacpi_pci_tbl[] = {
diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c
index f306e10c748d..794ec6e3275d 100644
--- a/drivers/ata/pata_ali.c
+++ b/drivers/ata/pata_ali.c
@@ -583,7 +583,10 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
583 ppi[0] = &info_20_udma; 583 ppi[0] = &info_20_udma;
584 } 584 }
585 585
586 return ata_pci_sff_init_one(pdev, ppi, &ali_sht, NULL, 0); 586 if (!ppi[0]->mwdma_mask && !ppi[0]->udma_mask)
587 return ata_pci_sff_init_one(pdev, ppi, &ali_sht, NULL, 0);
588 else
589 return ata_pci_bmdma_init_one(pdev, ppi, &ali_sht, NULL, 0);
587} 590}
588 591
589#ifdef CONFIG_PM 592#ifdef CONFIG_PM
diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c
index d95eca9c547e..620a07cabe31 100644
--- a/drivers/ata/pata_amd.c
+++ b/drivers/ata/pata_amd.c
@@ -574,7 +574,7 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
574 } 574 }
575 575
576 /* And fire it up */ 576 /* And fire it up */
577 return ata_pci_sff_init_one(pdev, ppi, &amd_sht, hpriv, 0); 577 return ata_pci_bmdma_init_one(pdev, ppi, &amd_sht, hpriv, 0);
578} 578}
579 579
580#ifdef CONFIG_PM 580#ifdef CONFIG_PM
diff --git a/drivers/ata/pata_artop.c b/drivers/ata/pata_artop.c
index 4d066d6c30fa..ba43f0f8c880 100644
--- a/drivers/ata/pata_artop.c
+++ b/drivers/ata/pata_artop.c
@@ -421,7 +421,7 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
421 421
422 BUG_ON(ppi[0] == NULL); 422 BUG_ON(ppi[0] == NULL);
423 423
424 return ata_pci_sff_init_one(pdev, ppi, &artop_sht, NULL, 0); 424 return ata_pci_bmdma_init_one(pdev, ppi, &artop_sht, NULL, 0);
425} 425}
426 426
427static const struct pci_device_id artop_pci_tbl[] = { 427static const struct pci_device_id artop_pci_tbl[] = {
diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c
index 44d88b380ddd..43755616dc5a 100644
--- a/drivers/ata/pata_atiixp.c
+++ b/drivers/ata/pata_atiixp.c
@@ -246,8 +246,8 @@ static int atiixp_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
246 if (!pci_test_config_bits(pdev, &atiixp_enable_bits[i])) 246 if (!pci_test_config_bits(pdev, &atiixp_enable_bits[i]))
247 ppi[i] = &ata_dummy_port_info; 247 ppi[i] = &ata_dummy_port_info;
248 248
249 return ata_pci_sff_init_one(pdev, ppi, &atiixp_sht, NULL, 249 return ata_pci_bmdma_init_one(pdev, ppi, &atiixp_sht, NULL,
250 ATA_HOST_PARALLEL_SCAN); 250 ATA_HOST_PARALLEL_SCAN);
251} 251}
252 252
253static const struct pci_device_id atiixp[] = { 253static const struct pci_device_id atiixp[] = {
diff --git a/drivers/ata/pata_atp867x.c b/drivers/ata/pata_atp867x.c
index bb6e0746e07d..95295935dd95 100644
--- a/drivers/ata/pata_atp867x.c
+++ b/drivers/ata/pata_atp867x.c
@@ -525,7 +525,7 @@ static int atp867x_init_one(struct pci_dev *pdev,
525 525
526 pci_set_master(pdev); 526 pci_set_master(pdev);
527 527
528 rc = ata_host_activate(host, pdev->irq, ata_sff_interrupt, 528 rc = ata_host_activate(host, pdev->irq, ata_bmdma_interrupt,
529 IRQF_SHARED, &atp867x_sht); 529 IRQF_SHARED, &atp867x_sht);
530 if (rc) 530 if (rc)
531 dev_printk(KERN_ERR, &pdev->dev, "failed to activate host\n"); 531 dev_printk(KERN_ERR, &pdev->dev, "failed to activate host\n");
diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c
index 6422cfd13d0d..9cae65de750e 100644
--- a/drivers/ata/pata_bf54x.c
+++ b/drivers/ata/pata_bf54x.c
@@ -1214,7 +1214,7 @@ static unsigned int bfin_data_xfer(struct ata_device *dev, unsigned char *buf,
1214 * bfin_irq_clear - Clear ATAPI interrupt. 1214 * bfin_irq_clear - Clear ATAPI interrupt.
1215 * @ap: Port associated with this ATA transaction. 1215 * @ap: Port associated with this ATA transaction.
1216 * 1216 *
1217 * Note: Original code is ata_sff_irq_clear(). 1217 * Note: Original code is ata_bmdma_irq_clear().
1218 */ 1218 */
1219 1219
1220static void bfin_irq_clear(struct ata_port *ap) 1220static void bfin_irq_clear(struct ata_port *ap)
diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c
index 4c81a71b8877..9f5da1c7454b 100644
--- a/drivers/ata/pata_cmd64x.c
+++ b/drivers/ata/pata_cmd64x.c
@@ -367,7 +367,7 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
367 pci_write_config_byte(pdev, UDIDETCR0, 0xF0); 367 pci_write_config_byte(pdev, UDIDETCR0, 0xF0);
368#endif 368#endif
369 369
370 return ata_pci_sff_init_one(pdev, ppi, &cmd64x_sht, NULL, 0); 370 return ata_pci_bmdma_init_one(pdev, ppi, &cmd64x_sht, NULL, 0);
371} 371}
372 372
373#ifdef CONFIG_PM 373#ifdef CONFIG_PM
diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c
index 17c5f346ff01..030952f1f97c 100644
--- a/drivers/ata/pata_cs5520.c
+++ b/drivers/ata/pata_cs5520.c
@@ -221,7 +221,7 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi
221 continue; 221 continue;
222 222
223 rc = devm_request_irq(&pdev->dev, irq[ap->port_no], 223 rc = devm_request_irq(&pdev->dev, irq[ap->port_no],
224 ata_sff_interrupt, 0, DRV_NAME, host); 224 ata_bmdma_interrupt, 0, DRV_NAME, host);
225 if (rc) 225 if (rc)
226 return rc; 226 return rc;
227 227
diff --git a/drivers/ata/pata_cs5530.c b/drivers/ata/pata_cs5530.c
index e809a4233a81..f792330f0d8e 100644
--- a/drivers/ata/pata_cs5530.c
+++ b/drivers/ata/pata_cs5530.c
@@ -324,7 +324,7 @@ static int cs5530_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
324 ppi[1] = &info_palmax_secondary; 324 ppi[1] = &info_palmax_secondary;
325 325
326 /* Now kick off ATA set up */ 326 /* Now kick off ATA set up */
327 return ata_pci_sff_init_one(pdev, ppi, &cs5530_sht, NULL, 0); 327 return ata_pci_bmdma_init_one(pdev, ppi, &cs5530_sht, NULL, 0);
328} 328}
329 329
330#ifdef CONFIG_PM 330#ifdef CONFIG_PM
diff --git a/drivers/ata/pata_cs5535.c b/drivers/ata/pata_cs5535.c
index a02e6459fdcc..03a93186aa19 100644
--- a/drivers/ata/pata_cs5535.c
+++ b/drivers/ata/pata_cs5535.c
@@ -198,7 +198,7 @@ static int cs5535_init_one(struct pci_dev *dev, const struct pci_device_id *id)
198 rdmsr(ATAC_CH0D1_PIO, timings, dummy); 198 rdmsr(ATAC_CH0D1_PIO, timings, dummy);
199 if (CS5535_BAD_PIO(timings)) 199 if (CS5535_BAD_PIO(timings))
200 wrmsr(ATAC_CH0D1_PIO, 0xF7F4F7F4UL, 0); 200 wrmsr(ATAC_CH0D1_PIO, 0xF7F4F7F4UL, 0);
201 return ata_pci_sff_init_one(dev, ppi, &cs5535_sht, NULL, 0); 201 return ata_pci_bmdma_init_one(dev, ppi, &cs5535_sht, NULL, 0);
202} 202}
203 203
204static const struct pci_device_id cs5535[] = { 204static const struct pci_device_id cs5535[] = {
diff --git a/drivers/ata/pata_cs5536.c b/drivers/ata/pata_cs5536.c
index 914ae3506ff5..21ee23f89e88 100644
--- a/drivers/ata/pata_cs5536.c
+++ b/drivers/ata/pata_cs5536.c
@@ -260,7 +260,7 @@ static int cs5536_init_one(struct pci_dev *dev, const struct pci_device_id *id)
260 return -ENODEV; 260 return -ENODEV;
261 } 261 }
262 262
263 return ata_pci_sff_init_one(dev, ppi, &cs5536_sht, NULL, 0); 263 return ata_pci_bmdma_init_one(dev, ppi, &cs5536_sht, NULL, 0);
264} 264}
265 265
266static const struct pci_device_id cs5536[] = { 266static const struct pci_device_id cs5536[] = {
diff --git a/drivers/ata/pata_cypress.c b/drivers/ata/pata_cypress.c
index 0fcc096b8dac..6d915b063d93 100644
--- a/drivers/ata/pata_cypress.c
+++ b/drivers/ata/pata_cypress.c
@@ -138,7 +138,7 @@ static int cy82c693_init_one(struct pci_dev *pdev, const struct pci_device_id *i
138 if (PCI_FUNC(pdev->devfn) != 1) 138 if (PCI_FUNC(pdev->devfn) != 1)
139 return -ENODEV; 139 return -ENODEV;
140 140
141 return ata_pci_sff_init_one(pdev, ppi, &cy82c693_sht, NULL, 0); 141 return ata_pci_bmdma_init_one(pdev, ppi, &cy82c693_sht, NULL, 0);
142} 142}
143 143
144static const struct pci_device_id cy82c693[] = { 144static const struct pci_device_id cy82c693[] = {
diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c
index 3bac0e079691..a08834758ea2 100644
--- a/drivers/ata/pata_efar.c
+++ b/drivers/ata/pata_efar.c
@@ -277,8 +277,8 @@ static int efar_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
277 dev_printk(KERN_DEBUG, &pdev->dev, 277 dev_printk(KERN_DEBUG, &pdev->dev,
278 "version " DRV_VERSION "\n"); 278 "version " DRV_VERSION "\n");
279 279
280 return ata_pci_sff_init_one(pdev, ppi, &efar_sht, NULL, 280 return ata_pci_bmdma_init_one(pdev, ppi, &efar_sht, NULL,
281 ATA_HOST_PARALLEL_SCAN); 281 ATA_HOST_PARALLEL_SCAN);
282} 282}
283 283
284static const struct pci_device_id efar_pci_tbl[] = { 284static const struct pci_device_id efar_pci_tbl[] = {
diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c
index 8580eb3cd54d..7688868557b9 100644
--- a/drivers/ata/pata_hpt366.c
+++ b/drivers/ata/pata_hpt366.c
@@ -361,7 +361,7 @@ static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
361 break; 361 break;
362 } 362 }
363 /* Now kick off ATA set up */ 363 /* Now kick off ATA set up */
364 return ata_pci_sff_init_one(dev, ppi, &hpt36x_sht, hpriv, 0); 364 return ata_pci_bmdma_init_one(dev, ppi, &hpt36x_sht, hpriv, 0);
365} 365}
366 366
367#ifdef CONFIG_PM 367#ifdef CONFIG_PM
diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c
index 98b498b6907c..9ae4c0830577 100644
--- a/drivers/ata/pata_hpt37x.c
+++ b/drivers/ata/pata_hpt37x.c
@@ -987,7 +987,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
987 } 987 }
988 988
989 /* Now kick off ATA set up */ 989 /* Now kick off ATA set up */
990 return ata_pci_sff_init_one(dev, ppi, &hpt37x_sht, private_data, 0); 990 return ata_pci_bmdma_init_one(dev, ppi, &hpt37x_sht, private_data, 0);
991} 991}
992 992
993static const struct pci_device_id hpt37x[] = { 993static const struct pci_device_id hpt37x[] = {
diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c
index 8b95aeba0e74..32f3463216b8 100644
--- a/drivers/ata/pata_hpt3x2n.c
+++ b/drivers/ata/pata_hpt3x2n.c
@@ -548,7 +548,7 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
548 outb(inb(iobase + 0x9c) | 0x04, iobase + 0x9c); 548 outb(inb(iobase + 0x9c) | 0x04, iobase + 0x9c);
549 549
550 /* Now kick off ATA set up */ 550 /* Now kick off ATA set up */
551 return ata_pci_sff_init_one(dev, ppi, &hpt3x2n_sht, hpriv, 0); 551 return ata_pci_bmdma_init_one(dev, ppi, &hpt3x2n_sht, hpriv, 0);
552} 552}
553 553
554static const struct pci_device_id hpt3x2n[] = { 554static const struct pci_device_id hpt3x2n[] = {
diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c
index 727a81ce4c9f..b63d5e2d4628 100644
--- a/drivers/ata/pata_hpt3x3.c
+++ b/drivers/ata/pata_hpt3x3.c
@@ -248,7 +248,7 @@ static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
248 ata_port_pbar_desc(ap, 4, offset_cmd[i], "cmd"); 248 ata_port_pbar_desc(ap, 4, offset_cmd[i], "cmd");
249 } 249 }
250 pci_set_master(pdev); 250 pci_set_master(pdev);
251 return ata_host_activate(host, pdev->irq, ata_sff_interrupt, 251 return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt,
252 IRQF_SHARED, &hpt3x3_sht); 252 IRQF_SHARED, &hpt3x3_sht);
253} 253}
254 254
diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c
index b56e8f722d20..9f2889fe43b2 100644
--- a/drivers/ata/pata_icside.c
+++ b/drivers/ata/pata_icside.c
@@ -470,7 +470,7 @@ static int __devinit pata_icside_add_ports(struct pata_icside_info *info)
470 pata_icside_setup_ioaddr(ap, info->base, info, info->port[i]); 470 pata_icside_setup_ioaddr(ap, info->base, info, info->port[i]);
471 } 471 }
472 472
473 return ata_host_activate(host, ec->irq, ata_sff_interrupt, 0, 473 return ata_host_activate(host, ec->irq, ata_bmdma_interrupt, 0,
474 &pata_icside_sht); 474 &pata_icside_sht);
475} 475}
476 476
diff --git a/drivers/ata/pata_it8213.c b/drivers/ata/pata_it8213.c
index f971f0de88e6..4d142a2ab8fd 100644
--- a/drivers/ata/pata_it8213.c
+++ b/drivers/ata/pata_it8213.c
@@ -273,7 +273,7 @@ static int it8213_init_one (struct pci_dev *pdev, const struct pci_device_id *en
273 dev_printk(KERN_DEBUG, &pdev->dev, 273 dev_printk(KERN_DEBUG, &pdev->dev,
274 "version " DRV_VERSION "\n"); 274 "version " DRV_VERSION "\n");
275 275
276 return ata_pci_sff_init_one(pdev, ppi, &it8213_sht, NULL, 0); 276 return ata_pci_bmdma_init_one(pdev, ppi, &it8213_sht, NULL, 0);
277} 277}
278 278
279static const struct pci_device_id it8213_pci_tbl[] = { 279static const struct pci_device_id it8213_pci_tbl[] = {
diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c
index 2bd2b002d14a..bf88f71a21f4 100644
--- a/drivers/ata/pata_it821x.c
+++ b/drivers/ata/pata_it821x.c
@@ -933,7 +933,7 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
933 else 933 else
934 ppi[0] = &info_smart; 934 ppi[0] = &info_smart;
935 } 935 }
936 return ata_pci_sff_init_one(pdev, ppi, &it821x_sht, NULL, 0); 936 return ata_pci_bmdma_init_one(pdev, ppi, &it821x_sht, NULL, 0);
937} 937}
938 938
939#ifdef CONFIG_PM 939#ifdef CONFIG_PM
diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c
index 565e01e6ac7c..cb3babbb7035 100644
--- a/drivers/ata/pata_jmicron.c
+++ b/drivers/ata/pata_jmicron.c
@@ -144,7 +144,7 @@ static int jmicron_init_one (struct pci_dev *pdev, const struct pci_device_id *i
144 }; 144 };
145 const struct ata_port_info *ppi[] = { &info, NULL }; 145 const struct ata_port_info *ppi[] = { &info, NULL };
146 146
147 return ata_pci_sff_init_one(pdev, ppi, &jmicron_sht, NULL, 0); 147 return ata_pci_bmdma_init_one(pdev, ppi, &jmicron_sht, NULL, 0);
148} 148}
149 149
150static const struct pci_device_id jmicron_pci_tbl[] = { 150static const struct pci_device_id jmicron_pci_tbl[] = {
diff --git a/drivers/ata/pata_macio.c b/drivers/ata/pata_macio.c
index b5b48e703cb7..75b49d01780b 100644
--- a/drivers/ata/pata_macio.c
+++ b/drivers/ata/pata_macio.c
@@ -1110,7 +1110,7 @@ static int __devinit pata_macio_common_init(struct pata_macio_priv *priv,
1110 1110
1111 /* Start it up */ 1111 /* Start it up */
1112 priv->irq = irq; 1112 priv->irq = irq;
1113 return ata_host_activate(priv->host, irq, ata_sff_interrupt, 0, 1113 return ata_host_activate(priv->host, irq, ata_bmdma_interrupt, 0,
1114 &pata_macio_sht); 1114 &pata_macio_sht);
1115} 1115}
1116 1116
@@ -1355,8 +1355,11 @@ static struct of_device_id pata_macio_match[] =
1355 1355
1356static struct macio_driver pata_macio_driver = 1356static struct macio_driver pata_macio_driver =
1357{ 1357{
1358 .name = "pata-macio", 1358 .driver = {
1359 .match_table = pata_macio_match, 1359 .name = "pata-macio",
1360 .owner = THIS_MODULE,
1361 .of_match_table = pata_macio_match,
1362 },
1360 .probe = pata_macio_attach, 1363 .probe = pata_macio_attach,
1361 .remove = pata_macio_detach, 1364 .remove = pata_macio_detach,
1362#ifdef CONFIG_PM 1365#ifdef CONFIG_PM
@@ -1366,9 +1369,6 @@ static struct macio_driver pata_macio_driver =
1366#ifdef CONFIG_PMAC_MEDIABAY 1369#ifdef CONFIG_PMAC_MEDIABAY
1367 .mediabay_event = pata_macio_mb_event, 1370 .mediabay_event = pata_macio_mb_event,
1368#endif 1371#endif
1369 .driver = {
1370 .owner = THIS_MODULE,
1371 },
1372}; 1372};
1373 1373
1374static const struct pci_device_id pata_macio_pci_match[] = { 1374static const struct pci_device_id pata_macio_pci_match[] = {
diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c
index e8ca02e5a71d..dd38083dcbeb 100644
--- a/drivers/ata/pata_marvell.c
+++ b/drivers/ata/pata_marvell.c
@@ -153,7 +153,7 @@ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *i
153 return -ENODEV; 153 return -ENODEV;
154 } 154 }
155#endif 155#endif
156 return ata_pci_sff_init_one(pdev, ppi, &marvell_sht, NULL, 0); 156 return ata_pci_bmdma_init_one(pdev, ppi, &marvell_sht, NULL, 0);
157} 157}
158 158
159static const struct pci_device_id marvell_pci_tbl[] = { 159static const struct pci_device_id marvell_pci_tbl[] = {
diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c
index 36afe2c1c747..f087ab55b1df 100644
--- a/drivers/ata/pata_mpc52xx.c
+++ b/drivers/ata/pata_mpc52xx.c
@@ -659,7 +659,7 @@ mpc52xx_ata_init_one(struct device *dev, struct mpc52xx_ata_priv *priv,
659 ata_port_desc(ap, "ata_regs 0x%lx", raw_ata_regs); 659 ata_port_desc(ap, "ata_regs 0x%lx", raw_ata_regs);
660 660
661 /* activate host */ 661 /* activate host */
662 return ata_host_activate(host, priv->ata_irq, ata_sff_interrupt, 0, 662 return ata_host_activate(host, priv->ata_irq, ata_bmdma_interrupt, 0,
663 &mpc52xx_ata_sht); 663 &mpc52xx_ata_sht);
664} 664}
665 665
diff --git a/drivers/ata/pata_netcell.c b/drivers/ata/pata_netcell.c
index 94f979a7f4f7..3eb921c746a1 100644
--- a/drivers/ata/pata_netcell.c
+++ b/drivers/ata/pata_netcell.c
@@ -82,7 +82,7 @@ static int netcell_init_one (struct pci_dev *pdev, const struct pci_device_id *e
82 ata_pci_bmdma_clear_simplex(pdev); 82 ata_pci_bmdma_clear_simplex(pdev);
83 83
84 /* And let the library code do the work */ 84 /* And let the library code do the work */
85 return ata_pci_sff_init_one(pdev, port_info, &netcell_sht, NULL, 0); 85 return ata_pci_bmdma_init_one(pdev, port_info, &netcell_sht, NULL, 0);
86} 86}
87 87
88static const struct pci_device_id netcell_pci_tbl[] = { 88static const struct pci_device_id netcell_pci_tbl[] = {
diff --git a/drivers/ata/pata_ninja32.c b/drivers/ata/pata_ninja32.c
index dd53a66b19e3..cc50bd09aa26 100644
--- a/drivers/ata/pata_ninja32.c
+++ b/drivers/ata/pata_ninja32.c
@@ -149,7 +149,7 @@ static int ninja32_init_one(struct pci_dev *dev, const struct pci_device_id *id)
149 149
150 ninja32_program(base); 150 ninja32_program(base);
151 /* FIXME: Should we disable them at remove ? */ 151 /* FIXME: Should we disable them at remove ? */
152 return ata_host_activate(host, dev->irq, ata_sff_interrupt, 152 return ata_host_activate(host, dev->irq, ata_bmdma_interrupt,
153 IRQF_SHARED, &ninja32_sht); 153 IRQF_SHARED, &ninja32_sht);
154} 154}
155 155
diff --git a/drivers/ata/pata_ns87415.c b/drivers/ata/pata_ns87415.c
index fdbba2d76d3e..605f198f958c 100644
--- a/drivers/ata/pata_ns87415.c
+++ b/drivers/ata/pata_ns87415.c
@@ -380,7 +380,7 @@ static int ns87415_init_one (struct pci_dev *pdev, const struct pci_device_id *e
380 380
381 ns87415_fixup(pdev); 381 ns87415_fixup(pdev);
382 382
383 return ata_pci_sff_init_one(pdev, ppi, &ns87415_sht, NULL, 0); 383 return ata_pci_bmdma_init_one(pdev, ppi, &ns87415_sht, NULL, 0);
384} 384}
385 385
386static const struct pci_device_id ns87415_pci_tbl[] = { 386static const struct pci_device_id ns87415_pci_tbl[] = {
diff --git a/drivers/ata/pata_octeon_cf.c b/drivers/ata/pata_octeon_cf.c
index 3001109352ea..06ddd91ffeda 100644
--- a/drivers/ata/pata_octeon_cf.c
+++ b/drivers/ata/pata_octeon_cf.c
@@ -750,20 +750,6 @@ static void octeon_cf_dev_config(struct ata_device *dev)
750} 750}
751 751
752/* 752/*
753 * Trap if driver tries to do standard bmdma commands. They are not
754 * supported.
755 */
756static void unreachable_qc(struct ata_queued_cmd *qc)
757{
758 BUG();
759}
760
761static u8 unreachable_port(struct ata_port *ap)
762{
763 BUG();
764}
765
766/*
767 * We don't do ATAPI DMA so return 0. 753 * We don't do ATAPI DMA so return 0.
768 */ 754 */
769static int octeon_cf_check_atapi_dma(struct ata_queued_cmd *qc) 755static int octeon_cf_check_atapi_dma(struct ata_queued_cmd *qc)
@@ -804,10 +790,6 @@ static struct ata_port_operations octeon_cf_ops = {
804 .sff_dev_select = octeon_cf_dev_select, 790 .sff_dev_select = octeon_cf_dev_select,
805 .sff_irq_on = octeon_cf_irq_on, 791 .sff_irq_on = octeon_cf_irq_on,
806 .sff_irq_clear = octeon_cf_irq_clear, 792 .sff_irq_clear = octeon_cf_irq_clear,
807 .bmdma_setup = unreachable_qc,
808 .bmdma_start = unreachable_qc,
809 .bmdma_stop = unreachable_qc,
810 .bmdma_status = unreachable_port,
811 .cable_detect = ata_cable_40wire, 793 .cable_detect = ata_cable_40wire,
812 .set_piomode = octeon_cf_set_piomode, 794 .set_piomode = octeon_cf_set_piomode,
813 .set_dmamode = octeon_cf_set_dmamode, 795 .set_dmamode = octeon_cf_set_dmamode,
diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c
index 988ef2627be3..b811c1636204 100644
--- a/drivers/ata/pata_oldpiix.c
+++ b/drivers/ata/pata_oldpiix.c
@@ -248,7 +248,7 @@ static int oldpiix_init_one (struct pci_dev *pdev, const struct pci_device_id *e
248 dev_printk(KERN_DEBUG, &pdev->dev, 248 dev_printk(KERN_DEBUG, &pdev->dev,
249 "version " DRV_VERSION "\n"); 249 "version " DRV_VERSION "\n");
250 250
251 return ata_pci_sff_init_one(pdev, ppi, &oldpiix_sht, NULL, 0); 251 return ata_pci_bmdma_init_one(pdev, ppi, &oldpiix_sht, NULL, 0);
252} 252}
253 253
254static const struct pci_device_id oldpiix_pci_tbl[] = { 254static const struct pci_device_id oldpiix_pci_tbl[] = {
diff --git a/drivers/ata/pata_optidma.c b/drivers/ata/pata_optidma.c
index 76b7d12b1e8d..0852cd07de08 100644
--- a/drivers/ata/pata_optidma.c
+++ b/drivers/ata/pata_optidma.c
@@ -429,7 +429,7 @@ static int optidma_init_one(struct pci_dev *dev, const struct pci_device_id *id)
429 if (optiplus_with_udma(dev)) 429 if (optiplus_with_udma(dev))
430 ppi[0] = &info_82c700_udma; 430 ppi[0] = &info_82c700_udma;
431 431
432 return ata_pci_sff_init_one(dev, ppi, &optidma_sht, NULL, 0); 432 return ata_pci_bmdma_init_one(dev, ppi, &optidma_sht, NULL, 0);
433} 433}
434 434
435static const struct pci_device_id optidma[] = { 435static const struct pci_device_id optidma[] = {
diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c
index 09f1f22c0307..b18351122525 100644
--- a/drivers/ata/pata_pdc2027x.c
+++ b/drivers/ata/pata_pdc2027x.c
@@ -754,7 +754,7 @@ static int __devinit pdc2027x_init_one(struct pci_dev *pdev, const struct pci_de
754 return -EIO; 754 return -EIO;
755 755
756 pci_set_master(pdev); 756 pci_set_master(pdev);
757 return ata_host_activate(host, pdev->irq, ata_sff_interrupt, 757 return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt,
758 IRQF_SHARED, &pdc2027x_sht); 758 IRQF_SHARED, &pdc2027x_sht);
759} 759}
760 760
diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c
index fa1e2f3bc0fd..c39f213e1bbc 100644
--- a/drivers/ata/pata_pdc202xx_old.c
+++ b/drivers/ata/pata_pdc202xx_old.c
@@ -337,7 +337,7 @@ static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id
337 return -ENODEV; 337 return -ENODEV;
338 } 338 }
339 } 339 }
340 return ata_pci_sff_init_one(dev, ppi, &pdc202xx_sht, NULL, 0); 340 return ata_pci_bmdma_init_one(dev, ppi, &pdc202xx_sht, NULL, 0);
341} 341}
342 342
343static const struct pci_device_id pdc202xx[] = { 343static const struct pci_device_id pdc202xx[] = {
diff --git a/drivers/ata/pata_piccolo.c b/drivers/ata/pata_piccolo.c
index 981615414849..cb01bf9496fe 100644
--- a/drivers/ata/pata_piccolo.c
+++ b/drivers/ata/pata_piccolo.c
@@ -95,7 +95,7 @@ static int ata_tosh_init_one(struct pci_dev *dev, const struct pci_device_id *id
95 }; 95 };
96 const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info }; 96 const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info };
97 /* Just one port for the moment */ 97 /* Just one port for the moment */
98 return ata_pci_sff_init_one(dev, ppi, &tosh_sht, NULL, 0); 98 return ata_pci_bmdma_init_one(dev, ppi, &tosh_sht, NULL, 0);
99} 99}
100 100
101static struct pci_device_id ata_tosh[] = { 101static struct pci_device_id ata_tosh[] = {
diff --git a/drivers/ata/pata_radisys.c b/drivers/ata/pata_radisys.c
index a5fa388e5398..8574b31f1773 100644
--- a/drivers/ata/pata_radisys.c
+++ b/drivers/ata/pata_radisys.c
@@ -227,7 +227,7 @@ static int radisys_init_one (struct pci_dev *pdev, const struct pci_device_id *e
227 dev_printk(KERN_DEBUG, &pdev->dev, 227 dev_printk(KERN_DEBUG, &pdev->dev,
228 "version " DRV_VERSION "\n"); 228 "version " DRV_VERSION "\n");
229 229
230 return ata_pci_sff_init_one(pdev, ppi, &radisys_sht, NULL, 0); 230 return ata_pci_bmdma_init_one(pdev, ppi, &radisys_sht, NULL, 0);
231} 231}
232 232
233static const struct pci_device_id radisys_pci_tbl[] = { 233static const struct pci_device_id radisys_pci_tbl[] = {
diff --git a/drivers/ata/pata_rdc.c b/drivers/ata/pata_rdc.c
index 37092cfd7bc6..5fbe9b166c69 100644
--- a/drivers/ata/pata_rdc.c
+++ b/drivers/ata/pata_rdc.c
@@ -344,7 +344,7 @@ static int __devinit rdc_init_one(struct pci_dev *pdev,
344 */ 344 */
345 pci_read_config_dword(pdev, 0x54, &hpriv->saved_iocfg); 345 pci_read_config_dword(pdev, 0x54, &hpriv->saved_iocfg);
346 346
347 rc = ata_pci_sff_prepare_host(pdev, ppi, &host); 347 rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host);
348 if (rc) 348 if (rc)
349 return rc; 349 return rc;
350 host->private_data = hpriv; 350 host->private_data = hpriv;
@@ -354,7 +354,7 @@ static int __devinit rdc_init_one(struct pci_dev *pdev,
354 host->flags |= ATA_HOST_PARALLEL_SCAN; 354 host->flags |= ATA_HOST_PARALLEL_SCAN;
355 355
356 pci_set_master(pdev); 356 pci_set_master(pdev);
357 return ata_pci_sff_activate_host(host, ata_sff_interrupt, &rdc_sht); 357 return ata_pci_sff_activate_host(host, ata_bmdma_interrupt, &rdc_sht);
358} 358}
359 359
360static void rdc_remove_one(struct pci_dev *pdev) 360static void rdc_remove_one(struct pci_dev *pdev)
diff --git a/drivers/ata/pata_sc1200.c b/drivers/ata/pata_sc1200.c
index 6b5b63a2fd8e..e2c18257adff 100644
--- a/drivers/ata/pata_sc1200.c
+++ b/drivers/ata/pata_sc1200.c
@@ -237,7 +237,7 @@ static int sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id)
237 }; 237 };
238 const struct ata_port_info *ppi[] = { &info, NULL }; 238 const struct ata_port_info *ppi[] = { &info, NULL };
239 239
240 return ata_pci_sff_init_one(dev, ppi, &sc1200_sht, NULL, 0); 240 return ata_pci_bmdma_init_one(dev, ppi, &sc1200_sht, NULL, 0);
241} 241}
242 242
243static const struct pci_device_id sc1200[] = { 243static const struct pci_device_id sc1200[] = {
diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c
index 6f6193b707cb..d9db3f8d60ef 100644
--- a/drivers/ata/pata_scc.c
+++ b/drivers/ata/pata_scc.c
@@ -875,7 +875,7 @@ static void scc_postreset(struct ata_link *link, unsigned int *classes)
875 * scc_irq_clear - Clear PCI IDE BMDMA interrupt. 875 * scc_irq_clear - Clear PCI IDE BMDMA interrupt.
876 * @ap: Port associated with this ATA transaction. 876 * @ap: Port associated with this ATA transaction.
877 * 877 *
878 * Note: Original code is ata_sff_irq_clear(). 878 * Note: Original code is ata_bmdma_irq_clear().
879 */ 879 */
880 880
881static void scc_irq_clear (struct ata_port *ap) 881static void scc_irq_clear (struct ata_port *ap)
@@ -1105,7 +1105,7 @@ static int scc_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
1105 if (rc) 1105 if (rc)
1106 return rc; 1106 return rc;
1107 1107
1108 return ata_host_activate(host, pdev->irq, ata_sff_interrupt, 1108 return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt,
1109 IRQF_SHARED, &scc_sht); 1109 IRQF_SHARED, &scc_sht);
1110} 1110}
1111 1111
diff --git a/drivers/ata/pata_sch.c b/drivers/ata/pata_sch.c
index 86b3d0133c7c..e97b32f03a6e 100644
--- a/drivers/ata/pata_sch.c
+++ b/drivers/ata/pata_sch.c
@@ -179,7 +179,7 @@ static int __devinit sch_init_one(struct pci_dev *pdev,
179 dev_printk(KERN_DEBUG, &pdev->dev, 179 dev_printk(KERN_DEBUG, &pdev->dev,
180 "version " DRV_VERSION "\n"); 180 "version " DRV_VERSION "\n");
181 181
182 return ata_pci_sff_init_one(pdev, ppi, &sch_sht, NULL, 0); 182 return ata_pci_bmdma_init_one(pdev, ppi, &sch_sht, NULL, 0);
183} 183}
184 184
185static int __init sch_init(void) 185static int __init sch_init(void)
diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c
index 43ea389df2b3..86dd714e3e1d 100644
--- a/drivers/ata/pata_serverworks.c
+++ b/drivers/ata/pata_serverworks.c
@@ -460,7 +460,7 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id
460 if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) 460 if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE)
461 ata_pci_bmdma_clear_simplex(pdev); 461 ata_pci_bmdma_clear_simplex(pdev);
462 462
463 return ata_pci_sff_init_one(pdev, ppi, &serverworks_sht, NULL, 0); 463 return ata_pci_bmdma_init_one(pdev, ppi, &serverworks_sht, NULL, 0);
464} 464}
465 465
466#ifdef CONFIG_PM 466#ifdef CONFIG_PM
diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c
index 43faf106f647..d3190d7ec304 100644
--- a/drivers/ata/pata_sil680.c
+++ b/drivers/ata/pata_sil680.c
@@ -374,11 +374,11 @@ static int __devinit sil680_init_one(struct pci_dev *pdev,
374 ata_sff_std_ports(&host->ports[1]->ioaddr); 374 ata_sff_std_ports(&host->ports[1]->ioaddr);
375 375
376 /* Register & activate */ 376 /* Register & activate */
377 return ata_host_activate(host, pdev->irq, ata_sff_interrupt, 377 return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt,
378 IRQF_SHARED, &sil680_sht); 378 IRQF_SHARED, &sil680_sht);
379 379
380use_ioports: 380use_ioports:
381 return ata_pci_sff_init_one(pdev, ppi, &sil680_sht, NULL, 0); 381 return ata_pci_bmdma_init_one(pdev, ppi, &sil680_sht, NULL, 0);
382} 382}
383 383
384#ifdef CONFIG_PM 384#ifdef CONFIG_PM
diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c
index b6708032f321..60cea13cccce 100644
--- a/drivers/ata/pata_sis.c
+++ b/drivers/ata/pata_sis.c
@@ -826,7 +826,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
826 826
827 sis_fixup(pdev, chipset); 827 sis_fixup(pdev, chipset);
828 828
829 return ata_pci_sff_init_one(pdev, ppi, &sis_sht, chipset, 0); 829 return ata_pci_bmdma_init_one(pdev, ppi, &sis_sht, chipset, 0);
830} 830}
831 831
832#ifdef CONFIG_PM 832#ifdef CONFIG_PM
diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c
index 733b042a7469..98548f640c8e 100644
--- a/drivers/ata/pata_sl82c105.c
+++ b/drivers/ata/pata_sl82c105.c
@@ -316,7 +316,7 @@ static int sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id
316 val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16; 316 val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16;
317 pci_write_config_dword(dev, 0x40, val); 317 pci_write_config_dword(dev, 0x40, val);
318 318
319 return ata_pci_sff_init_one(dev, ppi, &sl82c105_sht, NULL, 0); 319 return ata_pci_bmdma_init_one(dev, ppi, &sl82c105_sht, NULL, 0);
320} 320}
321 321
322static const struct pci_device_id sl82c105[] = { 322static const struct pci_device_id sl82c105[] = {
diff --git a/drivers/ata/pata_triflex.c b/drivers/ata/pata_triflex.c
index 48f50600ed2a..0d1f89e571dd 100644
--- a/drivers/ata/pata_triflex.c
+++ b/drivers/ata/pata_triflex.c
@@ -201,7 +201,7 @@ static int triflex_init_one(struct pci_dev *dev, const struct pci_device_id *id)
201 if (!printed_version++) 201 if (!printed_version++)
202 dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n"); 202 dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n");
203 203
204 return ata_pci_sff_init_one(dev, ppi, &triflex_sht, NULL, 0); 204 return ata_pci_bmdma_init_one(dev, ppi, &triflex_sht, NULL, 0);
205} 205}
206 206
207static const struct pci_device_id triflex[] = { 207static const struct pci_device_id triflex[] = {
diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c
index 7e3e0a5598b7..5e659885de16 100644
--- a/drivers/ata/pata_via.c
+++ b/drivers/ata/pata_via.c
@@ -627,7 +627,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
627 } 627 }
628 628
629 /* We have established the device type, now fire it up */ 629 /* We have established the device type, now fire it up */
630 return ata_pci_sff_init_one(pdev, ppi, &via_sht, (void *)config, 0); 630 return ata_pci_bmdma_init_one(pdev, ppi, &via_sht, (void *)config, 0);
631} 631}
632 632
633#ifdef CONFIG_PM 633#ifdef CONFIG_PM
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index f3471bc949d3..a476cd99b95d 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -675,8 +675,6 @@ static struct ata_port_operations mv5_ops = {
675 .freeze = mv_eh_freeze, 675 .freeze = mv_eh_freeze,
676 .thaw = mv_eh_thaw, 676 .thaw = mv_eh_thaw,
677 .hardreset = mv_hardreset, 677 .hardreset = mv_hardreset,
678 .error_handler = ata_std_error_handler, /* avoid SFF EH */
679 .post_internal_cmd = ATA_OP_NULL,
680 678
681 .scr_read = mv5_scr_read, 679 .scr_read = mv5_scr_read,
682 .scr_write = mv5_scr_write, 680 .scr_write = mv5_scr_write,
@@ -2813,7 +2811,7 @@ static void mv_port_intr(struct ata_port *ap, u32 port_cause)
2813 } else if (!edma_was_enabled) { 2811 } else if (!edma_was_enabled) {
2814 struct ata_queued_cmd *qc = mv_get_active_qc(ap); 2812 struct ata_queued_cmd *qc = mv_get_active_qc(ap);
2815 if (qc) 2813 if (qc)
2816 ata_sff_host_intr(ap, qc); 2814 ata_bmdma_port_intr(ap, qc);
2817 else 2815 else
2818 mv_unexpected_intr(ap, edma_was_enabled); 2816 mv_unexpected_intr(ap, edma_was_enabled);
2819 } 2817 }
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index baa8f0d2c86f..21161136cad0 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -920,7 +920,7 @@ static int nv_host_intr(struct ata_port *ap, u8 irq_stat)
920 } 920 }
921 921
922 /* handle interrupt */ 922 /* handle interrupt */
923 return ata_sff_host_intr(ap, qc); 923 return ata_bmdma_port_intr(ap, qc);
924} 924}
925 925
926static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance) 926static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
@@ -1100,7 +1100,7 @@ static void nv_adma_irq_clear(struct ata_port *ap)
1100 u32 notifier_clears[2]; 1100 u32 notifier_clears[2];
1101 1101
1102 if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) { 1102 if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) {
1103 ata_sff_irq_clear(ap); 1103 ata_bmdma_irq_clear(ap);
1104 return; 1104 return;
1105 } 1105 }
1106 1106
@@ -1505,7 +1505,7 @@ static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance)
1505 1505
1506 qc = ata_qc_from_tag(ap, ap->link.active_tag); 1506 qc = ata_qc_from_tag(ap, ap->link.active_tag);
1507 if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) { 1507 if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
1508 handled += ata_sff_host_intr(ap, qc); 1508 handled += ata_bmdma_port_intr(ap, qc);
1509 } else { 1509 } else {
1510 /* 1510 /*
1511 * No request pending? Clear interrupt status 1511 * No request pending? Clear interrupt status
@@ -1669,7 +1669,6 @@ static void nv_mcp55_freeze(struct ata_port *ap)
1669 mask = readl(mmio_base + NV_INT_ENABLE_MCP55); 1669 mask = readl(mmio_base + NV_INT_ENABLE_MCP55);
1670 mask &= ~(NV_INT_ALL_MCP55 << shift); 1670 mask &= ~(NV_INT_ALL_MCP55 << shift);
1671 writel(mask, mmio_base + NV_INT_ENABLE_MCP55); 1671 writel(mask, mmio_base + NV_INT_ENABLE_MCP55);
1672 ata_sff_freeze(ap);
1673} 1672}
1674 1673
1675static void nv_mcp55_thaw(struct ata_port *ap) 1674static void nv_mcp55_thaw(struct ata_port *ap)
@@ -1683,7 +1682,6 @@ static void nv_mcp55_thaw(struct ata_port *ap)
1683 mask = readl(mmio_base + NV_INT_ENABLE_MCP55); 1682 mask = readl(mmio_base + NV_INT_ENABLE_MCP55);
1684 mask |= (NV_INT_MASK_MCP55 << shift); 1683 mask |= (NV_INT_MASK_MCP55 << shift);
1685 writel(mask, mmio_base + NV_INT_ENABLE_MCP55); 1684 writel(mask, mmio_base + NV_INT_ENABLE_MCP55);
1686 ata_sff_thaw(ap);
1687} 1685}
1688 1686
1689static void nv_adma_error_handler(struct ata_port *ap) 1687static void nv_adma_error_handler(struct ata_port *ap)
@@ -2430,7 +2428,7 @@ static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
2430 2428
2431 ppi[0] = &nv_port_info[type]; 2429 ppi[0] = &nv_port_info[type];
2432 ipriv = ppi[0]->private_data; 2430 ipriv = ppi[0]->private_data;
2433 rc = ata_pci_sff_prepare_host(pdev, ppi, &host); 2431 rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host);
2434 if (rc) 2432 if (rc)
2435 return rc; 2433 return rc;
2436 2434
diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c
index d533b3d20ca1..daeebf19a6a9 100644
--- a/drivers/ata/sata_qstor.c
+++ b/drivers/ata/sata_qstor.c
@@ -120,8 +120,6 @@ static void qs_host_stop(struct ata_host *host);
120static void qs_qc_prep(struct ata_queued_cmd *qc); 120static void qs_qc_prep(struct ata_queued_cmd *qc);
121static unsigned int qs_qc_issue(struct ata_queued_cmd *qc); 121static unsigned int qs_qc_issue(struct ata_queued_cmd *qc);
122static int qs_check_atapi_dma(struct ata_queued_cmd *qc); 122static int qs_check_atapi_dma(struct ata_queued_cmd *qc);
123static void qs_bmdma_stop(struct ata_queued_cmd *qc);
124static u8 qs_bmdma_status(struct ata_port *ap);
125static void qs_freeze(struct ata_port *ap); 123static void qs_freeze(struct ata_port *ap);
126static void qs_thaw(struct ata_port *ap); 124static void qs_thaw(struct ata_port *ap);
127static int qs_prereset(struct ata_link *link, unsigned long deadline); 125static int qs_prereset(struct ata_link *link, unsigned long deadline);
@@ -137,8 +135,6 @@ static struct ata_port_operations qs_ata_ops = {
137 .inherits = &ata_sff_port_ops, 135 .inherits = &ata_sff_port_ops,
138 136
139 .check_atapi_dma = qs_check_atapi_dma, 137 .check_atapi_dma = qs_check_atapi_dma,
140 .bmdma_stop = qs_bmdma_stop,
141 .bmdma_status = qs_bmdma_status,
142 .qc_prep = qs_qc_prep, 138 .qc_prep = qs_qc_prep,
143 .qc_issue = qs_qc_issue, 139 .qc_issue = qs_qc_issue,
144 140
@@ -190,16 +186,6 @@ static int qs_check_atapi_dma(struct ata_queued_cmd *qc)
190 return 1; /* ATAPI DMA not supported */ 186 return 1; /* ATAPI DMA not supported */
191} 187}
192 188
193static void qs_bmdma_stop(struct ata_queued_cmd *qc)
194{
195 /* nothing */
196}
197
198static u8 qs_bmdma_status(struct ata_port *ap)
199{
200 return 0;
201}
202
203static inline void qs_enter_reg_mode(struct ata_port *ap) 189static inline void qs_enter_reg_mode(struct ata_port *ap)
204{ 190{
205 u8 __iomem *chan = qs_mmio_base(ap->host) + (ap->port_no * 0x4000); 191 u8 __iomem *chan = qs_mmio_base(ap->host) + (ap->port_no * 0x4000);
@@ -454,7 +440,7 @@ static inline unsigned int qs_intr_mmio(struct ata_host *host)
454 if (!pp || pp->state != qs_state_mmio) 440 if (!pp || pp->state != qs_state_mmio)
455 continue; 441 continue;
456 if (!(qc->tf.flags & ATA_TFLAG_POLLING)) 442 if (!(qc->tf.flags & ATA_TFLAG_POLLING))
457 handled |= ata_sff_host_intr(ap, qc); 443 handled |= ata_sff_port_intr(ap, qc);
458 } 444 }
459 return handled; 445 return handled;
460} 446}
diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c
index 2dda312b6b9a..3a4f84219719 100644
--- a/drivers/ata/sata_sil.c
+++ b/drivers/ata/sata_sil.c
@@ -503,7 +503,7 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
503 goto err_hsm; 503 goto err_hsm;
504 504
505 /* ack bmdma irq events */ 505 /* ack bmdma irq events */
506 ata_sff_irq_clear(ap); 506 ata_bmdma_irq_clear(ap);
507 507
508 /* kick HSM in the ass */ 508 /* kick HSM in the ass */
509 ata_sff_hsm_move(ap, qc, status, 0); 509 ata_sff_hsm_move(ap, qc, status, 0);
@@ -584,7 +584,7 @@ static void sil_thaw(struct ata_port *ap)
584 584
585 /* clear IRQ */ 585 /* clear IRQ */
586 ap->ops->sff_check_status(ap); 586 ap->ops->sff_check_status(ap);
587 ata_sff_irq_clear(ap); 587 ata_bmdma_irq_clear(ap);
588 588
589 /* turn on SATA IRQ if supported */ 589 /* turn on SATA IRQ if supported */
590 if (!(ap->flags & SIL_FLAG_NO_SATA_IRQ)) 590 if (!(ap->flags & SIL_FLAG_NO_SATA_IRQ))
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index e9250514734b..be7726d7686d 100644
--- a/drivers/ata/sata_sil24.c
+++ b/drivers/ata/sata_sil24.c
@@ -539,12 +539,12 @@ static void sil24_config_port(struct ata_port *ap)
539 writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR); 539 writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR);
540 540
541 /* zero error counters. */ 541 /* zero error counters. */
542 writel(0x8000, port + PORT_DECODE_ERR_THRESH); 542 writew(0x8000, port + PORT_DECODE_ERR_THRESH);
543 writel(0x8000, port + PORT_CRC_ERR_THRESH); 543 writew(0x8000, port + PORT_CRC_ERR_THRESH);
544 writel(0x8000, port + PORT_HSHK_ERR_THRESH); 544 writew(0x8000, port + PORT_HSHK_ERR_THRESH);
545 writel(0x0000, port + PORT_DECODE_ERR_CNT); 545 writew(0x0000, port + PORT_DECODE_ERR_CNT);
546 writel(0x0000, port + PORT_CRC_ERR_CNT); 546 writew(0x0000, port + PORT_CRC_ERR_CNT);
547 writel(0x0000, port + PORT_HSHK_ERR_CNT); 547 writew(0x0000, port + PORT_HSHK_ERR_CNT);
548 548
549 /* always use 64bit activation */ 549 /* always use 64bit activation */
550 writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_CLR); 550 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,
622 irq_enabled = readl(port + PORT_IRQ_ENABLE_SET); 622 irq_enabled = readl(port + PORT_IRQ_ENABLE_SET);
623 writel(PORT_IRQ_COMPLETE | PORT_IRQ_ERROR, port + PORT_IRQ_ENABLE_CLR); 623 writel(PORT_IRQ_COMPLETE | PORT_IRQ_ERROR, port + PORT_IRQ_ENABLE_CLR);
624 624
625 /*
626 * The barrier is required to ensure that writes to cmd_block reach
627 * the memory before the write to PORT_CMD_ACTIVATE.
628 */
629 wmb();
625 writel((u32)paddr, port + PORT_CMD_ACTIVATE); 630 writel((u32)paddr, port + PORT_CMD_ACTIVATE);
626 writel((u64)paddr >> 32, port + PORT_CMD_ACTIVATE + 4); 631 writel((u64)paddr >> 32, port + PORT_CMD_ACTIVATE + 4);
627 632
@@ -865,7 +870,7 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc)
865 } else { 870 } else {
866 prb = &cb->atapi.prb; 871 prb = &cb->atapi.prb;
867 sge = cb->atapi.sge; 872 sge = cb->atapi.sge;
868 memset(cb->atapi.cdb, 0, 32); 873 memset(cb->atapi.cdb, 0, sizeof(cb->atapi.cdb));
869 memcpy(cb->atapi.cdb, qc->cdb, qc->dev->cdb_len); 874 memcpy(cb->atapi.cdb, qc->cdb, qc->dev->cdb_len);
870 875
871 if (ata_is_data(qc->tf.protocol)) { 876 if (ata_is_data(qc->tf.protocol)) {
@@ -895,6 +900,11 @@ static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc)
895 paddr = pp->cmd_block_dma + tag * sizeof(*pp->cmd_block); 900 paddr = pp->cmd_block_dma + tag * sizeof(*pp->cmd_block);
896 activate = port + PORT_CMD_ACTIVATE + tag * 8; 901 activate = port + PORT_CMD_ACTIVATE + tag * 8;
897 902
903 /*
904 * The barrier is required to ensure that writes to cmd_block reach
905 * the memory before the write to PORT_CMD_ACTIVATE.
906 */
907 wmb();
898 writel((u32)paddr, activate); 908 writel((u32)paddr, activate);
899 writel((u64)paddr >> 32, activate + 4); 909 writel((u64)paddr >> 32, activate + 4);
900 910
diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c
index f8a91bfd66a8..2bfe3ae03976 100644
--- a/drivers/ata/sata_sis.c
+++ b/drivers/ata/sata_sis.c
@@ -279,7 +279,7 @@ static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
279 break; 279 break;
280 } 280 }
281 281
282 rc = ata_pci_sff_prepare_host(pdev, ppi, &host); 282 rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host);
283 if (rc) 283 if (rc)
284 return rc; 284 return rc;
285 285
@@ -308,7 +308,7 @@ static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
308 308
309 pci_set_master(pdev); 309 pci_set_master(pdev);
310 pci_intx(pdev, 1); 310 pci_intx(pdev, 1);
311 return ata_host_activate(host, pdev->irq, ata_sff_interrupt, 311 return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt,
312 IRQF_SHARED, &sis_sht); 312 IRQF_SHARED, &sis_sht);
313} 313}
314 314
diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c
index 101fd6a19829..7d9db4aaf07e 100644
--- a/drivers/ata/sata_svw.c
+++ b/drivers/ata/sata_svw.c
@@ -502,7 +502,7 @@ static int k2_sata_init_one(struct pci_dev *pdev, const struct pci_device_id *en
502 writel(0x0, mmio_base + K2_SATA_SIM_OFFSET); 502 writel(0x0, mmio_base + K2_SATA_SIM_OFFSET);
503 503
504 pci_set_master(pdev); 504 pci_set_master(pdev);
505 return ata_host_activate(host, pdev->irq, ata_sff_interrupt, 505 return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt,
506 IRQF_SHARED, &k2_sata_sht); 506 IRQF_SHARED, &k2_sata_sht);
507} 507}
508 508
diff --git a/drivers/ata/sata_uli.c b/drivers/ata/sata_uli.c
index d8dac17dc2c8..b8578c32d344 100644
--- a/drivers/ata/sata_uli.c
+++ b/drivers/ata/sata_uli.c
@@ -242,7 +242,7 @@ static int uli_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
242 242
243 pci_set_master(pdev); 243 pci_set_master(pdev);
244 pci_intx(pdev, 1); 244 pci_intx(pdev, 1);
245 return ata_host_activate(host, pdev->irq, ata_sff_interrupt, 245 return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt,
246 IRQF_SHARED, &uli_sht); 246 IRQF_SHARED, &uli_sht);
247} 247}
248 248
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c
index 08f65492cc81..4730c42a5ee5 100644
--- a/drivers/ata/sata_via.c
+++ b/drivers/ata/sata_via.c
@@ -308,7 +308,7 @@ static void svia_noop_freeze(struct ata_port *ap)
308 * certain way. Leave it alone and just clear pending IRQ. 308 * certain way. Leave it alone and just clear pending IRQ.
309 */ 309 */
310 ap->ops->sff_check_status(ap); 310 ap->ops->sff_check_status(ap);
311 ata_sff_irq_clear(ap); 311 ata_bmdma_irq_clear(ap);
312} 312}
313 313
314/** 314/**
@@ -463,7 +463,7 @@ static int vt6420_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)
463 struct ata_host *host; 463 struct ata_host *host;
464 int rc; 464 int rc;
465 465
466 rc = ata_pci_sff_prepare_host(pdev, ppi, &host); 466 rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host);
467 if (rc) 467 if (rc)
468 return rc; 468 return rc;
469 *r_host = host; 469 *r_host = host;
@@ -520,7 +520,7 @@ static int vt8251_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)
520 struct ata_host *host; 520 struct ata_host *host;
521 int i, rc; 521 int i, rc;
522 522
523 rc = ata_pci_sff_prepare_host(pdev, ppi, &host); 523 rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host);
524 if (rc) 524 if (rc)
525 return rc; 525 return rc;
526 *r_host = host; 526 *r_host = host;
@@ -575,6 +575,33 @@ static void svia_configure(struct pci_dev *pdev)
575 tmp8 |= NATIVE_MODE_ALL; 575 tmp8 |= NATIVE_MODE_ALL;
576 pci_write_config_byte(pdev, SATA_NATIVE_MODE, tmp8); 576 pci_write_config_byte(pdev, SATA_NATIVE_MODE, tmp8);
577 } 577 }
578
579 /*
580 * vt6421 has problems talking to some drives. The following
581 * is the fix from Joseph Chan <JosephChan@via.com.tw>.
582 *
583 * When host issues HOLD, device may send up to 20DW of data
584 * before acknowledging it with HOLDA and the host should be
585 * able to buffer them in FIFO. Unfortunately, some WD drives
586 * send upto 40DW before acknowledging HOLD and, in the
587 * default configuration, this ends up overflowing vt6421's
588 * FIFO, making the controller abort the transaction with
589 * R_ERR.
590 *
591 * Rx52[2] is the internal 128DW FIFO Flow control watermark
592 * adjusting mechanism enable bit and the default value 0
593 * means host will issue HOLD to device when the left FIFO
594 * size goes below 32DW. Setting it to 1 makes the watermark
595 * 64DW.
596 *
597 * https://bugzilla.kernel.org/show_bug.cgi?id=15173
598 * http://article.gmane.org/gmane.linux.ide/46352
599 */
600 if (pdev->device == 0x3249) {
601 pci_read_config_byte(pdev, 0x52, &tmp8);
602 tmp8 |= 1 << 2;
603 pci_write_config_byte(pdev, 0x52, tmp8);
604 }
578} 605}
579 606
580static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 607static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
@@ -628,7 +655,7 @@ static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
628 svia_configure(pdev); 655 svia_configure(pdev);
629 656
630 pci_set_master(pdev); 657 pci_set_master(pdev);
631 return ata_host_activate(host, pdev->irq, ata_sff_interrupt, 658 return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt,
632 IRQF_SHARED, &svia_sht); 659 IRQF_SHARED, &svia_sht);
633} 660}
634 661
diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c
index 2107952ebff1..b777176ff494 100644
--- a/drivers/ata/sata_vsc.c
+++ b/drivers/ata/sata_vsc.c
@@ -245,7 +245,7 @@ static void vsc_port_intr(u8 port_status, struct ata_port *ap)
245 245
246 qc = ata_qc_from_tag(ap, ap->link.active_tag); 246 qc = ata_qc_from_tag(ap, ap->link.active_tag);
247 if (qc && likely(!(qc->tf.flags & ATA_TFLAG_POLLING))) 247 if (qc && likely(!(qc->tf.flags & ATA_TFLAG_POLLING)))
248 handled = ata_sff_host_intr(ap, qc); 248 handled = ata_bmdma_port_intr(ap, qc);
249 249
250 /* We received an interrupt during a polled command, 250 /* We received an interrupt during a polled command,
251 * or some other spurious condition. Interrupt reporting 251 * or some other spurious condition. Interrupt reporting
diff --git a/drivers/base/topology.c b/drivers/base/topology.c
index bf6b13206d00..9fc630ce1ddb 100644
--- a/drivers/base/topology.c
+++ b/drivers/base/topology.c
@@ -162,7 +162,7 @@ static int __cpuinit topology_cpu_callback(struct notifier_block *nfb,
162 topology_remove_dev(cpu); 162 topology_remove_dev(cpu);
163 break; 163 break;
164 } 164 }
165 return rc ? NOTIFY_BAD : NOTIFY_OK; 165 return notifier_from_errno(rc);
166} 166}
167 167
168static int __cpuinit topology_sysfs_init(void) 168static int __cpuinit topology_sysfs_init(void)
diff --git a/drivers/block/brd.c b/drivers/block/brd.c
index 6081e81d5738..f1bf79d9bc0a 100644
--- a/drivers/block/brd.c
+++ b/drivers/block/brd.c
@@ -133,6 +133,28 @@ static struct page *brd_insert_page(struct brd_device *brd, sector_t sector)
133 return page; 133 return page;
134} 134}
135 135
136static void brd_free_page(struct brd_device *brd, sector_t sector)
137{
138 struct page *page;
139 pgoff_t idx;
140
141 spin_lock(&brd->brd_lock);
142 idx = sector >> PAGE_SECTORS_SHIFT;
143 page = radix_tree_delete(&brd->brd_pages, idx);
144 spin_unlock(&brd->brd_lock);
145 if (page)
146 __free_page(page);
147}
148
149static void brd_zero_page(struct brd_device *brd, sector_t sector)
150{
151 struct page *page;
152
153 page = brd_lookup_page(brd, sector);
154 if (page)
155 clear_highpage(page);
156}
157
136/* 158/*
137 * Free all backing store pages and radix tree. This must only be called when 159 * Free all backing store pages and radix tree. This must only be called when
138 * there are no other users of the device. 160 * 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)
189 return 0; 211 return 0;
190} 212}
191 213
214static void discard_from_brd(struct brd_device *brd,
215 sector_t sector, size_t n)
216{
217 while (n >= PAGE_SIZE) {
218 /*
219 * Don't want to actually discard pages here because
220 * re-allocating the pages can result in writeback
221 * deadlocks under heavy load.
222 */
223 if (0)
224 brd_free_page(brd, sector);
225 else
226 brd_zero_page(brd, sector);
227 sector += PAGE_SIZE >> SECTOR_SHIFT;
228 n -= PAGE_SIZE;
229 }
230}
231
192/* 232/*
193 * Copy n bytes from src to the brd starting at sector. Does not sleep. 233 * Copy n bytes from src to the brd starting at sector. Does not sleep.
194 */ 234 */
@@ -300,6 +340,12 @@ static int brd_make_request(struct request_queue *q, struct bio *bio)
300 get_capacity(bdev->bd_disk)) 340 get_capacity(bdev->bd_disk))
301 goto out; 341 goto out;
302 342
343 if (unlikely(bio_rw_flagged(bio, BIO_RW_DISCARD))) {
344 err = 0;
345 discard_from_brd(brd, sector, bio->bi_size);
346 goto out;
347 }
348
303 rw = bio_rw(bio); 349 rw = bio_rw(bio);
304 if (rw == READA) 350 if (rw == READA)
305 rw = READ; 351 rw = READ;
@@ -320,7 +366,7 @@ out:
320} 366}
321 367
322#ifdef CONFIG_BLK_DEV_XIP 368#ifdef CONFIG_BLK_DEV_XIP
323static int brd_direct_access (struct block_device *bdev, sector_t sector, 369static int brd_direct_access(struct block_device *bdev, sector_t sector,
324 void **kaddr, unsigned long *pfn) 370 void **kaddr, unsigned long *pfn)
325{ 371{
326 struct brd_device *brd = bdev->bd_disk->private_data; 372 struct brd_device *brd = bdev->bd_disk->private_data;
@@ -437,6 +483,11 @@ static struct brd_device *brd_alloc(int i)
437 blk_queue_max_hw_sectors(brd->brd_queue, 1024); 483 blk_queue_max_hw_sectors(brd->brd_queue, 1024);
438 blk_queue_bounce_limit(brd->brd_queue, BLK_BOUNCE_ANY); 484 blk_queue_bounce_limit(brd->brd_queue, BLK_BOUNCE_ANY);
439 485
486 brd->brd_queue->limits.discard_granularity = PAGE_SIZE;
487 brd->brd_queue->limits.max_discard_sectors = UINT_MAX;
488 brd->brd_queue->limits.discard_zeroes_data = 1;
489 queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, brd->brd_queue);
490
440 disk = brd->brd_disk = alloc_disk(1 << part_shift); 491 disk = brd->brd_disk = alloc_disk(1 << part_shift);
441 if (!disk) 492 if (!disk)
442 goto out_free_queue; 493 goto out_free_queue;
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index e1d0e2cfec72..3381505c8a6c 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -188,11 +188,11 @@ scsi_cmd_free(ctlr_info_t *h, CommandList_struct *cmd)
188 188
189 sa = h->scsi_ctlr; 189 sa = h->scsi_ctlr;
190 stk = &sa->cmd_stack; 190 stk = &sa->cmd_stack;
191 stk->top++;
191 if (stk->top >= CMD_STACK_SIZE) { 192 if (stk->top >= CMD_STACK_SIZE) {
192 printk("cciss: scsi_cmd_free called too many times.\n"); 193 printk("cciss: scsi_cmd_free called too many times.\n");
193 BUG(); 194 BUG();
194 } 195 }
195 stk->top++;
196 stk->elem[stk->top] = (struct cciss_scsi_cmd_stack_elem_t *) cmd; 196 stk->elem[stk->top] = (struct cciss_scsi_cmd_stack_elem_t *) cmd;
197} 197}
198 198
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index e9654c8d5b62..485ed8c7d623 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -943,8 +943,7 @@ struct drbd_conf {
943 struct drbd_work resync_work, 943 struct drbd_work resync_work,
944 unplug_work, 944 unplug_work,
945 md_sync_work, 945 md_sync_work,
946 delay_probe_work, 946 delay_probe_work;
947 uuid_work;
948 struct timer_list resync_timer; 947 struct timer_list resync_timer;
949 struct timer_list md_sync_timer; 948 struct timer_list md_sync_timer;
950 struct timer_list delay_probe_timer; 949 struct timer_list delay_probe_timer;
@@ -1069,7 +1068,6 @@ struct drbd_conf {
1069 struct timeval dps_time; /* delay-probes-start-time */ 1068 struct timeval dps_time; /* delay-probes-start-time */
1070 unsigned int dp_volume_last; /* send_cnt of last delay probe */ 1069 unsigned int dp_volume_last; /* send_cnt of last delay probe */
1071 int c_sync_rate; /* current resync rate after delay_probe magic */ 1070 int c_sync_rate; /* current resync rate after delay_probe magic */
1072 atomic_t new_c_uuid;
1073}; 1071};
1074 1072
1075static inline struct drbd_conf *minor_to_mdev(unsigned int minor) 1073static 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);
1476extern int w_ov_finished(struct drbd_conf *, struct drbd_work *, int); 1474extern int w_ov_finished(struct drbd_conf *, struct drbd_work *, int);
1477extern int w_resync_inactive(struct drbd_conf *, struct drbd_work *, int); 1475extern int w_resync_inactive(struct drbd_conf *, struct drbd_work *, int);
1478extern int w_resume_next_sg(struct drbd_conf *, struct drbd_work *, int); 1476extern int w_resume_next_sg(struct drbd_conf *, struct drbd_work *, int);
1479extern int w_io_error(struct drbd_conf *, struct drbd_work *, int);
1480extern int w_send_write_hint(struct drbd_conf *, struct drbd_work *, int); 1477extern int w_send_write_hint(struct drbd_conf *, struct drbd_work *, int);
1481extern int w_make_resync_request(struct drbd_conf *, struct drbd_work *, int); 1478extern int w_make_resync_request(struct drbd_conf *, struct drbd_work *, int);
1482extern int w_send_dblock(struct drbd_conf *, struct drbd_work *, int); 1479extern int w_send_dblock(struct drbd_conf *, struct drbd_work *, int);
@@ -1542,7 +1539,7 @@ static inline void drbd_tcp_nodelay(struct socket *sock)
1542 1539
1543static inline void drbd_tcp_quickack(struct socket *sock) 1540static inline void drbd_tcp_quickack(struct socket *sock)
1544{ 1541{
1545 int __user val = 1; 1542 int __user val = 2;
1546 (void) drbd_setsockopt(sock, SOL_TCP, TCP_QUICKACK, 1543 (void) drbd_setsockopt(sock, SOL_TCP, TCP_QUICKACK,
1547 (char __user *)&val, sizeof(val)); 1544 (char __user *)&val, sizeof(val));
1548} 1545}
@@ -1728,7 +1725,7 @@ static inline void __drbd_chk_io_error_(struct drbd_conf *mdev, int forcedetach,
1728 switch (mdev->ldev->dc.on_io_error) { 1725 switch (mdev->ldev->dc.on_io_error) {
1729 case EP_PASS_ON: 1726 case EP_PASS_ON:
1730 if (!forcedetach) { 1727 if (!forcedetach) {
1731 if (printk_ratelimit()) 1728 if (__ratelimit(&drbd_ratelimit_state))
1732 dev_err(DEV, "Local IO failed in %s." 1729 dev_err(DEV, "Local IO failed in %s."
1733 "Passing error on...\n", where); 1730 "Passing error on...\n", where);
1734 break; 1731 break;
@@ -2219,8 +2216,6 @@ static inline int __inc_ap_bio_cond(struct drbd_conf *mdev)
2219 return 0; 2216 return 0;
2220 if (test_bit(BITMAP_IO, &mdev->flags)) 2217 if (test_bit(BITMAP_IO, &mdev->flags))
2221 return 0; 2218 return 0;
2222 if (atomic_read(&mdev->new_c_uuid))
2223 return 0;
2224 return 1; 2219 return 1;
2225} 2220}
2226 2221
@@ -2241,9 +2236,6 @@ static inline void inc_ap_bio(struct drbd_conf *mdev, int count)
2241 * to avoid races with the reconnect code, 2236 * to avoid races with the reconnect code,
2242 * we need to atomic_inc within the spinlock. */ 2237 * we need to atomic_inc within the spinlock. */
2243 2238
2244 if (atomic_read(&mdev->new_c_uuid) && atomic_add_unless(&mdev->new_c_uuid, -1, 1))
2245 drbd_queue_work_front(&mdev->data.work, &mdev->uuid_work);
2246
2247 spin_lock_irq(&mdev->req_lock); 2239 spin_lock_irq(&mdev->req_lock);
2248 while (!__inc_ap_bio_cond(mdev)) { 2240 while (!__inc_ap_bio_cond(mdev)) {
2249 prepare_to_wait(&mdev->misc_wait, &wait, TASK_UNINTERRUPTIBLE); 2241 prepare_to_wait(&mdev->misc_wait, &wait, TASK_UNINTERRUPTIBLE);
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index be2d2da9cdba..6b077f93acc6 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -1215,18 +1215,17 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
1215 ns.pdsk == D_OUTDATED)) { 1215 ns.pdsk == D_OUTDATED)) {
1216 if (get_ldev(mdev)) { 1216 if (get_ldev(mdev)) {
1217 if ((ns.role == R_PRIMARY || ns.peer == R_PRIMARY) && 1217 if ((ns.role == R_PRIMARY || ns.peer == R_PRIMARY) &&
1218 mdev->ldev->md.uuid[UI_BITMAP] == 0 && ns.disk >= D_UP_TO_DATE && 1218 mdev->ldev->md.uuid[UI_BITMAP] == 0 && ns.disk >= D_UP_TO_DATE) {
1219 !atomic_read(&mdev->new_c_uuid)) 1219 drbd_uuid_new_current(mdev);
1220 atomic_set(&mdev->new_c_uuid, 2); 1220 drbd_send_uuids(mdev);
1221 }
1221 put_ldev(mdev); 1222 put_ldev(mdev);
1222 } 1223 }
1223 } 1224 }
1224 1225
1225 if (ns.pdsk < D_INCONSISTENT && get_ldev(mdev)) { 1226 if (ns.pdsk < D_INCONSISTENT && get_ldev(mdev)) {
1226 /* Diskless peer becomes primary or got connected do diskless, primary peer. */ 1227 if (ns.peer == R_PRIMARY && mdev->ldev->md.uuid[UI_BITMAP] == 0)
1227 if (ns.peer == R_PRIMARY && mdev->ldev->md.uuid[UI_BITMAP] == 0 && 1228 drbd_uuid_new_current(mdev);
1228 !atomic_read(&mdev->new_c_uuid))
1229 atomic_set(&mdev->new_c_uuid, 2);
1230 1229
1231 /* D_DISKLESS Peer becomes secondary */ 1230 /* D_DISKLESS Peer becomes secondary */
1232 if (os.peer == R_PRIMARY && ns.peer == R_SECONDARY) 1231 if (os.peer == R_PRIMARY && ns.peer == R_SECONDARY)
@@ -1350,24 +1349,6 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
1350 drbd_md_sync(mdev); 1349 drbd_md_sync(mdev);
1351} 1350}
1352 1351
1353static int w_new_current_uuid(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
1354{
1355 if (get_ldev(mdev)) {
1356 if (mdev->ldev->md.uuid[UI_BITMAP] == 0) {
1357 drbd_uuid_new_current(mdev);
1358 if (get_net_conf(mdev)) {
1359 drbd_send_uuids(mdev);
1360 put_net_conf(mdev);
1361 }
1362 drbd_md_sync(mdev);
1363 }
1364 put_ldev(mdev);
1365 }
1366 atomic_dec(&mdev->new_c_uuid);
1367 wake_up(&mdev->misc_wait);
1368
1369 return 1;
1370}
1371 1352
1372static int drbd_thread_setup(void *arg) 1353static int drbd_thread_setup(void *arg)
1373{ 1354{
@@ -2291,9 +2272,9 @@ static int we_should_drop_the_connection(struct drbd_conf *mdev, struct socket *
2291 * with page_count == 0 or PageSlab. 2272 * with page_count == 0 or PageSlab.
2292 */ 2273 */
2293static int _drbd_no_send_page(struct drbd_conf *mdev, struct page *page, 2274static int _drbd_no_send_page(struct drbd_conf *mdev, struct page *page,
2294 int offset, size_t size) 2275 int offset, size_t size, unsigned msg_flags)
2295{ 2276{
2296 int sent = drbd_send(mdev, mdev->data.socket, kmap(page) + offset, size, 0); 2277 int sent = drbd_send(mdev, mdev->data.socket, kmap(page) + offset, size, msg_flags);
2297 kunmap(page); 2278 kunmap(page);
2298 if (sent == size) 2279 if (sent == size)
2299 mdev->send_cnt += size>>9; 2280 mdev->send_cnt += size>>9;
@@ -2301,7 +2282,7 @@ static int _drbd_no_send_page(struct drbd_conf *mdev, struct page *page,
2301} 2282}
2302 2283
2303static int _drbd_send_page(struct drbd_conf *mdev, struct page *page, 2284static int _drbd_send_page(struct drbd_conf *mdev, struct page *page,
2304 int offset, size_t size) 2285 int offset, size_t size, unsigned msg_flags)
2305{ 2286{
2306 mm_segment_t oldfs = get_fs(); 2287 mm_segment_t oldfs = get_fs();
2307 int sent, ok; 2288 int sent, ok;
@@ -2314,14 +2295,15 @@ static int _drbd_send_page(struct drbd_conf *mdev, struct page *page,
2314 * __page_cache_release a page that would actually still be referenced 2295 * __page_cache_release a page that would actually still be referenced
2315 * by someone, leading to some obscure delayed Oops somewhere else. */ 2296 * by someone, leading to some obscure delayed Oops somewhere else. */
2316 if (disable_sendpage || (page_count(page) < 1) || PageSlab(page)) 2297 if (disable_sendpage || (page_count(page) < 1) || PageSlab(page))
2317 return _drbd_no_send_page(mdev, page, offset, size); 2298 return _drbd_no_send_page(mdev, page, offset, size, msg_flags);
2318 2299
2300 msg_flags |= MSG_NOSIGNAL;
2319 drbd_update_congested(mdev); 2301 drbd_update_congested(mdev);
2320 set_fs(KERNEL_DS); 2302 set_fs(KERNEL_DS);
2321 do { 2303 do {
2322 sent = mdev->data.socket->ops->sendpage(mdev->data.socket, page, 2304 sent = mdev->data.socket->ops->sendpage(mdev->data.socket, page,
2323 offset, len, 2305 offset, len,
2324 MSG_NOSIGNAL); 2306 msg_flags);
2325 if (sent == -EAGAIN) { 2307 if (sent == -EAGAIN) {
2326 if (we_should_drop_the_connection(mdev, 2308 if (we_should_drop_the_connection(mdev,
2327 mdev->data.socket)) 2309 mdev->data.socket))
@@ -2350,9 +2332,11 @@ static int _drbd_send_bio(struct drbd_conf *mdev, struct bio *bio)
2350{ 2332{
2351 struct bio_vec *bvec; 2333 struct bio_vec *bvec;
2352 int i; 2334 int i;
2335 /* hint all but last page with MSG_MORE */
2353 __bio_for_each_segment(bvec, bio, i, 0) { 2336 __bio_for_each_segment(bvec, bio, i, 0) {
2354 if (!_drbd_no_send_page(mdev, bvec->bv_page, 2337 if (!_drbd_no_send_page(mdev, bvec->bv_page,
2355 bvec->bv_offset, bvec->bv_len)) 2338 bvec->bv_offset, bvec->bv_len,
2339 i == bio->bi_vcnt -1 ? 0 : MSG_MORE))
2356 return 0; 2340 return 0;
2357 } 2341 }
2358 return 1; 2342 return 1;
@@ -2362,12 +2346,13 @@ static int _drbd_send_zc_bio(struct drbd_conf *mdev, struct bio *bio)
2362{ 2346{
2363 struct bio_vec *bvec; 2347 struct bio_vec *bvec;
2364 int i; 2348 int i;
2349 /* hint all but last page with MSG_MORE */
2365 __bio_for_each_segment(bvec, bio, i, 0) { 2350 __bio_for_each_segment(bvec, bio, i, 0) {
2366 if (!_drbd_send_page(mdev, bvec->bv_page, 2351 if (!_drbd_send_page(mdev, bvec->bv_page,
2367 bvec->bv_offset, bvec->bv_len)) 2352 bvec->bv_offset, bvec->bv_len,
2353 i == bio->bi_vcnt -1 ? 0 : MSG_MORE))
2368 return 0; 2354 return 0;
2369 } 2355 }
2370
2371 return 1; 2356 return 1;
2372} 2357}
2373 2358
@@ -2375,9 +2360,11 @@ static int _drbd_send_zc_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e)
2375{ 2360{
2376 struct page *page = e->pages; 2361 struct page *page = e->pages;
2377 unsigned len = e->size; 2362 unsigned len = e->size;
2363 /* hint all but last page with MSG_MORE */
2378 page_chain_for_each(page) { 2364 page_chain_for_each(page) {
2379 unsigned l = min_t(unsigned, len, PAGE_SIZE); 2365 unsigned l = min_t(unsigned, len, PAGE_SIZE);
2380 if (!_drbd_send_page(mdev, page, 0, l)) 2366 if (!_drbd_send_page(mdev, page, 0, l,
2367 page_chain_next(page) ? MSG_MORE : 0))
2381 return 0; 2368 return 0;
2382 len -= l; 2369 len -= l;
2383 } 2370 }
@@ -2457,11 +2444,11 @@ int drbd_send_dblock(struct drbd_conf *mdev, struct drbd_request *req)
2457 p.dp_flags = cpu_to_be32(dp_flags); 2444 p.dp_flags = cpu_to_be32(dp_flags);
2458 set_bit(UNPLUG_REMOTE, &mdev->flags); 2445 set_bit(UNPLUG_REMOTE, &mdev->flags);
2459 ok = (sizeof(p) == 2446 ok = (sizeof(p) ==
2460 drbd_send(mdev, mdev->data.socket, &p, sizeof(p), MSG_MORE)); 2447 drbd_send(mdev, mdev->data.socket, &p, sizeof(p), dgs ? MSG_MORE : 0));
2461 if (ok && dgs) { 2448 if (ok && dgs) {
2462 dgb = mdev->int_dig_out; 2449 dgb = mdev->int_dig_out;
2463 drbd_csum_bio(mdev, mdev->integrity_w_tfm, req->master_bio, dgb); 2450 drbd_csum_bio(mdev, mdev->integrity_w_tfm, req->master_bio, dgb);
2464 ok = drbd_send(mdev, mdev->data.socket, dgb, dgs, MSG_MORE); 2451 ok = drbd_send(mdev, mdev->data.socket, dgb, dgs, 0);
2465 } 2452 }
2466 if (ok) { 2453 if (ok) {
2467 if (mdev->net_conf->wire_protocol == DRBD_PROT_A) 2454 if (mdev->net_conf->wire_protocol == DRBD_PROT_A)
@@ -2510,11 +2497,11 @@ int drbd_send_block(struct drbd_conf *mdev, enum drbd_packets cmd,
2510 return 0; 2497 return 0;
2511 2498
2512 ok = sizeof(p) == drbd_send(mdev, mdev->data.socket, &p, 2499 ok = sizeof(p) == drbd_send(mdev, mdev->data.socket, &p,
2513 sizeof(p), MSG_MORE); 2500 sizeof(p), dgs ? MSG_MORE : 0);
2514 if (ok && dgs) { 2501 if (ok && dgs) {
2515 dgb = mdev->int_dig_out; 2502 dgb = mdev->int_dig_out;
2516 drbd_csum_ee(mdev, mdev->integrity_w_tfm, e, dgb); 2503 drbd_csum_ee(mdev, mdev->integrity_w_tfm, e, dgb);
2517 ok = drbd_send(mdev, mdev->data.socket, dgb, dgs, MSG_MORE); 2504 ok = drbd_send(mdev, mdev->data.socket, dgb, dgs, 0);
2518 } 2505 }
2519 if (ok) 2506 if (ok)
2520 ok = _drbd_send_zc_ee(mdev, e); 2507 ok = _drbd_send_zc_ee(mdev, e);
@@ -2708,7 +2695,6 @@ void drbd_init_set_defaults(struct drbd_conf *mdev)
2708 atomic_set(&mdev->net_cnt, 0); 2695 atomic_set(&mdev->net_cnt, 0);
2709 atomic_set(&mdev->packet_seq, 0); 2696 atomic_set(&mdev->packet_seq, 0);
2710 atomic_set(&mdev->pp_in_use, 0); 2697 atomic_set(&mdev->pp_in_use, 0);
2711 atomic_set(&mdev->new_c_uuid, 0);
2712 2698
2713 mutex_init(&mdev->md_io_mutex); 2699 mutex_init(&mdev->md_io_mutex);
2714 mutex_init(&mdev->data.mutex); 2700 mutex_init(&mdev->data.mutex);
@@ -2739,14 +2725,12 @@ void drbd_init_set_defaults(struct drbd_conf *mdev)
2739 INIT_LIST_HEAD(&mdev->bm_io_work.w.list); 2725 INIT_LIST_HEAD(&mdev->bm_io_work.w.list);
2740 INIT_LIST_HEAD(&mdev->delay_probes); 2726 INIT_LIST_HEAD(&mdev->delay_probes);
2741 INIT_LIST_HEAD(&mdev->delay_probe_work.list); 2727 INIT_LIST_HEAD(&mdev->delay_probe_work.list);
2742 INIT_LIST_HEAD(&mdev->uuid_work.list);
2743 2728
2744 mdev->resync_work.cb = w_resync_inactive; 2729 mdev->resync_work.cb = w_resync_inactive;
2745 mdev->unplug_work.cb = w_send_write_hint; 2730 mdev->unplug_work.cb = w_send_write_hint;
2746 mdev->md_sync_work.cb = w_md_sync; 2731 mdev->md_sync_work.cb = w_md_sync;
2747 mdev->bm_io_work.w.cb = w_bitmap_io; 2732 mdev->bm_io_work.w.cb = w_bitmap_io;
2748 mdev->delay_probe_work.cb = w_delay_probes; 2733 mdev->delay_probe_work.cb = w_delay_probes;
2749 mdev->uuid_work.cb = w_new_current_uuid;
2750 init_timer(&mdev->resync_timer); 2734 init_timer(&mdev->resync_timer);
2751 init_timer(&mdev->md_sync_timer); 2735 init_timer(&mdev->md_sync_timer);
2752 init_timer(&mdev->delay_probe_timer); 2736 init_timer(&mdev->delay_probe_timer);
@@ -3799,7 +3783,7 @@ _drbd_insert_fault(struct drbd_conf *mdev, unsigned int type)
3799 if (ret) { 3783 if (ret) {
3800 fault_count++; 3784 fault_count++;
3801 3785
3802 if (printk_ratelimit()) 3786 if (__ratelimit(&drbd_ratelimit_state))
3803 dev_warn(DEV, "***Simulating %s failure\n", 3787 dev_warn(DEV, "***Simulating %s failure\n",
3804 _drbd_fault_str(type)); 3788 _drbd_fault_str(type));
3805 } 3789 }
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index bc9ab7fb2cc7..dff48701b84d 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -42,7 +42,6 @@
42#include <linux/unistd.h> 42#include <linux/unistd.h>
43#include <linux/vmalloc.h> 43#include <linux/vmalloc.h>
44#include <linux/random.h> 44#include <linux/random.h>
45#include <linux/mm.h>
46#include <linux/string.h> 45#include <linux/string.h>
47#include <linux/scatterlist.h> 46#include <linux/scatterlist.h>
48#include "drbd_int.h" 47#include "drbd_int.h"
@@ -571,6 +570,25 @@ static int drbd_recv(struct drbd_conf *mdev, void *buf, size_t size)
571 return rv; 570 return rv;
572} 571}
573 572
573/* quoting tcp(7):
574 * On individual connections, the socket buffer size must be set prior to the
575 * listen(2) or connect(2) calls in order to have it take effect.
576 * This is our wrapper to do so.
577 */
578static void drbd_setbufsize(struct socket *sock, unsigned int snd,
579 unsigned int rcv)
580{
581 /* open coded SO_SNDBUF, SO_RCVBUF */
582 if (snd) {
583 sock->sk->sk_sndbuf = snd;
584 sock->sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
585 }
586 if (rcv) {
587 sock->sk->sk_rcvbuf = rcv;
588 sock->sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
589 }
590}
591
574static struct socket *drbd_try_connect(struct drbd_conf *mdev) 592static struct socket *drbd_try_connect(struct drbd_conf *mdev)
575{ 593{
576 const char *what; 594 const char *what;
@@ -592,6 +610,8 @@ static struct socket *drbd_try_connect(struct drbd_conf *mdev)
592 610
593 sock->sk->sk_rcvtimeo = 611 sock->sk->sk_rcvtimeo =
594 sock->sk->sk_sndtimeo = mdev->net_conf->try_connect_int*HZ; 612 sock->sk->sk_sndtimeo = mdev->net_conf->try_connect_int*HZ;
613 drbd_setbufsize(sock, mdev->net_conf->sndbuf_size,
614 mdev->net_conf->rcvbuf_size);
595 615
596 /* explicitly bind to the configured IP as source IP 616 /* explicitly bind to the configured IP as source IP
597 * for the outgoing connections. 617 * for the outgoing connections.
@@ -670,6 +690,8 @@ static struct socket *drbd_wait_for_connect(struct drbd_conf *mdev)
670 s_listen->sk->sk_reuse = 1; /* SO_REUSEADDR */ 690 s_listen->sk->sk_reuse = 1; /* SO_REUSEADDR */
671 s_listen->sk->sk_rcvtimeo = timeo; 691 s_listen->sk->sk_rcvtimeo = timeo;
672 s_listen->sk->sk_sndtimeo = timeo; 692 s_listen->sk->sk_sndtimeo = timeo;
693 drbd_setbufsize(s_listen, mdev->net_conf->sndbuf_size,
694 mdev->net_conf->rcvbuf_size);
673 695
674 what = "bind before listen"; 696 what = "bind before listen";
675 err = s_listen->ops->bind(s_listen, 697 err = s_listen->ops->bind(s_listen,
@@ -856,16 +878,6 @@ retry:
856 sock->sk->sk_priority = TC_PRIO_INTERACTIVE_BULK; 878 sock->sk->sk_priority = TC_PRIO_INTERACTIVE_BULK;
857 msock->sk->sk_priority = TC_PRIO_INTERACTIVE; 879 msock->sk->sk_priority = TC_PRIO_INTERACTIVE;
858 880
859 if (mdev->net_conf->sndbuf_size) {
860 sock->sk->sk_sndbuf = mdev->net_conf->sndbuf_size;
861 sock->sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
862 }
863
864 if (mdev->net_conf->rcvbuf_size) {
865 sock->sk->sk_rcvbuf = mdev->net_conf->rcvbuf_size;
866 sock->sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
867 }
868
869 /* NOT YET ... 881 /* NOT YET ...
870 * sock->sk->sk_sndtimeo = mdev->net_conf->timeout*HZ/10; 882 * sock->sk->sk_sndtimeo = mdev->net_conf->timeout*HZ/10;
871 * sock->sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT; 883 * sock->sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT;
@@ -1154,17 +1166,6 @@ int drbd_submit_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e,
1154 unsigned n_bios = 0; 1166 unsigned n_bios = 0;
1155 unsigned nr_pages = (ds + PAGE_SIZE -1) >> PAGE_SHIFT; 1167 unsigned nr_pages = (ds + PAGE_SIZE -1) >> PAGE_SHIFT;
1156 1168
1157 if (atomic_read(&mdev->new_c_uuid)) {
1158 if (atomic_add_unless(&mdev->new_c_uuid, -1, 1)) {
1159 drbd_uuid_new_current(mdev);
1160 drbd_md_sync(mdev);
1161
1162 atomic_dec(&mdev->new_c_uuid);
1163 wake_up(&mdev->misc_wait);
1164 }
1165 wait_event(mdev->misc_wait, !atomic_read(&mdev->new_c_uuid));
1166 }
1167
1168 /* In most cases, we will only need one bio. But in case the lower 1169 /* In most cases, we will only need one bio. But in case the lower
1169 * level restrictions happen to be different at this offset on this 1170 * level restrictions happen to be different at this offset on this
1170 * side than those of the sending peer, we may need to submit the 1171 * side than those of the sending peer, we may need to submit the
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index 3397f11d0ba9..654f1ef5cbb0 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -102,32 +102,7 @@ static void _req_is_done(struct drbd_conf *mdev, struct drbd_request *req, const
102 } 102 }
103 } 103 }
104 104
105 /* if it was a local io error, we want to notify our 105 drbd_req_free(req);
106 * peer about that, and see if we need to
107 * detach the disk and stuff.
108 * to avoid allocating some special work
109 * struct, reuse the request. */
110
111 /* THINK
112 * why do we do this not when we detect the error,
113 * but delay it until it is "done", i.e. possibly
114 * until the next barrier ack? */
115
116 if (rw == WRITE &&
117 ((s & RQ_LOCAL_MASK) && !(s & RQ_LOCAL_OK))) {
118 if (!(req->w.list.next == LIST_POISON1 ||
119 list_empty(&req->w.list))) {
120 /* DEBUG ASSERT only; if this triggers, we
121 * probably corrupt the worker list here */
122 dev_err(DEV, "req->w.list.next = %p\n", req->w.list.next);
123 dev_err(DEV, "req->w.list.prev = %p\n", req->w.list.prev);
124 }
125 req->w.cb = w_io_error;
126 drbd_queue_work(&mdev->data.work, &req->w);
127 /* drbd_req_free() is done in w_io_error */
128 } else {
129 drbd_req_free(req);
130 }
131} 106}
132 107
133static void queue_barrier(struct drbd_conf *mdev) 108static void queue_barrier(struct drbd_conf *mdev)
@@ -453,9 +428,6 @@ void __req_mod(struct drbd_request *req, enum drbd_req_event what,
453 req->rq_state |= RQ_LOCAL_COMPLETED; 428 req->rq_state |= RQ_LOCAL_COMPLETED;
454 req->rq_state &= ~RQ_LOCAL_PENDING; 429 req->rq_state &= ~RQ_LOCAL_PENDING;
455 430
456 dev_alert(DEV, "Local WRITE failed sec=%llus size=%u\n",
457 (unsigned long long)req->sector, req->size);
458 /* and now: check how to handle local io error. */
459 __drbd_chk_io_error(mdev, FALSE); 431 __drbd_chk_io_error(mdev, FALSE);
460 _req_may_be_done(req, m); 432 _req_may_be_done(req, m);
461 put_ldev(mdev); 433 put_ldev(mdev);
@@ -475,22 +447,21 @@ void __req_mod(struct drbd_request *req, enum drbd_req_event what,
475 req->rq_state |= RQ_LOCAL_COMPLETED; 447 req->rq_state |= RQ_LOCAL_COMPLETED;
476 req->rq_state &= ~RQ_LOCAL_PENDING; 448 req->rq_state &= ~RQ_LOCAL_PENDING;
477 449
478 dev_alert(DEV, "Local READ failed sec=%llus size=%u\n",
479 (unsigned long long)req->sector, req->size);
480 /* _req_mod(req,to_be_send); oops, recursion... */
481 D_ASSERT(!(req->rq_state & RQ_NET_MASK)); 450 D_ASSERT(!(req->rq_state & RQ_NET_MASK));
482 req->rq_state |= RQ_NET_PENDING;
483 inc_ap_pending(mdev);
484 451
485 __drbd_chk_io_error(mdev, FALSE); 452 __drbd_chk_io_error(mdev, FALSE);
486 put_ldev(mdev); 453 put_ldev(mdev);
487 /* NOTE: if we have no connection,
488 * or know the peer has no good data either,
489 * then we don't actually need to "queue_for_net_read",
490 * but we do so anyways, since the drbd_io_error()
491 * and the potential state change to "Diskless"
492 * needs to be done from process context */
493 454
455 /* no point in retrying if there is no good remote data,
456 * or we have no connection. */
457 if (mdev->state.pdsk != D_UP_TO_DATE) {
458 _req_may_be_done(req, m);
459 break;
460 }
461
462 /* _req_mod(req,to_be_send); oops, recursion... */
463 req->rq_state |= RQ_NET_PENDING;
464 inc_ap_pending(mdev);
494 /* fall through: _req_mod(req,queue_for_net_read); */ 465 /* fall through: _req_mod(req,queue_for_net_read); */
495 466
496 case queue_for_net_read: 467 case queue_for_net_read:
@@ -600,6 +571,9 @@ void __req_mod(struct drbd_request *req, enum drbd_req_event what,
600 _req_may_be_done(req, m); 571 _req_may_be_done(req, m);
601 break; 572 break;
602 573
574 case read_retry_remote_canceled:
575 req->rq_state &= ~RQ_NET_QUEUED;
576 /* fall through, in case we raced with drbd_disconnect */
603 case connection_lost_while_pending: 577 case connection_lost_while_pending:
604 /* transfer log cleanup after connection loss */ 578 /* transfer log cleanup after connection loss */
605 /* assert something? */ 579 /* assert something? */
diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h
index 16119d7056cc..02d575d24518 100644
--- a/drivers/block/drbd/drbd_req.h
+++ b/drivers/block/drbd/drbd_req.h
@@ -91,6 +91,7 @@ enum drbd_req_event {
91 send_failed, 91 send_failed,
92 handed_over_to_network, 92 handed_over_to_network,
93 connection_lost_while_pending, 93 connection_lost_while_pending,
94 read_retry_remote_canceled,
94 recv_acked_by_peer, 95 recv_acked_by_peer,
95 write_acked_by_peer, 96 write_acked_by_peer,
96 write_acked_by_peer_and_sis, /* and set_in_sync */ 97 write_acked_by_peer_and_sis, /* and set_in_sync */
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c
index 727ff6339754..b623ceee2a4a 100644
--- a/drivers/block/drbd/drbd_worker.c
+++ b/drivers/block/drbd/drbd_worker.c
@@ -224,9 +224,6 @@ void drbd_endio_pri(struct bio *bio, int error)
224 enum drbd_req_event what; 224 enum drbd_req_event what;
225 int uptodate = bio_flagged(bio, BIO_UPTODATE); 225 int uptodate = bio_flagged(bio, BIO_UPTODATE);
226 226
227 if (error)
228 dev_warn(DEV, "p %s: error=%d\n",
229 bio_data_dir(bio) == WRITE ? "write" : "read", error);
230 if (!error && !uptodate) { 227 if (!error && !uptodate) {
231 dev_warn(DEV, "p %s: setting error to -EIO\n", 228 dev_warn(DEV, "p %s: setting error to -EIO\n",
232 bio_data_dir(bio) == WRITE ? "write" : "read"); 229 bio_data_dir(bio) == WRITE ? "write" : "read");
@@ -257,20 +254,6 @@ void drbd_endio_pri(struct bio *bio, int error)
257 complete_master_bio(mdev, &m); 254 complete_master_bio(mdev, &m);
258} 255}
259 256
260int w_io_error(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
261{
262 struct drbd_request *req = container_of(w, struct drbd_request, w);
263
264 /* NOTE: mdev->ldev can be NULL by the time we get here! */
265 /* D_ASSERT(mdev->ldev->dc.on_io_error != EP_PASS_ON); */
266
267 /* the only way this callback is scheduled is from _req_may_be_done,
268 * when it is done and had a local write error, see comments there */
269 drbd_req_free(req);
270
271 return TRUE;
272}
273
274int w_read_retry_remote(struct drbd_conf *mdev, struct drbd_work *w, int cancel) 257int w_read_retry_remote(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
275{ 258{
276 struct drbd_request *req = container_of(w, struct drbd_request, w); 259 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)
280 * to give the disk the chance to relocate that block */ 263 * to give the disk the chance to relocate that block */
281 264
282 spin_lock_irq(&mdev->req_lock); 265 spin_lock_irq(&mdev->req_lock);
283 if (cancel || 266 if (cancel || mdev->state.pdsk != D_UP_TO_DATE) {
284 mdev->state.conn < C_CONNECTED || 267 _req_mod(req, read_retry_remote_canceled);
285 mdev->state.pdsk <= D_INCONSISTENT) {
286 _req_mod(req, send_canceled);
287 spin_unlock_irq(&mdev->req_lock); 268 spin_unlock_irq(&mdev->req_lock);
288 dev_alert(DEV, "WE ARE LOST. Local IO failure, no peer.\n");
289 return 1; 269 return 1;
290 } 270 }
291 spin_unlock_irq(&mdev->req_lock); 271 spin_unlock_irq(&mdev->req_lock);
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c
index 52f2d11bc7b9..ed6fb91123ab 100644
--- a/drivers/block/swim3.c
+++ b/drivers/block/swim3.c
@@ -1159,8 +1159,10 @@ static struct of_device_id swim3_match[] =
1159 1159
1160static struct macio_driver swim3_driver = 1160static struct macio_driver swim3_driver =
1161{ 1161{
1162 .name = "swim3", 1162 .driver = {
1163 .match_table = swim3_match, 1163 .name = "swim3",
1164 .of_match_table = swim3_match,
1165 },
1164 .probe = swim3_attach, 1166 .probe = swim3_attach,
1165#if 0 1167#if 0
1166 .suspend = swim3_suspend, 1168 .suspend = swim3_suspend,
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 83fa09a836ca..258bc2ae2885 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -298,7 +298,9 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
298 err = virtio_config_val(vdev, VIRTIO_BLK_F_SEG_MAX, 298 err = virtio_config_val(vdev, VIRTIO_BLK_F_SEG_MAX,
299 offsetof(struct virtio_blk_config, seg_max), 299 offsetof(struct virtio_blk_config, seg_max),
300 &sg_elems); 300 &sg_elems);
301 if (err) 301
302 /* We need at least one SG element, whatever they say. */
303 if (err || !sg_elems)
302 sg_elems = 1; 304 sg_elems = 1;
303 305
304 /* We need an extra sg elements at head and tail. */ 306 /* We need an extra sg elements at head and tail. */
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index e21175be25d0..7cfcc629a7fd 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -1121,5 +1121,13 @@ config DEVPORT
1121 1121
1122source "drivers/s390/char/Kconfig" 1122source "drivers/s390/char/Kconfig"
1123 1123
1124config RAMOOPS
1125 tristate "Log panic/oops to a RAM buffer"
1126 depends on HAS_IOMEM
1127 default n
1128 help
1129 This enables panic and oops messages to be logged to a circular
1130 buffer in RAM where it can be read back at some later point.
1131
1124endmenu 1132endmenu
1125 1133
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index d39be4cf1f5d..88d6eac69754 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -108,6 +108,7 @@ obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o
108obj-$(CONFIG_TCG_TPM) += tpm/ 108obj-$(CONFIG_TCG_TPM) += tpm/
109 109
110obj-$(CONFIG_PS3_FLASH) += ps3flash.o 110obj-$(CONFIG_PS3_FLASH) += ps3flash.o
111obj-$(CONFIG_RAMOOPS) += ramoops.o
111 112
112obj-$(CONFIG_JS_RTC) += js-rtc.o 113obj-$(CONFIG_JS_RTC) += js-rtc.o
113js-rtc-y = rtc.o 114js-rtc-y = rtc.o
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 67ea3a60de74..70312da4c968 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -384,7 +384,7 @@ static int __devinit uli_agp_init(struct pci_dev *pdev)
384{ 384{
385 u32 httfea,baseaddr,enuscr; 385 u32 httfea,baseaddr,enuscr;
386 struct pci_dev *dev1; 386 struct pci_dev *dev1;
387 int i; 387 int i, ret;
388 unsigned size = amd64_fetch_size(); 388 unsigned size = amd64_fetch_size();
389 389
390 dev_info(&pdev->dev, "setting up ULi AGP\n"); 390 dev_info(&pdev->dev, "setting up ULi AGP\n");
@@ -400,15 +400,18 @@ static int __devinit uli_agp_init(struct pci_dev *pdev)
400 400
401 if (i == ARRAY_SIZE(uli_sizes)) { 401 if (i == ARRAY_SIZE(uli_sizes)) {
402 dev_info(&pdev->dev, "no ULi size found for %d\n", size); 402 dev_info(&pdev->dev, "no ULi size found for %d\n", size);
403 return -ENODEV; 403 ret = -ENODEV;
404 goto put;
404 } 405 }
405 406
406 /* shadow x86-64 registers into ULi registers */ 407 /* shadow x86-64 registers into ULi registers */
407 pci_read_config_dword (k8_northbridges[0], AMD64_GARTAPERTUREBASE, &httfea); 408 pci_read_config_dword (k8_northbridges[0], AMD64_GARTAPERTUREBASE, &httfea);
408 409
409 /* if x86-64 aperture base is beyond 4G, exit here */ 410 /* if x86-64 aperture base is beyond 4G, exit here */
410 if ((httfea & 0x7fff) >> (32 - 25)) 411 if ((httfea & 0x7fff) >> (32 - 25)) {
411 return -ENODEV; 412 ret = -ENODEV;
413 goto put;
414 }
412 415
413 httfea = (httfea& 0x7fff) << 25; 416 httfea = (httfea& 0x7fff) << 25;
414 417
@@ -420,9 +423,10 @@ static int __devinit uli_agp_init(struct pci_dev *pdev)
420 enuscr= httfea+ (size * 1024 * 1024) - 1; 423 enuscr= httfea+ (size * 1024 * 1024) - 1;
421 pci_write_config_dword(dev1, ULI_X86_64_HTT_FEA_REG, httfea); 424 pci_write_config_dword(dev1, ULI_X86_64_HTT_FEA_REG, httfea);
422 pci_write_config_dword(dev1, ULI_X86_64_ENU_SCR_REG, enuscr); 425 pci_write_config_dword(dev1, ULI_X86_64_ENU_SCR_REG, enuscr);
423 426 ret = 0;
427put:
424 pci_dev_put(dev1); 428 pci_dev_put(dev1);
425 return 0; 429 return ret;
426} 430}
427 431
428 432
@@ -441,7 +445,7 @@ static int nforce3_agp_init(struct pci_dev *pdev)
441{ 445{
442 u32 tmp, apbase, apbar, aplimit; 446 u32 tmp, apbase, apbar, aplimit;
443 struct pci_dev *dev1; 447 struct pci_dev *dev1;
444 int i; 448 int i, ret;
445 unsigned size = amd64_fetch_size(); 449 unsigned size = amd64_fetch_size();
446 450
447 dev_info(&pdev->dev, "setting up Nforce3 AGP\n"); 451 dev_info(&pdev->dev, "setting up Nforce3 AGP\n");
@@ -458,7 +462,8 @@ static int nforce3_agp_init(struct pci_dev *pdev)
458 462
459 if (i == ARRAY_SIZE(nforce3_sizes)) { 463 if (i == ARRAY_SIZE(nforce3_sizes)) {
460 dev_info(&pdev->dev, "no NForce3 size found for %d\n", size); 464 dev_info(&pdev->dev, "no NForce3 size found for %d\n", size);
461 return -ENODEV; 465 ret = -ENODEV;
466 goto put;
462 } 467 }
463 468
464 pci_read_config_dword(dev1, NVIDIA_X86_64_1_APSIZE, &tmp); 469 pci_read_config_dword(dev1, NVIDIA_X86_64_1_APSIZE, &tmp);
@@ -472,7 +477,8 @@ static int nforce3_agp_init(struct pci_dev *pdev)
472 /* if x86-64 aperture base is beyond 4G, exit here */ 477 /* if x86-64 aperture base is beyond 4G, exit here */
473 if ( (apbase & 0x7fff) >> (32 - 25) ) { 478 if ( (apbase & 0x7fff) >> (32 - 25) ) {
474 dev_info(&pdev->dev, "aperture base > 4G\n"); 479 dev_info(&pdev->dev, "aperture base > 4G\n");
475 return -ENODEV; 480 ret = -ENODEV;
481 goto put;
476 } 482 }
477 483
478 apbase = (apbase & 0x7fff) << 25; 484 apbase = (apbase & 0x7fff) << 25;
@@ -488,9 +494,11 @@ static int nforce3_agp_init(struct pci_dev *pdev)
488 pci_write_config_dword(dev1, NVIDIA_X86_64_1_APBASE2, apbase); 494 pci_write_config_dword(dev1, NVIDIA_X86_64_1_APBASE2, apbase);
489 pci_write_config_dword(dev1, NVIDIA_X86_64_1_APLIMIT2, aplimit); 495 pci_write_config_dword(dev1, NVIDIA_X86_64_1_APLIMIT2, aplimit);
490 496
497 ret = 0;
498put:
491 pci_dev_put(dev1); 499 pci_dev_put(dev1);
492 500
493 return 0; 501 return ret;
494} 502}
495 503
496static int __devinit agp_amd64_probe(struct pci_dev *pdev, 504static int __devinit agp_amd64_probe(struct pci_dev *pdev,
diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c
index e8ea6825822c..9344216183a4 100644
--- a/drivers/char/agp/intel-gtt.c
+++ b/drivers/char/agp/intel-gtt.c
@@ -1059,7 +1059,7 @@ static void intel_i9xx_setup_flush(void)
1059 } 1059 }
1060} 1060}
1061 1061
1062static int intel_i915_configure(void) 1062static int intel_i9xx_configure(void)
1063{ 1063{
1064 struct aper_size_info_fixed *current_size; 1064 struct aper_size_info_fixed *current_size;
1065 u32 temp; 1065 u32 temp;
@@ -1207,6 +1207,38 @@ static int intel_i9xx_fetch_size(void)
1207 return 0; 1207 return 0;
1208} 1208}
1209 1209
1210static int intel_i915_get_gtt_size(void)
1211{
1212 int size;
1213
1214 if (IS_G33) {
1215 u16 gmch_ctrl;
1216
1217 /* G33's GTT size defined in gmch_ctrl */
1218 pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl);
1219 switch (gmch_ctrl & G33_PGETBL_SIZE_MASK) {
1220 case G33_PGETBL_SIZE_1M:
1221 size = 1024;
1222 break;
1223 case G33_PGETBL_SIZE_2M:
1224 size = 2048;
1225 break;
1226 default:
1227 dev_info(&agp_bridge->dev->dev,
1228 "unknown page table size 0x%x, assuming 512KB\n",
1229 (gmch_ctrl & G33_PGETBL_SIZE_MASK));
1230 size = 512;
1231 }
1232 } else {
1233 /* On previous hardware, the GTT size was just what was
1234 * required to map the aperture.
1235 */
1236 size = agp_bridge->driver->fetch_size();
1237 }
1238
1239 return KB(size);
1240}
1241
1210/* The intel i915 automatically initializes the agp aperture during POST. 1242/* The intel i915 automatically initializes the agp aperture during POST.
1211 * Use the memory already set aside for in the GTT. 1243 * Use the memory already set aside for in the GTT.
1212 */ 1244 */
@@ -1216,7 +1248,7 @@ static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge)
1216 struct aper_size_info_fixed *size; 1248 struct aper_size_info_fixed *size;
1217 int num_entries; 1249 int num_entries;
1218 u32 temp, temp2; 1250 u32 temp, temp2;
1219 int gtt_map_size = 256 * 1024; 1251 int gtt_map_size;
1220 1252
1221 size = agp_bridge->current_size; 1253 size = agp_bridge->current_size;
1222 page_order = size->page_order; 1254 page_order = size->page_order;
@@ -1226,8 +1258,8 @@ static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge)
1226 pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &temp); 1258 pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &temp);
1227 pci_read_config_dword(intel_private.pcidev, I915_PTEADDR, &temp2); 1259 pci_read_config_dword(intel_private.pcidev, I915_PTEADDR, &temp2);
1228 1260
1229 if (IS_G33) 1261 gtt_map_size = intel_i915_get_gtt_size();
1230 gtt_map_size = 1024 * 1024; /* 1M on G33 */ 1262
1231 intel_private.gtt = ioremap(temp2, gtt_map_size); 1263 intel_private.gtt = ioremap(temp2, gtt_map_size);
1232 if (!intel_private.gtt) 1264 if (!intel_private.gtt)
1233 return -ENOMEM; 1265 return -ENOMEM;
@@ -1422,7 +1454,7 @@ static const struct agp_bridge_driver intel_915_driver = {
1422 .size_type = FIXED_APER_SIZE, 1454 .size_type = FIXED_APER_SIZE,
1423 .num_aperture_sizes = 4, 1455 .num_aperture_sizes = 4,
1424 .needs_scratch_page = true, 1456 .needs_scratch_page = true,
1425 .configure = intel_i915_configure, 1457 .configure = intel_i9xx_configure,
1426 .fetch_size = intel_i9xx_fetch_size, 1458 .fetch_size = intel_i9xx_fetch_size,
1427 .cleanup = intel_i915_cleanup, 1459 .cleanup = intel_i915_cleanup,
1428 .mask_memory = intel_i810_mask_memory, 1460 .mask_memory = intel_i810_mask_memory,
@@ -1455,7 +1487,7 @@ static const struct agp_bridge_driver intel_i965_driver = {
1455 .size_type = FIXED_APER_SIZE, 1487 .size_type = FIXED_APER_SIZE,
1456 .num_aperture_sizes = 4, 1488 .num_aperture_sizes = 4,
1457 .needs_scratch_page = true, 1489 .needs_scratch_page = true,
1458 .configure = intel_i915_configure, 1490 .configure = intel_i9xx_configure,
1459 .fetch_size = intel_i9xx_fetch_size, 1491 .fetch_size = intel_i9xx_fetch_size,
1460 .cleanup = intel_i915_cleanup, 1492 .cleanup = intel_i915_cleanup,
1461 .mask_memory = intel_i965_mask_memory, 1493 .mask_memory = intel_i965_mask_memory,
@@ -1488,7 +1520,7 @@ static const struct agp_bridge_driver intel_g33_driver = {
1488 .size_type = FIXED_APER_SIZE, 1520 .size_type = FIXED_APER_SIZE,
1489 .num_aperture_sizes = 4, 1521 .num_aperture_sizes = 4,
1490 .needs_scratch_page = true, 1522 .needs_scratch_page = true,
1491 .configure = intel_i915_configure, 1523 .configure = intel_i9xx_configure,
1492 .fetch_size = intel_i9xx_fetch_size, 1524 .fetch_size = intel_i9xx_fetch_size,
1493 .cleanup = intel_i915_cleanup, 1525 .cleanup = intel_i915_cleanup,
1494 .mask_memory = intel_i965_mask_memory, 1526 .mask_memory = intel_i965_mask_memory,
diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c
index 95db71360d24..f845a8f718b3 100644
--- a/drivers/char/agp/uninorth-agp.c
+++ b/drivers/char/agp/uninorth-agp.c
@@ -415,7 +415,7 @@ static int uninorth_create_gatt_table(struct agp_bridge_data *bridge)
415 bridge->gatt_table_real = (u32 *) table; 415 bridge->gatt_table_real = (u32 *) table;
416 /* Need to clear out any dirty data still sitting in caches */ 416 /* Need to clear out any dirty data still sitting in caches */
417 flush_dcache_range((unsigned long)table, 417 flush_dcache_range((unsigned long)table,
418 (unsigned long)(table_end + PAGE_SIZE)); 418 (unsigned long)table_end + 1);
419 bridge->gatt_table = vmap(pages, (1 << page_order), 0, PAGE_KERNEL_NCG); 419 bridge->gatt_table = vmap(pages, (1 << page_order), 0, PAGE_KERNEL_NCG);
420 420
421 if (bridge->gatt_table == NULL) 421 if (bridge->gatt_table == NULL)
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index 56b27671adc4..4f8d60c25a98 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -84,6 +84,7 @@ static char *serial_version = "4.30";
84#include <linux/smp_lock.h> 84#include <linux/smp_lock.h>
85#include <linux/init.h> 85#include <linux/init.h>
86#include <linux/bitops.h> 86#include <linux/bitops.h>
87#include <linux/platform_device.h>
87 88
88#include <asm/setup.h> 89#include <asm/setup.h>
89 90
@@ -1954,29 +1955,16 @@ static const struct tty_operations serial_ops = {
1954/* 1955/*
1955 * The serial driver boot-time initialization code! 1956 * The serial driver boot-time initialization code!
1956 */ 1957 */
1957static int __init rs_init(void) 1958static int __init amiga_serial_probe(struct platform_device *pdev)
1958{ 1959{
1959 unsigned long flags; 1960 unsigned long flags;
1960 struct serial_state * state; 1961 struct serial_state * state;
1961 int error; 1962 int error;
1962 1963
1963 if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_SERIAL))
1964 return -ENODEV;
1965
1966 serial_driver = alloc_tty_driver(1); 1964 serial_driver = alloc_tty_driver(1);
1967 if (!serial_driver) 1965 if (!serial_driver)
1968 return -ENOMEM; 1966 return -ENOMEM;
1969 1967
1970 /*
1971 * We request SERDAT and SERPER only, because the serial registers are
1972 * too spreaded over the custom register space
1973 */
1974 if (!request_mem_region(CUSTOM_PHYSADDR+0x30, 4,
1975 "amiserial [Paula]")) {
1976 error = -EBUSY;
1977 goto fail_put_tty_driver;
1978 }
1979
1980 IRQ_ports = NULL; 1968 IRQ_ports = NULL;
1981 1969
1982 show_serial_version(); 1970 show_serial_version();
@@ -1998,7 +1986,7 @@ static int __init rs_init(void)
1998 1986
1999 error = tty_register_driver(serial_driver); 1987 error = tty_register_driver(serial_driver);
2000 if (error) 1988 if (error)
2001 goto fail_release_mem_region; 1989 goto fail_put_tty_driver;
2002 1990
2003 state = rs_table; 1991 state = rs_table;
2004 state->magic = SSTATE_MAGIC; 1992 state->magic = SSTATE_MAGIC;
@@ -2050,23 +2038,24 @@ static int __init rs_init(void)
2050 ciab.ddra |= (SER_DTR | SER_RTS); /* outputs */ 2038 ciab.ddra |= (SER_DTR | SER_RTS); /* outputs */
2051 ciab.ddra &= ~(SER_DCD | SER_CTS | SER_DSR); /* inputs */ 2039 ciab.ddra &= ~(SER_DCD | SER_CTS | SER_DSR); /* inputs */
2052 2040
2041 platform_set_drvdata(pdev, state);
2042
2053 return 0; 2043 return 0;
2054 2044
2055fail_free_irq: 2045fail_free_irq:
2056 free_irq(IRQ_AMIGA_TBE, state); 2046 free_irq(IRQ_AMIGA_TBE, state);
2057fail_unregister: 2047fail_unregister:
2058 tty_unregister_driver(serial_driver); 2048 tty_unregister_driver(serial_driver);
2059fail_release_mem_region:
2060 release_mem_region(CUSTOM_PHYSADDR+0x30, 4);
2061fail_put_tty_driver: 2049fail_put_tty_driver:
2062 put_tty_driver(serial_driver); 2050 put_tty_driver(serial_driver);
2063 return error; 2051 return error;
2064} 2052}
2065 2053
2066static __exit void rs_exit(void) 2054static int __exit amiga_serial_remove(struct platform_device *pdev)
2067{ 2055{
2068 int error; 2056 int error;
2069 struct async_struct *info = rs_table[0].info; 2057 struct serial_state *state = platform_get_drvdata(pdev);
2058 struct async_struct *info = state->info;
2070 2059
2071 /* printk("Unloading %s: version %s\n", serial_name, serial_version); */ 2060 /* printk("Unloading %s: version %s\n", serial_name, serial_version); */
2072 tasklet_kill(&info->tlet); 2061 tasklet_kill(&info->tlet);
@@ -2075,19 +2064,38 @@ static __exit void rs_exit(void)
2075 error); 2064 error);
2076 put_tty_driver(serial_driver); 2065 put_tty_driver(serial_driver);
2077 2066
2078 if (info) { 2067 rs_table[0].info = NULL;
2079 rs_table[0].info = NULL; 2068 kfree(info);
2080 kfree(info);
2081 }
2082 2069
2083 free_irq(IRQ_AMIGA_TBE, rs_table); 2070 free_irq(IRQ_AMIGA_TBE, rs_table);
2084 free_irq(IRQ_AMIGA_RBF, rs_table); 2071 free_irq(IRQ_AMIGA_RBF, rs_table);
2085 2072
2086 release_mem_region(CUSTOM_PHYSADDR+0x30, 4); 2073 platform_set_drvdata(pdev, NULL);
2074
2075 return error;
2076}
2077
2078static struct platform_driver amiga_serial_driver = {
2079 .remove = __exit_p(amiga_serial_remove),
2080 .driver = {
2081 .name = "amiga-serial",
2082 .owner = THIS_MODULE,
2083 },
2084};
2085
2086static int __init amiga_serial_init(void)
2087{
2088 return platform_driver_probe(&amiga_serial_driver, amiga_serial_probe);
2089}
2090
2091module_init(amiga_serial_init);
2092
2093static void __exit amiga_serial_exit(void)
2094{
2095 platform_driver_unregister(&amiga_serial_driver);
2087} 2096}
2088 2097
2089module_init(rs_init) 2098module_exit(amiga_serial_exit);
2090module_exit(rs_exit)
2091 2099
2092 2100
2093#if defined(CONFIG_SERIAL_CONSOLE) && !defined(MODULE) 2101#if defined(CONFIG_SERIAL_CONSOLE) && !defined(MODULE)
@@ -2154,3 +2162,4 @@ console_initcall(amiserial_console_init);
2154#endif /* CONFIG_SERIAL_CONSOLE && !MODULE */ 2162#endif /* CONFIG_SERIAL_CONSOLE && !MODULE */
2155 2163
2156MODULE_LICENSE("GPL"); 2164MODULE_LICENSE("GPL");
2165MODULE_ALIAS("platform:amiga-serial");
diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c
index 63313a33ba5f..f4ae0e0fb631 100644
--- a/drivers/char/applicom.c
+++ b/drivers/char/applicom.c
@@ -703,14 +703,9 @@ static long ac_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
703 /* In general, the device is only openable by root anyway, so we're not 703 /* In general, the device is only openable by root anyway, so we're not
704 particularly concerned that bogus ioctls can flood the console. */ 704 particularly concerned that bogus ioctls can flood the console. */
705 705
706 adgl = kmalloc(sizeof(struct st_ram_io), GFP_KERNEL); 706 adgl = memdup_user(argp, sizeof(struct st_ram_io));
707 if (!adgl) 707 if (IS_ERR(adgl))
708 return -ENOMEM; 708 return PTR_ERR(adgl);
709
710 if (copy_from_user(adgl, argp, sizeof(struct st_ram_io))) {
711 kfree(adgl);
712 return -EFAULT;
713 }
714 709
715 lock_kernel(); 710 lock_kernel();
716 IndexCard = adgl->num_card-1; 711 IndexCard = adgl->num_card-1;
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index c6ad4234378d..4f3f8c9ec262 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -2505,12 +2505,11 @@ static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum,
2505 return rv; 2505 return rv;
2506 } 2506 }
2507 2507
2508 printk(KERN_INFO 2508 dev_info(intf->si_dev, "Found new BMC (man_id: 0x%6.6x, "
2509 "ipmi: Found new BMC (man_id: 0x%6.6x, " 2509 "prod_id: 0x%4.4x, dev_id: 0x%2.2x)\n",
2510 " prod_id: 0x%4.4x, dev_id: 0x%2.2x)\n", 2510 bmc->id.manufacturer_id,
2511 bmc->id.manufacturer_id, 2511 bmc->id.product_id,
2512 bmc->id.product_id, 2512 bmc->id.device_id);
2513 bmc->id.device_id);
2514 } 2513 }
2515 2514
2516 /* 2515 /*
@@ -4037,8 +4036,8 @@ static void ipmi_request_event(void)
4037 4036
4038static struct timer_list ipmi_timer; 4037static struct timer_list ipmi_timer;
4039 4038
4040/* Call every ~100 ms. */ 4039/* Call every ~1000 ms. */
4041#define IPMI_TIMEOUT_TIME 100 4040#define IPMI_TIMEOUT_TIME 1000
4042 4041
4043/* How many jiffies does it take to get to the timeout time. */ 4042/* How many jiffies does it take to get to the timeout time. */
4044#define IPMI_TIMEOUT_JIFFIES ((IPMI_TIMEOUT_TIME * HZ) / 1000) 4043#define IPMI_TIMEOUT_JIFFIES ((IPMI_TIMEOUT_TIME * HZ) / 1000)
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 47ffe4a90a95..35603dd4e6c5 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -107,6 +107,14 @@ enum si_type {
107}; 107};
108static char *si_to_str[] = { "kcs", "smic", "bt" }; 108static char *si_to_str[] = { "kcs", "smic", "bt" };
109 109
110enum ipmi_addr_src {
111 SI_INVALID = 0, SI_HOTMOD, SI_HARDCODED, SI_SPMI, SI_ACPI, SI_SMBIOS,
112 SI_PCI, SI_DEVICETREE, SI_DEFAULT
113};
114static char *ipmi_addr_src_to_str[] = { NULL, "hotmod", "hardcoded", "SPMI",
115 "ACPI", "SMBIOS", "PCI",
116 "device-tree", "default" };
117
110#define DEVICE_NAME "ipmi_si" 118#define DEVICE_NAME "ipmi_si"
111 119
112static struct platform_driver ipmi_driver = { 120static struct platform_driver ipmi_driver = {
@@ -188,7 +196,7 @@ struct smi_info {
188 int (*irq_setup)(struct smi_info *info); 196 int (*irq_setup)(struct smi_info *info);
189 void (*irq_cleanup)(struct smi_info *info); 197 void (*irq_cleanup)(struct smi_info *info);
190 unsigned int io_size; 198 unsigned int io_size;
191 char *addr_source; /* ACPI, PCI, SMBIOS, hardcode, default. */ 199 enum ipmi_addr_src addr_source; /* ACPI, PCI, SMBIOS, hardcode, etc. */
192 void (*addr_source_cleanup)(struct smi_info *info); 200 void (*addr_source_cleanup)(struct smi_info *info);
193 void *addr_source_data; 201 void *addr_source_data;
194 202
@@ -300,6 +308,7 @@ static int num_max_busy_us;
300 308
301static int unload_when_empty = 1; 309static int unload_when_empty = 1;
302 310
311static int add_smi(struct smi_info *smi);
303static int try_smi_init(struct smi_info *smi); 312static int try_smi_init(struct smi_info *smi);
304static void cleanup_one_si(struct smi_info *to_clean); 313static void cleanup_one_si(struct smi_info *to_clean);
305 314
@@ -314,9 +323,14 @@ static void deliver_recv_msg(struct smi_info *smi_info,
314{ 323{
315 /* Deliver the message to the upper layer with the lock 324 /* Deliver the message to the upper layer with the lock
316 released. */ 325 released. */
317 spin_unlock(&(smi_info->si_lock)); 326
318 ipmi_smi_msg_received(smi_info->intf, msg); 327 if (smi_info->run_to_completion) {
319 spin_lock(&(smi_info->si_lock)); 328 ipmi_smi_msg_received(smi_info->intf, msg);
329 } else {
330 spin_unlock(&(smi_info->si_lock));
331 ipmi_smi_msg_received(smi_info->intf, msg);
332 spin_lock(&(smi_info->si_lock));
333 }
320} 334}
321 335
322static void return_hosed_msg(struct smi_info *smi_info, int cCode) 336static void return_hosed_msg(struct smi_info *smi_info, int cCode)
@@ -445,6 +459,9 @@ static inline void disable_si_irq(struct smi_info *smi_info)
445 if ((smi_info->irq) && (!smi_info->interrupt_disabled)) { 459 if ((smi_info->irq) && (!smi_info->interrupt_disabled)) {
446 start_disable_irq(smi_info); 460 start_disable_irq(smi_info);
447 smi_info->interrupt_disabled = 1; 461 smi_info->interrupt_disabled = 1;
462 if (!atomic_read(&smi_info->stop_operation))
463 mod_timer(&smi_info->si_timer,
464 jiffies + SI_TIMEOUT_JIFFIES);
448 } 465 }
449} 466}
450 467
@@ -576,9 +593,8 @@ static void handle_transaction_done(struct smi_info *smi_info)
576 smi_info->handlers->get_result(smi_info->si_sm, msg, 3); 593 smi_info->handlers->get_result(smi_info->si_sm, msg, 3);
577 if (msg[2] != 0) { 594 if (msg[2] != 0) {
578 /* Error clearing flags */ 595 /* Error clearing flags */
579 printk(KERN_WARNING 596 dev_warn(smi_info->dev,
580 "ipmi_si: Error clearing flags: %2.2x\n", 597 "Error clearing flags: %2.2x\n", msg[2]);
581 msg[2]);
582 } 598 }
583 if (smi_info->si_state == SI_CLEARING_FLAGS_THEN_SET_IRQ) 599 if (smi_info->si_state == SI_CLEARING_FLAGS_THEN_SET_IRQ)
584 start_enable_irq(smi_info); 600 start_enable_irq(smi_info);
@@ -670,9 +686,8 @@ static void handle_transaction_done(struct smi_info *smi_info)
670 /* We got the flags from the SMI, now handle them. */ 686 /* We got the flags from the SMI, now handle them. */
671 smi_info->handlers->get_result(smi_info->si_sm, msg, 4); 687 smi_info->handlers->get_result(smi_info->si_sm, msg, 4);
672 if (msg[2] != 0) { 688 if (msg[2] != 0) {
673 printk(KERN_WARNING 689 dev_warn(smi_info->dev, "Could not enable interrupts"
674 "ipmi_si: Could not enable interrupts" 690 ", failed get, using polled mode.\n");
675 ", failed get, using polled mode.\n");
676 smi_info->si_state = SI_NORMAL; 691 smi_info->si_state = SI_NORMAL;
677 } else { 692 } else {
678 msg[0] = (IPMI_NETFN_APP_REQUEST << 2); 693 msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
@@ -693,11 +708,11 @@ static void handle_transaction_done(struct smi_info *smi_info)
693 708
694 /* We got the flags from the SMI, now handle them. */ 709 /* We got the flags from the SMI, now handle them. */
695 smi_info->handlers->get_result(smi_info->si_sm, msg, 4); 710 smi_info->handlers->get_result(smi_info->si_sm, msg, 4);
696 if (msg[2] != 0) { 711 if (msg[2] != 0)
697 printk(KERN_WARNING 712 dev_warn(smi_info->dev, "Could not enable interrupts"
698 "ipmi_si: Could not enable interrupts" 713 ", failed set, using polled mode.\n");
699 ", failed set, using polled mode.\n"); 714 else
700 } 715 smi_info->interrupt_disabled = 0;
701 smi_info->si_state = SI_NORMAL; 716 smi_info->si_state = SI_NORMAL;
702 break; 717 break;
703 } 718 }
@@ -709,9 +724,8 @@ static void handle_transaction_done(struct smi_info *smi_info)
709 /* We got the flags from the SMI, now handle them. */ 724 /* We got the flags from the SMI, now handle them. */
710 smi_info->handlers->get_result(smi_info->si_sm, msg, 4); 725 smi_info->handlers->get_result(smi_info->si_sm, msg, 4);
711 if (msg[2] != 0) { 726 if (msg[2] != 0) {
712 printk(KERN_WARNING 727 dev_warn(smi_info->dev, "Could not disable interrupts"
713 "ipmi_si: Could not disable interrupts" 728 ", failed get.\n");
714 ", failed get.\n");
715 smi_info->si_state = SI_NORMAL; 729 smi_info->si_state = SI_NORMAL;
716 } else { 730 } else {
717 msg[0] = (IPMI_NETFN_APP_REQUEST << 2); 731 msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
@@ -733,9 +747,8 @@ static void handle_transaction_done(struct smi_info *smi_info)
733 /* We got the flags from the SMI, now handle them. */ 747 /* We got the flags from the SMI, now handle them. */
734 smi_info->handlers->get_result(smi_info->si_sm, msg, 4); 748 smi_info->handlers->get_result(smi_info->si_sm, msg, 4);
735 if (msg[2] != 0) { 749 if (msg[2] != 0) {
736 printk(KERN_WARNING 750 dev_warn(smi_info->dev, "Could not disable interrupts"
737 "ipmi_si: Could not disable interrupts" 751 ", failed set.\n");
738 ", failed set.\n");
739 } 752 }
740 smi_info->si_state = SI_NORMAL; 753 smi_info->si_state = SI_NORMAL;
741 break; 754 break;
@@ -877,6 +890,11 @@ static void sender(void *send_info,
877 printk("**Enqueue: %d.%9.9d\n", t.tv_sec, t.tv_usec); 890 printk("**Enqueue: %d.%9.9d\n", t.tv_sec, t.tv_usec);
878#endif 891#endif
879 892
893 mod_timer(&smi_info->si_timer, jiffies + SI_TIMEOUT_JIFFIES);
894
895 if (smi_info->thread)
896 wake_up_process(smi_info->thread);
897
880 if (smi_info->run_to_completion) { 898 if (smi_info->run_to_completion) {
881 /* 899 /*
882 * If we are running to completion, then throw it in 900 * If we are running to completion, then throw it in
@@ -997,6 +1015,8 @@ static int ipmi_thread(void *data)
997 ; /* do nothing */ 1015 ; /* do nothing */
998 else if (smi_result == SI_SM_CALL_WITH_DELAY && busy_wait) 1016 else if (smi_result == SI_SM_CALL_WITH_DELAY && busy_wait)
999 schedule(); 1017 schedule();
1018 else if (smi_result == SI_SM_IDLE)
1019 schedule_timeout_interruptible(100);
1000 else 1020 else
1001 schedule_timeout_interruptible(0); 1021 schedule_timeout_interruptible(0);
1002 } 1022 }
@@ -1039,6 +1059,7 @@ static void smi_timeout(unsigned long data)
1039 unsigned long flags; 1059 unsigned long flags;
1040 unsigned long jiffies_now; 1060 unsigned long jiffies_now;
1041 long time_diff; 1061 long time_diff;
1062 long timeout;
1042#ifdef DEBUG_TIMING 1063#ifdef DEBUG_TIMING
1043 struct timeval t; 1064 struct timeval t;
1044#endif 1065#endif
@@ -1059,9 +1080,9 @@ static void smi_timeout(unsigned long data)
1059 1080
1060 if ((smi_info->irq) && (!smi_info->interrupt_disabled)) { 1081 if ((smi_info->irq) && (!smi_info->interrupt_disabled)) {
1061 /* Running with interrupts, only do long timeouts. */ 1082 /* Running with interrupts, only do long timeouts. */
1062 smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES; 1083 timeout = jiffies + SI_TIMEOUT_JIFFIES;
1063 smi_inc_stat(smi_info, long_timeouts); 1084 smi_inc_stat(smi_info, long_timeouts);
1064 goto do_add_timer; 1085 goto do_mod_timer;
1065 } 1086 }
1066 1087
1067 /* 1088 /*
@@ -1070,14 +1091,15 @@ static void smi_timeout(unsigned long data)
1070 */ 1091 */
1071 if (smi_result == SI_SM_CALL_WITH_DELAY) { 1092 if (smi_result == SI_SM_CALL_WITH_DELAY) {
1072 smi_inc_stat(smi_info, short_timeouts); 1093 smi_inc_stat(smi_info, short_timeouts);
1073 smi_info->si_timer.expires = jiffies + 1; 1094 timeout = jiffies + 1;
1074 } else { 1095 } else {
1075 smi_inc_stat(smi_info, long_timeouts); 1096 smi_inc_stat(smi_info, long_timeouts);
1076 smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES; 1097 timeout = jiffies + SI_TIMEOUT_JIFFIES;
1077 } 1098 }
1078 1099
1079 do_add_timer: 1100 do_mod_timer:
1080 add_timer(&(smi_info->si_timer)); 1101 if (smi_result != SI_SM_IDLE)
1102 mod_timer(&(smi_info->si_timer), timeout);
1081} 1103}
1082 1104
1083static irqreturn_t si_irq_handler(int irq, void *data) 1105static irqreturn_t si_irq_handler(int irq, void *data)
@@ -1144,10 +1166,10 @@ static int smi_start_processing(void *send_info,
1144 new_smi->thread = kthread_run(ipmi_thread, new_smi, 1166 new_smi->thread = kthread_run(ipmi_thread, new_smi,
1145 "kipmi%d", new_smi->intf_num); 1167 "kipmi%d", new_smi->intf_num);
1146 if (IS_ERR(new_smi->thread)) { 1168 if (IS_ERR(new_smi->thread)) {
1147 printk(KERN_NOTICE "ipmi_si_intf: Could not start" 1169 dev_notice(new_smi->dev, "Could not start"
1148 " kernel thread due to error %ld, only using" 1170 " kernel thread due to error %ld, only using"
1149 " timers to drive the interface\n", 1171 " timers to drive the interface\n",
1150 PTR_ERR(new_smi->thread)); 1172 PTR_ERR(new_smi->thread));
1151 new_smi->thread = NULL; 1173 new_smi->thread = NULL;
1152 } 1174 }
1153 } 1175 }
@@ -1308,14 +1330,13 @@ static int std_irq_setup(struct smi_info *info)
1308 DEVICE_NAME, 1330 DEVICE_NAME,
1309 info); 1331 info);
1310 if (rv) { 1332 if (rv) {
1311 printk(KERN_WARNING 1333 dev_warn(info->dev, "%s unable to claim interrupt %d,"
1312 "ipmi_si: %s unable to claim interrupt %d," 1334 " running polled\n",
1313 " running polled\n", 1335 DEVICE_NAME, info->irq);
1314 DEVICE_NAME, info->irq);
1315 info->irq = 0; 1336 info->irq = 0;
1316 } else { 1337 } else {
1317 info->irq_cleanup = std_irq_cleanup; 1338 info->irq_cleanup = std_irq_cleanup;
1318 printk(" Using irq %d\n", info->irq); 1339 dev_info(info->dev, "Using irq %d\n", info->irq);
1319 } 1340 }
1320 1341
1321 return rv; 1342 return rv;
@@ -1406,8 +1427,8 @@ static int port_setup(struct smi_info *info)
1406 info->io.outputb = port_outl; 1427 info->io.outputb = port_outl;
1407 break; 1428 break;
1408 default: 1429 default:
1409 printk(KERN_WARNING "ipmi_si: Invalid register size: %d\n", 1430 dev_warn(info->dev, "Invalid register size: %d\n",
1410 info->io.regsize); 1431 info->io.regsize);
1411 return -EINVAL; 1432 return -EINVAL;
1412 } 1433 }
1413 1434
@@ -1529,8 +1550,8 @@ static int mem_setup(struct smi_info *info)
1529 break; 1550 break;
1530#endif 1551#endif
1531 default: 1552 default:
1532 printk(KERN_WARNING "ipmi_si: Invalid register size: %d\n", 1553 dev_warn(info->dev, "Invalid register size: %d\n",
1533 info->io.regsize); 1554 info->io.regsize);
1534 return -EINVAL; 1555 return -EINVAL;
1535 } 1556 }
1536 1557
@@ -1755,7 +1776,7 @@ static int hotmod_handler(const char *val, struct kernel_param *kp)
1755 goto out; 1776 goto out;
1756 } 1777 }
1757 1778
1758 info->addr_source = "hotmod"; 1779 info->addr_source = SI_HOTMOD;
1759 info->si_type = si_type; 1780 info->si_type = si_type;
1760 info->io.addr_data = addr; 1781 info->io.addr_data = addr;
1761 info->io.addr_type = addr_space; 1782 info->io.addr_type = addr_space;
@@ -1777,7 +1798,9 @@ static int hotmod_handler(const char *val, struct kernel_param *kp)
1777 info->irq_setup = std_irq_setup; 1798 info->irq_setup = std_irq_setup;
1778 info->slave_addr = ipmb; 1799 info->slave_addr = ipmb;
1779 1800
1780 try_smi_init(info); 1801 if (!add_smi(info))
1802 if (try_smi_init(info))
1803 cleanup_one_si(info);
1781 } else { 1804 } else {
1782 /* remove */ 1805 /* remove */
1783 struct smi_info *e, *tmp_e; 1806 struct smi_info *e, *tmp_e;
@@ -1813,7 +1836,8 @@ static __devinit void hardcode_find_bmc(void)
1813 if (!info) 1836 if (!info)
1814 return; 1837 return;
1815 1838
1816 info->addr_source = "hardcoded"; 1839 info->addr_source = SI_HARDCODED;
1840 printk(KERN_INFO PFX "probing via hardcoded address\n");
1817 1841
1818 if (!si_type[i] || strcmp(si_type[i], "kcs") == 0) { 1842 if (!si_type[i] || strcmp(si_type[i], "kcs") == 0) {
1819 info->si_type = SI_KCS; 1843 info->si_type = SI_KCS;
@@ -1822,8 +1846,7 @@ static __devinit void hardcode_find_bmc(void)
1822 } else if (strcmp(si_type[i], "bt") == 0) { 1846 } else if (strcmp(si_type[i], "bt") == 0) {
1823 info->si_type = SI_BT; 1847 info->si_type = SI_BT;
1824 } else { 1848 } else {
1825 printk(KERN_WARNING 1849 printk(KERN_WARNING PFX "Interface type specified "
1826 "ipmi_si: Interface type specified "
1827 "for interface %d, was invalid: %s\n", 1850 "for interface %d, was invalid: %s\n",
1828 i, si_type[i]); 1851 i, si_type[i]);
1829 kfree(info); 1852 kfree(info);
@@ -1841,11 +1864,9 @@ static __devinit void hardcode_find_bmc(void)
1841 info->io.addr_data = addrs[i]; 1864 info->io.addr_data = addrs[i];
1842 info->io.addr_type = IPMI_MEM_ADDR_SPACE; 1865 info->io.addr_type = IPMI_MEM_ADDR_SPACE;
1843 } else { 1866 } else {
1844 printk(KERN_WARNING 1867 printk(KERN_WARNING PFX "Interface type specified "
1845 "ipmi_si: Interface type specified " 1868 "for interface %d, but port and address were "
1846 "for interface %d, " 1869 "not set or set to zero.\n", i);
1847 "but port and address were not set or "
1848 "set to zero.\n", i);
1849 kfree(info); 1870 kfree(info);
1850 continue; 1871 continue;
1851 } 1872 }
@@ -1863,7 +1884,9 @@ static __devinit void hardcode_find_bmc(void)
1863 info->irq_setup = std_irq_setup; 1884 info->irq_setup = std_irq_setup;
1864 info->slave_addr = slave_addrs[i]; 1885 info->slave_addr = slave_addrs[i];
1865 1886
1866 try_smi_init(info); 1887 if (!add_smi(info))
1888 if (try_smi_init(info))
1889 cleanup_one_si(info);
1867 } 1890 }
1868} 1891}
1869 1892
@@ -1923,15 +1946,13 @@ static int acpi_gpe_irq_setup(struct smi_info *info)
1923 &ipmi_acpi_gpe, 1946 &ipmi_acpi_gpe,
1924 info); 1947 info);
1925 if (status != AE_OK) { 1948 if (status != AE_OK) {
1926 printk(KERN_WARNING 1949 dev_warn(info->dev, "%s unable to claim ACPI GPE %d,"
1927 "ipmi_si: %s unable to claim ACPI GPE %d," 1950 " running polled\n", DEVICE_NAME, info->irq);
1928 " running polled\n",
1929 DEVICE_NAME, info->irq);
1930 info->irq = 0; 1951 info->irq = 0;
1931 return -EINVAL; 1952 return -EINVAL;
1932 } else { 1953 } else {
1933 info->irq_cleanup = acpi_gpe_irq_cleanup; 1954 info->irq_cleanup = acpi_gpe_irq_cleanup;
1934 printk(" Using ACPI GPE %d\n", info->irq); 1955 dev_info(info->dev, "Using ACPI GPE %d\n", info->irq);
1935 return 0; 1956 return 0;
1936 } 1957 }
1937} 1958}
@@ -1989,8 +2010,8 @@ static __devinit int try_init_spmi(struct SPMITable *spmi)
1989 u8 addr_space; 2010 u8 addr_space;
1990 2011
1991 if (spmi->IPMIlegacy != 1) { 2012 if (spmi->IPMIlegacy != 1) {
1992 printk(KERN_INFO "IPMI: Bad SPMI legacy %d\n", spmi->IPMIlegacy); 2013 printk(KERN_INFO PFX "Bad SPMI legacy %d\n", spmi->IPMIlegacy);
1993 return -ENODEV; 2014 return -ENODEV;
1994 } 2015 }
1995 2016
1996 if (spmi->addr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) 2017 if (spmi->addr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
@@ -2000,11 +2021,12 @@ static __devinit int try_init_spmi(struct SPMITable *spmi)
2000 2021
2001 info = kzalloc(sizeof(*info), GFP_KERNEL); 2022 info = kzalloc(sizeof(*info), GFP_KERNEL);
2002 if (!info) { 2023 if (!info) {
2003 printk(KERN_ERR "ipmi_si: Could not allocate SI data (3)\n"); 2024 printk(KERN_ERR PFX "Could not allocate SI data (3)\n");
2004 return -ENOMEM; 2025 return -ENOMEM;
2005 } 2026 }
2006 2027
2007 info->addr_source = "SPMI"; 2028 info->addr_source = SI_SPMI;
2029 printk(KERN_INFO PFX "probing via SPMI\n");
2008 2030
2009 /* Figure out the interface type. */ 2031 /* Figure out the interface type. */
2010 switch (spmi->InterfaceType) { 2032 switch (spmi->InterfaceType) {
@@ -2018,8 +2040,8 @@ static __devinit int try_init_spmi(struct SPMITable *spmi)
2018 info->si_type = SI_BT; 2040 info->si_type = SI_BT;
2019 break; 2041 break;
2020 default: 2042 default:
2021 printk(KERN_INFO "ipmi_si: Unknown ACPI/SPMI SI type %d\n", 2043 printk(KERN_INFO PFX "Unknown ACPI/SPMI SI type %d\n",
2022 spmi->InterfaceType); 2044 spmi->InterfaceType);
2023 kfree(info); 2045 kfree(info);
2024 return -EIO; 2046 return -EIO;
2025 } 2047 }
@@ -2055,13 +2077,12 @@ static __devinit int try_init_spmi(struct SPMITable *spmi)
2055 info->io.addr_type = IPMI_IO_ADDR_SPACE; 2077 info->io.addr_type = IPMI_IO_ADDR_SPACE;
2056 } else { 2078 } else {
2057 kfree(info); 2079 kfree(info);
2058 printk(KERN_WARNING 2080 printk(KERN_WARNING PFX "Unknown ACPI I/O Address type\n");
2059 "ipmi_si: Unknown ACPI I/O Address type\n");
2060 return -EIO; 2081 return -EIO;
2061 } 2082 }
2062 info->io.addr_data = spmi->addr.address; 2083 info->io.addr_data = spmi->addr.address;
2063 2084
2064 try_smi_init(info); 2085 add_smi(info);
2065 2086
2066 return 0; 2087 return 0;
2067} 2088}
@@ -2093,6 +2114,7 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev,
2093{ 2114{
2094 struct acpi_device *acpi_dev; 2115 struct acpi_device *acpi_dev;
2095 struct smi_info *info; 2116 struct smi_info *info;
2117 struct resource *res;
2096 acpi_handle handle; 2118 acpi_handle handle;
2097 acpi_status status; 2119 acpi_status status;
2098 unsigned long long tmp; 2120 unsigned long long tmp;
@@ -2105,7 +2127,8 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev,
2105 if (!info) 2127 if (!info)
2106 return -ENOMEM; 2128 return -ENOMEM;
2107 2129
2108 info->addr_source = "ACPI"; 2130 info->addr_source = SI_ACPI;
2131 printk(KERN_INFO PFX "probing via ACPI\n");
2109 2132
2110 handle = acpi_dev->handle; 2133 handle = acpi_dev->handle;
2111 2134
@@ -2125,22 +2148,26 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev,
2125 info->si_type = SI_BT; 2148 info->si_type = SI_BT;
2126 break; 2149 break;
2127 default: 2150 default:
2128 dev_info(&dev->dev, "unknown interface type %lld\n", tmp); 2151 dev_info(&dev->dev, "unknown IPMI type %lld\n", tmp);
2129 goto err_free; 2152 goto err_free;
2130 } 2153 }
2131 2154
2132 if (pnp_port_valid(dev, 0)) { 2155 res = pnp_get_resource(dev, IORESOURCE_IO, 0);
2156 if (res) {
2133 info->io_setup = port_setup; 2157 info->io_setup = port_setup;
2134 info->io.addr_type = IPMI_IO_ADDR_SPACE; 2158 info->io.addr_type = IPMI_IO_ADDR_SPACE;
2135 info->io.addr_data = pnp_port_start(dev, 0);
2136 } else if (pnp_mem_valid(dev, 0)) {
2137 info->io_setup = mem_setup;
2138 info->io.addr_type = IPMI_MEM_ADDR_SPACE;
2139 info->io.addr_data = pnp_mem_start(dev, 0);
2140 } else { 2159 } else {
2160 res = pnp_get_resource(dev, IORESOURCE_MEM, 0);
2161 if (res) {
2162 info->io_setup = mem_setup;
2163 info->io.addr_type = IPMI_MEM_ADDR_SPACE;
2164 }
2165 }
2166 if (!res) {
2141 dev_err(&dev->dev, "no I/O or memory address\n"); 2167 dev_err(&dev->dev, "no I/O or memory address\n");
2142 goto err_free; 2168 goto err_free;
2143 } 2169 }
2170 info->io.addr_data = res->start;
2144 2171
2145 info->io.regspacing = DEFAULT_REGSPACING; 2172 info->io.regspacing = DEFAULT_REGSPACING;
2146 info->io.regsize = DEFAULT_REGSPACING; 2173 info->io.regsize = DEFAULT_REGSPACING;
@@ -2156,10 +2183,14 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev,
2156 info->irq_setup = std_irq_setup; 2183 info->irq_setup = std_irq_setup;
2157 } 2184 }
2158 2185
2159 info->dev = &acpi_dev->dev; 2186 info->dev = &dev->dev;
2160 pnp_set_drvdata(dev, info); 2187 pnp_set_drvdata(dev, info);
2161 2188
2162 return try_smi_init(info); 2189 dev_info(info->dev, "%pR regsize %d spacing %d irq %d\n",
2190 res, info->io.regsize, info->io.regspacing,
2191 info->irq);
2192
2193 return add_smi(info);
2163 2194
2164err_free: 2195err_free:
2165 kfree(info); 2196 kfree(info);
@@ -2264,12 +2295,12 @@ static __devinit void try_init_dmi(struct dmi_ipmi_data *ipmi_data)
2264 2295
2265 info = kzalloc(sizeof(*info), GFP_KERNEL); 2296 info = kzalloc(sizeof(*info), GFP_KERNEL);
2266 if (!info) { 2297 if (!info) {
2267 printk(KERN_ERR 2298 printk(KERN_ERR PFX "Could not allocate SI data\n");
2268 "ipmi_si: Could not allocate SI data\n");
2269 return; 2299 return;
2270 } 2300 }
2271 2301
2272 info->addr_source = "SMBIOS"; 2302 info->addr_source = SI_SMBIOS;
2303 printk(KERN_INFO PFX "probing via SMBIOS\n");
2273 2304
2274 switch (ipmi_data->type) { 2305 switch (ipmi_data->type) {
2275 case 0x01: /* KCS */ 2306 case 0x01: /* KCS */
@@ -2299,8 +2330,7 @@ static __devinit void try_init_dmi(struct dmi_ipmi_data *ipmi_data)
2299 2330
2300 default: 2331 default:
2301 kfree(info); 2332 kfree(info);
2302 printk(KERN_WARNING 2333 printk(KERN_WARNING PFX "Unknown SMBIOS I/O Address type: %d\n",
2303 "ipmi_si: Unknown SMBIOS I/O Address type: %d.\n",
2304 ipmi_data->addr_space); 2334 ipmi_data->addr_space);
2305 return; 2335 return;
2306 } 2336 }
@@ -2318,7 +2348,7 @@ static __devinit void try_init_dmi(struct dmi_ipmi_data *ipmi_data)
2318 if (info->irq) 2348 if (info->irq)
2319 info->irq_setup = std_irq_setup; 2349 info->irq_setup = std_irq_setup;
2320 2350
2321 try_smi_init(info); 2351 add_smi(info);
2322} 2352}
2323 2353
2324static void __devinit dmi_find_bmc(void) 2354static void __devinit dmi_find_bmc(void)
@@ -2368,7 +2398,8 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev,
2368 if (!info) 2398 if (!info)
2369 return -ENOMEM; 2399 return -ENOMEM;
2370 2400
2371 info->addr_source = "PCI"; 2401 info->addr_source = SI_PCI;
2402 dev_info(&pdev->dev, "probing via PCI");
2372 2403
2373 switch (class_type) { 2404 switch (class_type) {
2374 case PCI_ERMC_CLASSCODE_TYPE_SMIC: 2405 case PCI_ERMC_CLASSCODE_TYPE_SMIC:
@@ -2385,15 +2416,13 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev,
2385 2416
2386 default: 2417 default:
2387 kfree(info); 2418 kfree(info);
2388 printk(KERN_INFO "ipmi_si: %s: Unknown IPMI type: %d\n", 2419 dev_info(&pdev->dev, "Unknown IPMI type: %d\n", class_type);
2389 pci_name(pdev), class_type);
2390 return -ENOMEM; 2420 return -ENOMEM;
2391 } 2421 }
2392 2422
2393 rv = pci_enable_device(pdev); 2423 rv = pci_enable_device(pdev);
2394 if (rv) { 2424 if (rv) {
2395 printk(KERN_ERR "ipmi_si: %s: couldn't enable PCI device\n", 2425 dev_err(&pdev->dev, "couldn't enable PCI device\n");
2396 pci_name(pdev));
2397 kfree(info); 2426 kfree(info);
2398 return rv; 2427 return rv;
2399 } 2428 }
@@ -2421,7 +2450,11 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev,
2421 info->dev = &pdev->dev; 2450 info->dev = &pdev->dev;
2422 pci_set_drvdata(pdev, info); 2451 pci_set_drvdata(pdev, info);
2423 2452
2424 return try_smi_init(info); 2453 dev_info(&pdev->dev, "%pR regsize %d spacing %d irq %d\n",
2454 &pdev->resource[0], info->io.regsize, info->io.regspacing,
2455 info->irq);
2456
2457 return add_smi(info);
2425} 2458}
2426 2459
2427static void __devexit ipmi_pci_remove(struct pci_dev *pdev) 2460static void __devexit ipmi_pci_remove(struct pci_dev *pdev)
@@ -2473,7 +2506,7 @@ static int __devinit ipmi_of_probe(struct of_device *dev,
2473 int ret; 2506 int ret;
2474 int proplen; 2507 int proplen;
2475 2508
2476 dev_info(&dev->dev, PFX "probing via device tree\n"); 2509 dev_info(&dev->dev, "probing via device tree\n");
2477 2510
2478 ret = of_address_to_resource(np, 0, &resource); 2511 ret = of_address_to_resource(np, 0, &resource);
2479 if (ret) { 2512 if (ret) {
@@ -2503,12 +2536,12 @@ static int __devinit ipmi_of_probe(struct of_device *dev,
2503 2536
2504 if (!info) { 2537 if (!info) {
2505 dev_err(&dev->dev, 2538 dev_err(&dev->dev,
2506 PFX "could not allocate memory for OF probe\n"); 2539 "could not allocate memory for OF probe\n");
2507 return -ENOMEM; 2540 return -ENOMEM;
2508 } 2541 }
2509 2542
2510 info->si_type = (enum si_type) match->data; 2543 info->si_type = (enum si_type) match->data;
2511 info->addr_source = "device-tree"; 2544 info->addr_source = SI_DEVICETREE;
2512 info->irq_setup = std_irq_setup; 2545 info->irq_setup = std_irq_setup;
2513 2546
2514 if (resource.flags & IORESOURCE_IO) { 2547 if (resource.flags & IORESOURCE_IO) {
@@ -2528,13 +2561,13 @@ static int __devinit ipmi_of_probe(struct of_device *dev,
2528 info->irq = irq_of_parse_and_map(dev->dev.of_node, 0); 2561 info->irq = irq_of_parse_and_map(dev->dev.of_node, 0);
2529 info->dev = &dev->dev; 2562 info->dev = &dev->dev;
2530 2563
2531 dev_dbg(&dev->dev, "addr 0x%lx regsize %d spacing %d irq %x\n", 2564 dev_dbg(&dev->dev, "addr 0x%lx regsize %d spacing %d irq %d\n",
2532 info->io.addr_data, info->io.regsize, info->io.regspacing, 2565 info->io.addr_data, info->io.regsize, info->io.regspacing,
2533 info->irq); 2566 info->irq);
2534 2567
2535 dev_set_drvdata(&dev->dev, info); 2568 dev_set_drvdata(&dev->dev, info);
2536 2569
2537 return try_smi_init(info); 2570 return add_smi(info);
2538} 2571}
2539 2572
2540static int __devexit ipmi_of_remove(struct of_device *dev) 2573static int __devexit ipmi_of_remove(struct of_device *dev)
@@ -2643,9 +2676,8 @@ static int try_enable_event_buffer(struct smi_info *smi_info)
2643 2676
2644 rv = wait_for_msg_done(smi_info); 2677 rv = wait_for_msg_done(smi_info);
2645 if (rv) { 2678 if (rv) {
2646 printk(KERN_WARNING 2679 printk(KERN_WARNING PFX "Error getting response from get"
2647 "ipmi_si: Error getting response from get global," 2680 " global enables command, the event buffer is not"
2648 " enables command, the event buffer is not"
2649 " enabled.\n"); 2681 " enabled.\n");
2650 goto out; 2682 goto out;
2651 } 2683 }
@@ -2657,10 +2689,8 @@ static int try_enable_event_buffer(struct smi_info *smi_info)
2657 resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 || 2689 resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 ||
2658 resp[1] != IPMI_GET_BMC_GLOBAL_ENABLES_CMD || 2690 resp[1] != IPMI_GET_BMC_GLOBAL_ENABLES_CMD ||
2659 resp[2] != 0) { 2691 resp[2] != 0) {
2660 printk(KERN_WARNING 2692 printk(KERN_WARNING PFX "Invalid return from get global"
2661 "ipmi_si: Invalid return from get global" 2693 " enables command, cannot enable the event buffer.\n");
2662 " enables command, cannot enable the event"
2663 " buffer.\n");
2664 rv = -EINVAL; 2694 rv = -EINVAL;
2665 goto out; 2695 goto out;
2666 } 2696 }
@@ -2676,9 +2706,8 @@ static int try_enable_event_buffer(struct smi_info *smi_info)
2676 2706
2677 rv = wait_for_msg_done(smi_info); 2707 rv = wait_for_msg_done(smi_info);
2678 if (rv) { 2708 if (rv) {
2679 printk(KERN_WARNING 2709 printk(KERN_WARNING PFX "Error getting response from set"
2680 "ipmi_si: Error getting response from set global," 2710 " global, enables command, the event buffer is not"
2681 " enables command, the event buffer is not"
2682 " enabled.\n"); 2711 " enabled.\n");
2683 goto out; 2712 goto out;
2684 } 2713 }
@@ -2689,10 +2718,8 @@ static int try_enable_event_buffer(struct smi_info *smi_info)
2689 if (resp_len < 3 || 2718 if (resp_len < 3 ||
2690 resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 || 2719 resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 ||
2691 resp[1] != IPMI_SET_BMC_GLOBAL_ENABLES_CMD) { 2720 resp[1] != IPMI_SET_BMC_GLOBAL_ENABLES_CMD) {
2692 printk(KERN_WARNING 2721 printk(KERN_WARNING PFX "Invalid return from get global,"
2693 "ipmi_si: Invalid return from get global," 2722 "enables command, not enable the event buffer.\n");
2694 "enables command, not enable the event"
2695 " buffer.\n");
2696 rv = -EINVAL; 2723 rv = -EINVAL;
2697 goto out; 2724 goto out;
2698 } 2725 }
@@ -2951,7 +2978,7 @@ static __devinit void default_find_bmc(void)
2951 if (!info) 2978 if (!info)
2952 return; 2979 return;
2953 2980
2954 info->addr_source = NULL; 2981 info->addr_source = SI_DEFAULT;
2955 2982
2956 info->si_type = ipmi_defaults[i].type; 2983 info->si_type = ipmi_defaults[i].type;
2957 info->io_setup = port_setup; 2984 info->io_setup = port_setup;
@@ -2963,14 +2990,16 @@ static __devinit void default_find_bmc(void)
2963 info->io.regsize = DEFAULT_REGSPACING; 2990 info->io.regsize = DEFAULT_REGSPACING;
2964 info->io.regshift = 0; 2991 info->io.regshift = 0;
2965 2992
2966 if (try_smi_init(info) == 0) { 2993 if (add_smi(info) == 0) {
2967 /* Found one... */ 2994 if ((try_smi_init(info)) == 0) {
2968 printk(KERN_INFO "ipmi_si: Found default %s state" 2995 /* Found one... */
2969 " machine at %s address 0x%lx\n", 2996 printk(KERN_INFO PFX "Found default %s"
2970 si_to_str[info->si_type], 2997 " state machine at %s address 0x%lx\n",
2971 addr_space_to_str[info->io.addr_type], 2998 si_to_str[info->si_type],
2972 info->io.addr_data); 2999 addr_space_to_str[info->io.addr_type],
2973 return; 3000 info->io.addr_data);
3001 } else
3002 cleanup_one_si(info);
2974 } 3003 }
2975 } 3004 }
2976} 3005}
@@ -2989,34 +3018,48 @@ static int is_new_interface(struct smi_info *info)
2989 return 1; 3018 return 1;
2990} 3019}
2991 3020
2992static int try_smi_init(struct smi_info *new_smi) 3021static int add_smi(struct smi_info *new_smi)
2993{ 3022{
2994 int rv; 3023 int rv = 0;
2995 int i;
2996
2997 if (new_smi->addr_source) {
2998 printk(KERN_INFO "ipmi_si: Trying %s-specified %s state"
2999 " machine at %s address 0x%lx, slave address 0x%x,"
3000 " irq %d\n",
3001 new_smi->addr_source,
3002 si_to_str[new_smi->si_type],
3003 addr_space_to_str[new_smi->io.addr_type],
3004 new_smi->io.addr_data,
3005 new_smi->slave_addr, new_smi->irq);
3006 }
3007 3024
3025 printk(KERN_INFO PFX "Adding %s-specified %s state machine",
3026 ipmi_addr_src_to_str[new_smi->addr_source],
3027 si_to_str[new_smi->si_type]);
3008 mutex_lock(&smi_infos_lock); 3028 mutex_lock(&smi_infos_lock);
3009 if (!is_new_interface(new_smi)) { 3029 if (!is_new_interface(new_smi)) {
3010 printk(KERN_WARNING "ipmi_si: duplicate interface\n"); 3030 printk(KERN_CONT PFX "duplicate interface\n");
3011 rv = -EBUSY; 3031 rv = -EBUSY;
3012 goto out_err; 3032 goto out_err;
3013 } 3033 }
3014 3034
3035 printk(KERN_CONT "\n");
3036
3015 /* So we know not to free it unless we have allocated one. */ 3037 /* So we know not to free it unless we have allocated one. */
3016 new_smi->intf = NULL; 3038 new_smi->intf = NULL;
3017 new_smi->si_sm = NULL; 3039 new_smi->si_sm = NULL;
3018 new_smi->handlers = NULL; 3040 new_smi->handlers = NULL;
3019 3041
3042 list_add_tail(&new_smi->link, &smi_infos);
3043
3044out_err:
3045 mutex_unlock(&smi_infos_lock);
3046 return rv;
3047}
3048
3049static int try_smi_init(struct smi_info *new_smi)
3050{
3051 int rv = 0;
3052 int i;
3053
3054 printk(KERN_INFO PFX "Trying %s-specified %s state"
3055 " machine at %s address 0x%lx, slave address 0x%x,"
3056 " irq %d\n",
3057 ipmi_addr_src_to_str[new_smi->addr_source],
3058 si_to_str[new_smi->si_type],
3059 addr_space_to_str[new_smi->io.addr_type],
3060 new_smi->io.addr_data,
3061 new_smi->slave_addr, new_smi->irq);
3062
3020 switch (new_smi->si_type) { 3063 switch (new_smi->si_type) {
3021 case SI_KCS: 3064 case SI_KCS:
3022 new_smi->handlers = &kcs_smi_handlers; 3065 new_smi->handlers = &kcs_smi_handlers;
@@ -3039,7 +3082,8 @@ static int try_smi_init(struct smi_info *new_smi)
3039 /* Allocate the state machine's data and initialize it. */ 3082 /* Allocate the state machine's data and initialize it. */
3040 new_smi->si_sm = kmalloc(new_smi->handlers->size(), GFP_KERNEL); 3083 new_smi->si_sm = kmalloc(new_smi->handlers->size(), GFP_KERNEL);
3041 if (!new_smi->si_sm) { 3084 if (!new_smi->si_sm) {
3042 printk(KERN_ERR "Could not allocate state machine memory\n"); 3085 printk(KERN_ERR PFX
3086 "Could not allocate state machine memory\n");
3043 rv = -ENOMEM; 3087 rv = -ENOMEM;
3044 goto out_err; 3088 goto out_err;
3045 } 3089 }
@@ -3049,7 +3093,7 @@ static int try_smi_init(struct smi_info *new_smi)
3049 /* Now that we know the I/O size, we can set up the I/O. */ 3093 /* Now that we know the I/O size, we can set up the I/O. */
3050 rv = new_smi->io_setup(new_smi); 3094 rv = new_smi->io_setup(new_smi);
3051 if (rv) { 3095 if (rv) {
3052 printk(KERN_ERR "Could not set up I/O space\n"); 3096 printk(KERN_ERR PFX "Could not set up I/O space\n");
3053 goto out_err; 3097 goto out_err;
3054 } 3098 }
3055 3099
@@ -3059,8 +3103,7 @@ static int try_smi_init(struct smi_info *new_smi)
3059 /* Do low-level detection first. */ 3103 /* Do low-level detection first. */
3060 if (new_smi->handlers->detect(new_smi->si_sm)) { 3104 if (new_smi->handlers->detect(new_smi->si_sm)) {
3061 if (new_smi->addr_source) 3105 if (new_smi->addr_source)
3062 printk(KERN_INFO "ipmi_si: Interface detection" 3106 printk(KERN_INFO PFX "Interface detection failed\n");
3063 " failed\n");
3064 rv = -ENODEV; 3107 rv = -ENODEV;
3065 goto out_err; 3108 goto out_err;
3066 } 3109 }
@@ -3072,7 +3115,7 @@ static int try_smi_init(struct smi_info *new_smi)
3072 rv = try_get_dev_id(new_smi); 3115 rv = try_get_dev_id(new_smi);
3073 if (rv) { 3116 if (rv) {
3074 if (new_smi->addr_source) 3117 if (new_smi->addr_source)
3075 printk(KERN_INFO "ipmi_si: There appears to be no BMC" 3118 printk(KERN_INFO PFX "There appears to be no BMC"
3076 " at this location\n"); 3119 " at this location\n");
3077 goto out_err; 3120 goto out_err;
3078 } 3121 }
@@ -3088,7 +3131,7 @@ static int try_smi_init(struct smi_info *new_smi)
3088 for (i = 0; i < SI_NUM_STATS; i++) 3131 for (i = 0; i < SI_NUM_STATS; i++)
3089 atomic_set(&new_smi->stats[i], 0); 3132 atomic_set(&new_smi->stats[i], 0);
3090 3133
3091 new_smi->interrupt_disabled = 0; 3134 new_smi->interrupt_disabled = 1;
3092 atomic_set(&new_smi->stop_operation, 0); 3135 atomic_set(&new_smi->stop_operation, 0);
3093 new_smi->intf_num = smi_num; 3136 new_smi->intf_num = smi_num;
3094 smi_num++; 3137 smi_num++;
@@ -3114,9 +3157,8 @@ static int try_smi_init(struct smi_info *new_smi)
3114 new_smi->pdev = platform_device_alloc("ipmi_si", 3157 new_smi->pdev = platform_device_alloc("ipmi_si",
3115 new_smi->intf_num); 3158 new_smi->intf_num);
3116 if (!new_smi->pdev) { 3159 if (!new_smi->pdev) {
3117 printk(KERN_ERR 3160 printk(KERN_ERR PFX
3118 "ipmi_si_intf:" 3161 "Unable to allocate platform device\n");
3119 " Unable to allocate platform device\n");
3120 goto out_err; 3162 goto out_err;
3121 } 3163 }
3122 new_smi->dev = &new_smi->pdev->dev; 3164 new_smi->dev = &new_smi->pdev->dev;
@@ -3124,9 +3166,8 @@ static int try_smi_init(struct smi_info *new_smi)
3124 3166
3125 rv = platform_device_add(new_smi->pdev); 3167 rv = platform_device_add(new_smi->pdev);
3126 if (rv) { 3168 if (rv) {
3127 printk(KERN_ERR 3169 printk(KERN_ERR PFX
3128 "ipmi_si_intf:" 3170 "Unable to register system interface device:"
3129 " Unable to register system interface device:"
3130 " %d\n", 3171 " %d\n",
3131 rv); 3172 rv);
3132 goto out_err; 3173 goto out_err;
@@ -3141,9 +3182,8 @@ static int try_smi_init(struct smi_info *new_smi)
3141 "bmc", 3182 "bmc",
3142 new_smi->slave_addr); 3183 new_smi->slave_addr);
3143 if (rv) { 3184 if (rv) {
3144 printk(KERN_ERR 3185 dev_err(new_smi->dev, "Unable to register device: error %d\n",
3145 "ipmi_si: Unable to register device: error %d\n", 3186 rv);
3146 rv);
3147 goto out_err_stop_timer; 3187 goto out_err_stop_timer;
3148 } 3188 }
3149 3189
@@ -3151,9 +3191,7 @@ static int try_smi_init(struct smi_info *new_smi)
3151 type_file_read_proc, 3191 type_file_read_proc,
3152 new_smi); 3192 new_smi);
3153 if (rv) { 3193 if (rv) {
3154 printk(KERN_ERR 3194 dev_err(new_smi->dev, "Unable to create proc entry: %d\n", rv);
3155 "ipmi_si: Unable to create proc entry: %d\n",
3156 rv);
3157 goto out_err_stop_timer; 3195 goto out_err_stop_timer;
3158 } 3196 }
3159 3197
@@ -3161,9 +3199,7 @@ static int try_smi_init(struct smi_info *new_smi)
3161 stat_file_read_proc, 3199 stat_file_read_proc,
3162 new_smi); 3200 new_smi);
3163 if (rv) { 3201 if (rv) {
3164 printk(KERN_ERR 3202 dev_err(new_smi->dev, "Unable to create proc entry: %d\n", rv);
3165 "ipmi_si: Unable to create proc entry: %d\n",
3166 rv);
3167 goto out_err_stop_timer; 3203 goto out_err_stop_timer;
3168 } 3204 }
3169 3205
@@ -3171,18 +3207,12 @@ static int try_smi_init(struct smi_info *new_smi)
3171 param_read_proc, 3207 param_read_proc,
3172 new_smi); 3208 new_smi);
3173 if (rv) { 3209 if (rv) {
3174 printk(KERN_ERR 3210 dev_err(new_smi->dev, "Unable to create proc entry: %d\n", rv);
3175 "ipmi_si: Unable to create proc entry: %d\n",
3176 rv);
3177 goto out_err_stop_timer; 3211 goto out_err_stop_timer;
3178 } 3212 }
3179 3213
3180 list_add_tail(&new_smi->link, &smi_infos); 3214 dev_info(new_smi->dev, "IPMI %s interface initialized\n",
3181 3215 si_to_str[new_smi->si_type]);
3182 mutex_unlock(&smi_infos_lock);
3183
3184 printk(KERN_INFO "IPMI %s interface initialized\n",
3185 si_to_str[new_smi->si_type]);
3186 3216
3187 return 0; 3217 return 0;
3188 3218
@@ -3191,11 +3221,17 @@ static int try_smi_init(struct smi_info *new_smi)
3191 wait_for_timer_and_thread(new_smi); 3221 wait_for_timer_and_thread(new_smi);
3192 3222
3193 out_err: 3223 out_err:
3194 if (new_smi->intf) 3224 new_smi->interrupt_disabled = 1;
3225
3226 if (new_smi->intf) {
3195 ipmi_unregister_smi(new_smi->intf); 3227 ipmi_unregister_smi(new_smi->intf);
3228 new_smi->intf = NULL;
3229 }
3196 3230
3197 if (new_smi->irq_cleanup) 3231 if (new_smi->irq_cleanup) {
3198 new_smi->irq_cleanup(new_smi); 3232 new_smi->irq_cleanup(new_smi);
3233 new_smi->irq_cleanup = NULL;
3234 }
3199 3235
3200 /* 3236 /*
3201 * Wait until we know that we are out of any interrupt 3237 * Wait until we know that we are out of any interrupt
@@ -3208,18 +3244,21 @@ static int try_smi_init(struct smi_info *new_smi)
3208 if (new_smi->handlers) 3244 if (new_smi->handlers)
3209 new_smi->handlers->cleanup(new_smi->si_sm); 3245 new_smi->handlers->cleanup(new_smi->si_sm);
3210 kfree(new_smi->si_sm); 3246 kfree(new_smi->si_sm);
3247 new_smi->si_sm = NULL;
3211 } 3248 }
3212 if (new_smi->addr_source_cleanup) 3249 if (new_smi->addr_source_cleanup) {
3213 new_smi->addr_source_cleanup(new_smi); 3250 new_smi->addr_source_cleanup(new_smi);
3214 if (new_smi->io_cleanup) 3251 new_smi->addr_source_cleanup = NULL;
3252 }
3253 if (new_smi->io_cleanup) {
3215 new_smi->io_cleanup(new_smi); 3254 new_smi->io_cleanup(new_smi);
3255 new_smi->io_cleanup = NULL;
3256 }
3216 3257
3217 if (new_smi->dev_registered) 3258 if (new_smi->dev_registered) {
3218 platform_device_unregister(new_smi->pdev); 3259 platform_device_unregister(new_smi->pdev);
3219 3260 new_smi->dev_registered = 0;
3220 kfree(new_smi); 3261 }
3221
3222 mutex_unlock(&smi_infos_lock);
3223 3262
3224 return rv; 3263 return rv;
3225} 3264}
@@ -3229,6 +3268,8 @@ static __devinit int init_ipmi_si(void)
3229 int i; 3268 int i;
3230 char *str; 3269 char *str;
3231 int rv; 3270 int rv;
3271 struct smi_info *e;
3272 enum ipmi_addr_src type = SI_INVALID;
3232 3273
3233 if (initialized) 3274 if (initialized)
3234 return 0; 3275 return 0;
@@ -3237,9 +3278,7 @@ static __devinit int init_ipmi_si(void)
3237 /* Register the device drivers. */ 3278 /* Register the device drivers. */
3238 rv = driver_register(&ipmi_driver.driver); 3279 rv = driver_register(&ipmi_driver.driver);
3239 if (rv) { 3280 if (rv) {
3240 printk(KERN_ERR 3281 printk(KERN_ERR PFX "Unable to register driver: %d\n", rv);
3241 "init_ipmi_si: Unable to register driver: %d\n",
3242 rv);
3243 return rv; 3282 return rv;
3244 } 3283 }
3245 3284
@@ -3263,38 +3302,81 @@ static __devinit int init_ipmi_si(void)
3263 3302
3264 hardcode_find_bmc(); 3303 hardcode_find_bmc();
3265 3304
3266#ifdef CONFIG_DMI 3305 /* If the user gave us a device, they presumably want us to use it */
3267 dmi_find_bmc(); 3306 mutex_lock(&smi_infos_lock);
3268#endif 3307 if (!list_empty(&smi_infos)) {
3308 mutex_unlock(&smi_infos_lock);
3309 return 0;
3310 }
3311 mutex_unlock(&smi_infos_lock);
3269 3312
3270#ifdef CONFIG_ACPI 3313#ifdef CONFIG_PCI
3271 spmi_find_bmc(); 3314 rv = pci_register_driver(&ipmi_pci_driver);
3315 if (rv)
3316 printk(KERN_ERR PFX "Unable to register PCI driver: %d\n", rv);
3272#endif 3317#endif
3318
3273#ifdef CONFIG_ACPI 3319#ifdef CONFIG_ACPI
3274 pnp_register_driver(&ipmi_pnp_driver); 3320 pnp_register_driver(&ipmi_pnp_driver);
3275#endif 3321#endif
3276 3322
3277#ifdef CONFIG_PCI 3323#ifdef CONFIG_DMI
3278 rv = pci_register_driver(&ipmi_pci_driver); 3324 dmi_find_bmc();
3279 if (rv) 3325#endif
3280 printk(KERN_ERR 3326
3281 "init_ipmi_si: Unable to register PCI driver: %d\n", 3327#ifdef CONFIG_ACPI
3282 rv); 3328 spmi_find_bmc();
3283#endif 3329#endif
3284 3330
3285#ifdef CONFIG_PPC_OF 3331#ifdef CONFIG_PPC_OF
3286 of_register_platform_driver(&ipmi_of_platform_driver); 3332 of_register_platform_driver(&ipmi_of_platform_driver);
3287#endif 3333#endif
3288 3334
3335 /* We prefer devices with interrupts, but in the case of a machine
3336 with multiple BMCs we assume that there will be several instances
3337 of a given type so if we succeed in registering a type then also
3338 try to register everything else of the same type */
3339
3340 mutex_lock(&smi_infos_lock);
3341 list_for_each_entry(e, &smi_infos, link) {
3342 /* Try to register a device if it has an IRQ and we either
3343 haven't successfully registered a device yet or this
3344 device has the same type as one we successfully registered */
3345 if (e->irq && (!type || e->addr_source == type)) {
3346 if (!try_smi_init(e)) {
3347 type = e->addr_source;
3348 }
3349 }
3350 }
3351
3352 /* type will only have been set if we successfully registered an si */
3353 if (type) {
3354 mutex_unlock(&smi_infos_lock);
3355 return 0;
3356 }
3357
3358 /* Fall back to the preferred device */
3359
3360 list_for_each_entry(e, &smi_infos, link) {
3361 if (!e->irq && (!type || e->addr_source == type)) {
3362 if (!try_smi_init(e)) {
3363 type = e->addr_source;
3364 }
3365 }
3366 }
3367 mutex_unlock(&smi_infos_lock);
3368
3369 if (type)
3370 return 0;
3371
3289 if (si_trydefaults) { 3372 if (si_trydefaults) {
3290 mutex_lock(&smi_infos_lock); 3373 mutex_lock(&smi_infos_lock);
3291 if (list_empty(&smi_infos)) { 3374 if (list_empty(&smi_infos)) {
3292 /* No BMC was found, try defaults. */ 3375 /* No BMC was found, try defaults. */
3293 mutex_unlock(&smi_infos_lock); 3376 mutex_unlock(&smi_infos_lock);
3294 default_find_bmc(); 3377 default_find_bmc();
3295 } else { 3378 } else
3296 mutex_unlock(&smi_infos_lock); 3379 mutex_unlock(&smi_infos_lock);
3297 }
3298 } 3380 }
3299 3381
3300 mutex_lock(&smi_infos_lock); 3382 mutex_lock(&smi_infos_lock);
@@ -3308,8 +3390,8 @@ static __devinit int init_ipmi_si(void)
3308 of_unregister_platform_driver(&ipmi_of_platform_driver); 3390 of_unregister_platform_driver(&ipmi_of_platform_driver);
3309#endif 3391#endif
3310 driver_unregister(&ipmi_driver.driver); 3392 driver_unregister(&ipmi_driver.driver);
3311 printk(KERN_WARNING 3393 printk(KERN_WARNING PFX
3312 "ipmi_si: Unable to find any System Interface(s)\n"); 3394 "Unable to find any System Interface(s)\n");
3313 return -ENODEV; 3395 return -ENODEV;
3314 } else { 3396 } else {
3315 mutex_unlock(&smi_infos_lock); 3397 mutex_unlock(&smi_infos_lock);
@@ -3320,7 +3402,7 @@ module_init(init_ipmi_si);
3320 3402
3321static void cleanup_one_si(struct smi_info *to_clean) 3403static void cleanup_one_si(struct smi_info *to_clean)
3322{ 3404{
3323 int rv; 3405 int rv = 0;
3324 unsigned long flags; 3406 unsigned long flags;
3325 3407
3326 if (!to_clean) 3408 if (!to_clean)
@@ -3364,14 +3446,16 @@ static void cleanup_one_si(struct smi_info *to_clean)
3364 schedule_timeout_uninterruptible(1); 3446 schedule_timeout_uninterruptible(1);
3365 } 3447 }
3366 3448
3367 rv = ipmi_unregister_smi(to_clean->intf); 3449 if (to_clean->intf)
3450 rv = ipmi_unregister_smi(to_clean->intf);
3451
3368 if (rv) { 3452 if (rv) {
3369 printk(KERN_ERR 3453 printk(KERN_ERR PFX "Unable to unregister device: errno=%d\n",
3370 "ipmi_si: Unable to unregister device: errno=%d\n",
3371 rv); 3454 rv);
3372 } 3455 }
3373 3456
3374 to_clean->handlers->cleanup(to_clean->si_sm); 3457 if (to_clean->handlers)
3458 to_clean->handlers->cleanup(to_clean->si_sm);
3375 3459
3376 kfree(to_clean->si_sm); 3460 kfree(to_clean->si_sm);
3377 3461
diff --git a/drivers/char/n_gsm.c b/drivers/char/n_gsm.c
index c4161d5e053d..e4089c432f15 100644
--- a/drivers/char/n_gsm.c
+++ b/drivers/char/n_gsm.c
@@ -904,9 +904,7 @@ static void gsm_dlci_data_sweep(struct gsm_mux *gsm)
904 int len; 904 int len;
905 /* Priority ordering: We should do priority with RR of the groups */ 905 /* Priority ordering: We should do priority with RR of the groups */
906 int i = 1; 906 int i = 1;
907 unsigned long flags;
908 907
909 spin_lock_irqsave(&gsm->tx_lock, flags);
910 while (i < NUM_DLCI) { 908 while (i < NUM_DLCI) {
911 struct gsm_dlci *dlci; 909 struct gsm_dlci *dlci;
912 910
@@ -927,7 +925,6 @@ static void gsm_dlci_data_sweep(struct gsm_mux *gsm)
927 if (len == 0) 925 if (len == 0)
928 i++; 926 i++;
929 } 927 }
930 spin_unlock_irqrestore(&gsm->tx_lock, flags);
931} 928}
932 929
933/** 930/**
@@ -2230,12 +2227,16 @@ static int gsmld_open(struct tty_struct *tty)
2230static void gsmld_write_wakeup(struct tty_struct *tty) 2227static void gsmld_write_wakeup(struct tty_struct *tty)
2231{ 2228{
2232 struct gsm_mux *gsm = tty->disc_data; 2229 struct gsm_mux *gsm = tty->disc_data;
2230 unsigned long flags;
2233 2231
2234 /* Queue poll */ 2232 /* Queue poll */
2235 clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); 2233 clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
2236 gsm_data_kick(gsm); 2234 gsm_data_kick(gsm);
2237 if (gsm->tx_bytes < TX_THRESH_LO) 2235 if (gsm->tx_bytes < TX_THRESH_LO) {
2236 spin_lock_irqsave(&gsm->tx_lock, flags);
2238 gsm_dlci_data_sweep(gsm); 2237 gsm_dlci_data_sweep(gsm);
2238 spin_unlock_irqrestore(&gsm->tx_lock, flags);
2239 }
2239} 2240}
2240 2241
2241/** 2242/**
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
index fdd37543aa79..02abfddce45a 100644
--- a/drivers/char/ppdev.c
+++ b/drivers/char/ppdev.c
@@ -287,12 +287,10 @@ static int register_device (int minor, struct pp_struct *pp)
287 char *name; 287 char *name;
288 int fl; 288 int fl;
289 289
290 name = kmalloc (strlen (CHRDEV) + 3, GFP_KERNEL); 290 name = kasprintf(GFP_KERNEL, CHRDEV "%x", minor);
291 if (name == NULL) 291 if (name == NULL)
292 return -ENOMEM; 292 return -ENOMEM;
293 293
294 sprintf (name, CHRDEV "%x", minor);
295
296 port = parport_find_number (minor); 294 port = parport_find_number (minor);
297 if (!port) { 295 if (!port) {
298 printk (KERN_WARNING "%s: no associated port!\n", name); 296 printk (KERN_WARNING "%s: no associated port!\n", name);
diff --git a/drivers/char/ps3flash.c b/drivers/char/ps3flash.c
index 606048b72bcf..85c004a518ee 100644
--- a/drivers/char/ps3flash.c
+++ b/drivers/char/ps3flash.c
@@ -305,8 +305,7 @@ static int ps3flash_flush(struct file *file, fl_owner_t id)
305 return ps3flash_writeback(ps3flash_dev); 305 return ps3flash_writeback(ps3flash_dev);
306} 306}
307 307
308static int ps3flash_fsync(struct file *file, struct dentry *dentry, 308static int ps3flash_fsync(struct file *file, int datasync)
309 int datasync)
310{ 309{
311 return ps3flash_writeback(ps3flash_dev); 310 return ps3flash_writeback(ps3flash_dev);
312} 311}
diff --git a/drivers/char/ramoops.c b/drivers/char/ramoops.c
new file mode 100644
index 000000000000..74f00b5ffa36
--- /dev/null
+++ b/drivers/char/ramoops.c
@@ -0,0 +1,162 @@
1/*
2 * RAM Oops/Panic logger
3 *
4 * Copyright (C) 2010 Marco Stornelli <marco.stornelli@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 *
20 */
21
22#include <linux/kernel.h>
23#include <linux/module.h>
24#include <linux/kmsg_dump.h>
25#include <linux/time.h>
26#include <linux/io.h>
27#include <linux/ioport.h>
28
29#define RAMOOPS_KERNMSG_HDR "===="
30#define RAMOOPS_HEADER_SIZE (5 + sizeof(struct timeval))
31
32#define RECORD_SIZE 4096
33
34static ulong mem_address;
35module_param(mem_address, ulong, 0400);
36MODULE_PARM_DESC(mem_address,
37 "start of reserved RAM used to store oops/panic logs");
38
39static ulong mem_size;
40module_param(mem_size, ulong, 0400);
41MODULE_PARM_DESC(mem_size,
42 "size of reserved RAM used to store oops/panic logs");
43
44static int dump_oops = 1;
45module_param(dump_oops, int, 0600);
46MODULE_PARM_DESC(dump_oops,
47 "set to 1 to dump oopses, 0 to only dump panics (default 1)");
48
49static struct ramoops_context {
50 struct kmsg_dumper dump;
51 void *virt_addr;
52 phys_addr_t phys_addr;
53 unsigned long size;
54 int count;
55 int max_count;
56} oops_cxt;
57
58static void ramoops_do_dump(struct kmsg_dumper *dumper,
59 enum kmsg_dump_reason reason, const char *s1, unsigned long l1,
60 const char *s2, unsigned long l2)
61{
62 struct ramoops_context *cxt = container_of(dumper,
63 struct ramoops_context, dump);
64 unsigned long s1_start, s2_start;
65 unsigned long l1_cpy, l2_cpy;
66 int res;
67 char *buf;
68 struct timeval timestamp;
69
70 /* Only dump oopses if dump_oops is set */
71 if (reason == KMSG_DUMP_OOPS && !dump_oops)
72 return;
73
74 buf = (char *)(cxt->virt_addr + (cxt->count * RECORD_SIZE));
75 memset(buf, '\0', RECORD_SIZE);
76 res = sprintf(buf, "%s", RAMOOPS_KERNMSG_HDR);
77 buf += res;
78 do_gettimeofday(&timestamp);
79 res = sprintf(buf, "%lu.%lu\n", (long)timestamp.tv_sec, (long)timestamp.tv_usec);
80 buf += res;
81
82 l2_cpy = min(l2, (unsigned long)(RECORD_SIZE - RAMOOPS_HEADER_SIZE));
83 l1_cpy = min(l1, (unsigned long)(RECORD_SIZE - RAMOOPS_HEADER_SIZE) - l2_cpy);
84
85 s2_start = l2 - l2_cpy;
86 s1_start = l1 - l1_cpy;
87
88 memcpy(buf, s1 + s1_start, l1_cpy);
89 memcpy(buf + l1_cpy, s2 + s2_start, l2_cpy);
90
91 cxt->count = (cxt->count + 1) % cxt->max_count;
92}
93
94static int __init ramoops_init(void)
95{
96 struct ramoops_context *cxt = &oops_cxt;
97 int err = -EINVAL;
98
99 if (!mem_size) {
100 printk(KERN_ERR "ramoops: invalid size specification");
101 goto fail3;
102 }
103
104 rounddown_pow_of_two(mem_size);
105
106 if (mem_size < RECORD_SIZE) {
107 printk(KERN_ERR "ramoops: size too small");
108 goto fail3;
109 }
110
111 cxt->max_count = mem_size / RECORD_SIZE;
112 cxt->count = 0;
113 cxt->size = mem_size;
114 cxt->phys_addr = mem_address;
115
116 if (!request_mem_region(cxt->phys_addr, cxt->size, "ramoops")) {
117 printk(KERN_ERR "ramoops: request mem region failed");
118 err = -EINVAL;
119 goto fail3;
120 }
121
122 cxt->virt_addr = ioremap(cxt->phys_addr, cxt->size);
123 if (!cxt->virt_addr) {
124 printk(KERN_ERR "ramoops: ioremap failed");
125 goto fail2;
126 }
127
128 cxt->dump.dump = ramoops_do_dump;
129 err = kmsg_dump_register(&cxt->dump);
130 if (err) {
131 printk(KERN_ERR "ramoops: registering kmsg dumper failed");
132 goto fail1;
133 }
134
135 return 0;
136
137fail1:
138 iounmap(cxt->virt_addr);
139fail2:
140 release_mem_region(cxt->phys_addr, cxt->size);
141fail3:
142 return err;
143}
144
145static void __exit ramoops_exit(void)
146{
147 struct ramoops_context *cxt = &oops_cxt;
148
149 if (kmsg_dump_unregister(&cxt->dump) < 0)
150 printk(KERN_WARNING "ramoops: could not unregister kmsg_dumper");
151
152 iounmap(cxt->virt_addr);
153 release_mem_region(cxt->phys_addr, cxt->size);
154}
155
156
157module_init(ramoops_init);
158module_exit(ramoops_exit);
159
160MODULE_LICENSE("GPL");
161MODULE_AUTHOR("Marco Stornelli <marco.stornelli@gmail.com>");
162MODULE_DESCRIPTION("RAM Oops/Panic logger/driver");
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 8c99bf1b5e9f..942a9826bd23 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -529,6 +529,10 @@ static bool will_write_block(struct port *port)
529{ 529{
530 bool ret; 530 bool ret;
531 531
532 if (!port->guest_connected) {
533 /* Port got hot-unplugged. Let's exit. */
534 return false;
535 }
532 if (!port->host_connected) 536 if (!port->host_connected)
533 return true; 537 return true;
534 538
@@ -1099,6 +1103,13 @@ static int remove_port(struct port *port)
1099{ 1103{
1100 struct port_buffer *buf; 1104 struct port_buffer *buf;
1101 1105
1106 if (port->guest_connected) {
1107 port->guest_connected = false;
1108 port->host_connected = false;
1109 wake_up_interruptible(&port->waitqueue);
1110 send_control_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 0);
1111 }
1112
1102 spin_lock_irq(&port->portdev->ports_lock); 1113 spin_lock_irq(&port->portdev->ports_lock);
1103 list_del(&port->list); 1114 list_del(&port->list);
1104 spin_unlock_irq(&port->portdev->ports_lock); 1115 spin_unlock_irq(&port->portdev->ports_lock);
@@ -1120,9 +1131,6 @@ static int remove_port(struct port *port)
1120 hvc_remove(port->cons.hvc); 1131 hvc_remove(port->cons.hvc);
1121#endif 1132#endif
1122 } 1133 }
1123 if (port->guest_connected)
1124 send_control_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 0);
1125
1126 sysfs_remove_group(&port->dev->kobj, &port_attribute_group); 1134 sysfs_remove_group(&port->dev->kobj, &port_attribute_group);
1127 device_destroy(pdrvdata.class, port->dev->devt); 1135 device_destroy(pdrvdata.class, port->dev->devt);
1128 cdev_del(&port->cdev); 1136 cdev_del(&port->cdev);
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index bd1d1164fec5..7cdb6ee569cd 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -3967,13 +3967,9 @@ static int con_font_set(struct vc_data *vc, struct console_font_op *op)
3967 font.charcount = op->charcount; 3967 font.charcount = op->charcount;
3968 font.height = op->height; 3968 font.height = op->height;
3969 font.width = op->width; 3969 font.width = op->width;
3970 font.data = kmalloc(size, GFP_KERNEL); 3970 font.data = memdup_user(op->data, size);
3971 if (!font.data) 3971 if (IS_ERR(font.data))
3972 return -ENOMEM; 3972 return PTR_ERR(font.data);
3973 if (copy_from_user(font.data, op->data, size)) {
3974 kfree(font.data);
3975 return -EFAULT;
3976 }
3977 acquire_console_sem(); 3973 acquire_console_sem();
3978 if (vc->vc_sw->con_font_set) 3974 if (vc->vc_sw->con_font_set)
3979 rc = vc->vc_sw->con_font_set(vc, &font, op->flags); 3975 rc = vc->vc_sw->con_font_set(vc, &font, op->flags);
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index 6aa10284104a..cb19dbc52136 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -1303,7 +1303,9 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
1303 if (!perm) 1303 if (!perm)
1304 goto eperm; 1304 goto eperm;
1305 ret = copy_from_user(&ui, up, sizeof(struct unimapinit)); 1305 ret = copy_from_user(&ui, up, sizeof(struct unimapinit));
1306 if (!ret) 1306 if (ret)
1307 ret = -EFAULT;
1308 else
1307 con_clear_unimap(vc, &ui); 1309 con_clear_unimap(vc, &ui);
1308 break; 1310 break;
1309 } 1311 }
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index f6677cb19789..f3d3898898ed 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -412,18 +412,10 @@ static cycle_t sh_cmt_clocksource_read(struct clocksource *cs)
412static int sh_cmt_clocksource_enable(struct clocksource *cs) 412static int sh_cmt_clocksource_enable(struct clocksource *cs)
413{ 413{
414 struct sh_cmt_priv *p = cs_to_sh_cmt(cs); 414 struct sh_cmt_priv *p = cs_to_sh_cmt(cs);
415 int ret;
416 415
417 p->total_cycles = 0; 416 p->total_cycles = 0;
418 417
419 ret = sh_cmt_start(p, FLAG_CLOCKSOURCE); 418 return sh_cmt_start(p, FLAG_CLOCKSOURCE);
420 if (ret)
421 return ret;
422
423 /* TODO: calculate good shift from rate and counter bit width */
424 cs->shift = 0;
425 cs->mult = clocksource_hz2mult(p->rate, cs->shift);
426 return 0;
427} 419}
428 420
429static void sh_cmt_clocksource_disable(struct clocksource *cs) 421static void sh_cmt_clocksource_disable(struct clocksource *cs)
@@ -450,8 +442,20 @@ static int sh_cmt_register_clocksource(struct sh_cmt_priv *p,
450 cs->resume = sh_cmt_clocksource_resume; 442 cs->resume = sh_cmt_clocksource_resume;
451 cs->mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8); 443 cs->mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8);
452 cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; 444 cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
445
446 /* clk_get_rate() needs an enabled clock */
447 clk_enable(p->clk);
448 p->rate = clk_get_rate(p->clk) / (p->width == 16) ? 512 : 8;
449 clk_disable(p->clk);
450
451 /* TODO: calculate good shift from rate and counter bit width */
452 cs->shift = 10;
453 cs->mult = clocksource_hz2mult(p->rate, cs->shift);
454
453 dev_info(&p->pdev->dev, "used as clock source\n"); 455 dev_info(&p->pdev->dev, "used as clock source\n");
456
454 clocksource_register(cs); 457 clocksource_register(cs);
458
455 return 0; 459 return 0;
456} 460}
457 461
diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c
index 8e44e14ec4c2..de715901b82a 100644
--- a/drivers/clocksource/sh_tmu.c
+++ b/drivers/clocksource/sh_tmu.c
@@ -199,16 +199,8 @@ static cycle_t sh_tmu_clocksource_read(struct clocksource *cs)
199static int sh_tmu_clocksource_enable(struct clocksource *cs) 199static int sh_tmu_clocksource_enable(struct clocksource *cs)
200{ 200{
201 struct sh_tmu_priv *p = cs_to_sh_tmu(cs); 201 struct sh_tmu_priv *p = cs_to_sh_tmu(cs);
202 int ret;
203
204 ret = sh_tmu_enable(p);
205 if (ret)
206 return ret;
207 202
208 /* TODO: calculate good shift from rate and counter bit width */ 203 return sh_tmu_enable(p);
209 cs->shift = 10;
210 cs->mult = clocksource_hz2mult(p->rate, cs->shift);
211 return 0;
212} 204}
213 205
214static void sh_tmu_clocksource_disable(struct clocksource *cs) 206static void sh_tmu_clocksource_disable(struct clocksource *cs)
@@ -228,6 +220,16 @@ static int sh_tmu_register_clocksource(struct sh_tmu_priv *p,
228 cs->disable = sh_tmu_clocksource_disable; 220 cs->disable = sh_tmu_clocksource_disable;
229 cs->mask = CLOCKSOURCE_MASK(32); 221 cs->mask = CLOCKSOURCE_MASK(32);
230 cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; 222 cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
223
224 /* clk_get_rate() needs an enabled clock */
225 clk_enable(p->clk);
226 /* channel will be configured at parent clock / 4 */
227 p->rate = clk_get_rate(p->clk) / 4;
228 clk_disable(p->clk);
229 /* TODO: calculate good shift from rate and counter bit width */
230 cs->shift = 10;
231 cs->mult = clocksource_hz2mult(p->rate, cs->shift);
232
231 dev_info(&p->pdev->dev, "used as clock source\n"); 233 dev_info(&p->pdev->dev, "used as clock source\n");
232 clocksource_register(cs); 234 clocksource_register(cs);
233 return 0; 235 return 0;
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index 12fdd3987a36..199488576a05 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -156,7 +156,7 @@ int cpuidle_enable_device(struct cpuidle_device *dev)
156 156
157 if (dev->enabled) 157 if (dev->enabled)
158 return 0; 158 return 0;
159 if (!cpuidle_curr_driver || !cpuidle_curr_governor) 159 if (!cpuidle_get_driver() || !cpuidle_curr_governor)
160 return -EIO; 160 return -EIO;
161 if (!dev->state_count) 161 if (!dev->state_count)
162 return -EINVAL; 162 return -EINVAL;
@@ -207,7 +207,7 @@ void cpuidle_disable_device(struct cpuidle_device *dev)
207{ 207{
208 if (!dev->enabled) 208 if (!dev->enabled)
209 return; 209 return;
210 if (!cpuidle_curr_driver || !cpuidle_curr_governor) 210 if (!cpuidle_get_driver() || !cpuidle_curr_governor)
211 return; 211 return;
212 212
213 dev->enabled = 0; 213 dev->enabled = 0;
@@ -271,10 +271,11 @@ static int __cpuidle_register_device(struct cpuidle_device *dev)
271{ 271{
272 int ret; 272 int ret;
273 struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu); 273 struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu);
274 struct cpuidle_driver *cpuidle_driver = cpuidle_get_driver();
274 275
275 if (!sys_dev) 276 if (!sys_dev)
276 return -EINVAL; 277 return -EINVAL;
277 if (!try_module_get(cpuidle_curr_driver->owner)) 278 if (!try_module_get(cpuidle_driver->owner))
278 return -EINVAL; 279 return -EINVAL;
279 280
280 init_completion(&dev->kobj_unregister); 281 init_completion(&dev->kobj_unregister);
@@ -284,7 +285,7 @@ static int __cpuidle_register_device(struct cpuidle_device *dev)
284 per_cpu(cpuidle_devices, dev->cpu) = dev; 285 per_cpu(cpuidle_devices, dev->cpu) = dev;
285 list_add(&dev->device_list, &cpuidle_detected_devices); 286 list_add(&dev->device_list, &cpuidle_detected_devices);
286 if ((ret = cpuidle_add_sysfs(sys_dev))) { 287 if ((ret = cpuidle_add_sysfs(sys_dev))) {
287 module_put(cpuidle_curr_driver->owner); 288 module_put(cpuidle_driver->owner);
288 return ret; 289 return ret;
289 } 290 }
290 291
@@ -325,6 +326,7 @@ EXPORT_SYMBOL_GPL(cpuidle_register_device);
325void cpuidle_unregister_device(struct cpuidle_device *dev) 326void cpuidle_unregister_device(struct cpuidle_device *dev)
326{ 327{
327 struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu); 328 struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu);
329 struct cpuidle_driver *cpuidle_driver = cpuidle_get_driver();
328 330
329 if (dev->registered == 0) 331 if (dev->registered == 0)
330 return; 332 return;
@@ -340,7 +342,7 @@ void cpuidle_unregister_device(struct cpuidle_device *dev)
340 342
341 cpuidle_resume_and_unlock(); 343 cpuidle_resume_and_unlock();
342 344
343 module_put(cpuidle_curr_driver->owner); 345 module_put(cpuidle_driver->owner);
344} 346}
345 347
346EXPORT_SYMBOL_GPL(cpuidle_unregister_device); 348EXPORT_SYMBOL_GPL(cpuidle_unregister_device);
diff --git a/drivers/cpuidle/cpuidle.h b/drivers/cpuidle/cpuidle.h
index 9476ba33ee2c..33e50d556f17 100644
--- a/drivers/cpuidle/cpuidle.h
+++ b/drivers/cpuidle/cpuidle.h
@@ -9,7 +9,6 @@
9 9
10/* For internal use only */ 10/* For internal use only */
11extern struct cpuidle_governor *cpuidle_curr_governor; 11extern struct cpuidle_governor *cpuidle_curr_governor;
12extern struct cpuidle_driver *cpuidle_curr_driver;
13extern struct list_head cpuidle_governors; 12extern struct list_head cpuidle_governors;
14extern struct list_head cpuidle_detected_devices; 13extern struct list_head cpuidle_detected_devices;
15extern struct mutex cpuidle_lock; 14extern struct mutex cpuidle_lock;
diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c
index 2257004fe33d..fd1601e3d125 100644
--- a/drivers/cpuidle/driver.c
+++ b/drivers/cpuidle/driver.c
@@ -14,7 +14,7 @@
14 14
15#include "cpuidle.h" 15#include "cpuidle.h"
16 16
17struct cpuidle_driver *cpuidle_curr_driver; 17static struct cpuidle_driver *cpuidle_curr_driver;
18DEFINE_SPINLOCK(cpuidle_driver_lock); 18DEFINE_SPINLOCK(cpuidle_driver_lock);
19 19
20/** 20/**
@@ -40,13 +40,25 @@ int cpuidle_register_driver(struct cpuidle_driver *drv)
40EXPORT_SYMBOL_GPL(cpuidle_register_driver); 40EXPORT_SYMBOL_GPL(cpuidle_register_driver);
41 41
42/** 42/**
43 * cpuidle_get_driver - return the current driver
44 */
45struct cpuidle_driver *cpuidle_get_driver(void)
46{
47 return cpuidle_curr_driver;
48}
49EXPORT_SYMBOL_GPL(cpuidle_get_driver);
50
51/**
43 * cpuidle_unregister_driver - unregisters a driver 52 * cpuidle_unregister_driver - unregisters a driver
44 * @drv: the driver 53 * @drv: the driver
45 */ 54 */
46void cpuidle_unregister_driver(struct cpuidle_driver *drv) 55void cpuidle_unregister_driver(struct cpuidle_driver *drv)
47{ 56{
48 if (!drv) 57 if (drv != cpuidle_curr_driver) {
58 WARN(1, "invalid cpuidle_unregister_driver(%s)\n",
59 drv->name);
49 return; 60 return;
61 }
50 62
51 spin_lock(&cpuidle_driver_lock); 63 spin_lock(&cpuidle_driver_lock);
52 cpuidle_curr_driver = NULL; 64 cpuidle_curr_driver = NULL;
diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c
index 0ba9c8b8ee74..0310ffaec9df 100644
--- a/drivers/cpuidle/sysfs.c
+++ b/drivers/cpuidle/sysfs.c
@@ -47,10 +47,11 @@ static ssize_t show_current_driver(struct sysdev_class *class,
47 char *buf) 47 char *buf)
48{ 48{
49 ssize_t ret; 49 ssize_t ret;
50 struct cpuidle_driver *cpuidle_driver = cpuidle_get_driver();
50 51
51 spin_lock(&cpuidle_driver_lock); 52 spin_lock(&cpuidle_driver_lock);
52 if (cpuidle_curr_driver) 53 if (cpuidle_driver)
53 ret = sprintf(buf, "%s\n", cpuidle_curr_driver->name); 54 ret = sprintf(buf, "%s\n", cpuidle_driver->name);
54 else 55 else
55 ret = sprintf(buf, "none\n"); 56 ret = sprintf(buf, "none\n");
56 spin_unlock(&cpuidle_driver_lock); 57 spin_unlock(&cpuidle_driver_lock);
diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c
index 9d65b371de64..983530ba04a7 100644
--- a/drivers/crypto/amcc/crypto4xx_core.c
+++ b/drivers/crypto/amcc/crypto4xx_core.c
@@ -1158,7 +1158,7 @@ static int __init crypto4xx_probe(struct of_device *ofdev,
1158 struct device *dev = &ofdev->dev; 1158 struct device *dev = &ofdev->dev;
1159 struct crypto4xx_core_device *core_dev; 1159 struct crypto4xx_core_device *core_dev;
1160 1160
1161 rc = of_address_to_resource(ofdev->node, 0, &res); 1161 rc = of_address_to_resource(ofdev->dev.of_node, 0, &res);
1162 if (rc) 1162 if (rc)
1163 return -ENODEV; 1163 return -ENODEV;
1164 1164
@@ -1215,13 +1215,13 @@ static int __init crypto4xx_probe(struct of_device *ofdev,
1215 (unsigned long) dev); 1215 (unsigned long) dev);
1216 1216
1217 /* Register for Crypto isr, Crypto Engine IRQ */ 1217 /* Register for Crypto isr, Crypto Engine IRQ */
1218 core_dev->irq = irq_of_parse_and_map(ofdev->node, 0); 1218 core_dev->irq = irq_of_parse_and_map(ofdev->dev.of_node, 0);
1219 rc = request_irq(core_dev->irq, crypto4xx_ce_interrupt_handler, 0, 1219 rc = request_irq(core_dev->irq, crypto4xx_ce_interrupt_handler, 0,
1220 core_dev->dev->name, dev); 1220 core_dev->dev->name, dev);
1221 if (rc) 1221 if (rc)
1222 goto err_request_irq; 1222 goto err_request_irq;
1223 1223
1224 core_dev->dev->ce_base = of_iomap(ofdev->node, 0); 1224 core_dev->dev->ce_base = of_iomap(ofdev->dev.of_node, 0);
1225 if (!core_dev->dev->ce_base) { 1225 if (!core_dev->dev->ce_base) {
1226 dev_err(dev, "failed to of_iomap\n"); 1226 dev_err(dev, "failed to of_iomap\n");
1227 goto err_iomap; 1227 goto err_iomap;
diff --git a/drivers/crypto/n2_core.c b/drivers/crypto/n2_core.c
index 8566be832f51..23163fda5035 100644
--- a/drivers/crypto/n2_core.c
+++ b/drivers/crypto/n2_core.c
@@ -251,16 +251,10 @@ static void n2_base_ctx_init(struct n2_base_ctx *ctx)
251struct n2_hash_ctx { 251struct n2_hash_ctx {
252 struct n2_base_ctx base; 252 struct n2_base_ctx base;
253 253
254 struct crypto_ahash *fallback; 254 struct crypto_ahash *fallback_tfm;
255};
255 256
256 /* These next three members must match the layout created by 257struct n2_hash_req_ctx {
257 * crypto_init_shash_ops_async. This allows us to properly
258 * plumb requests we can't do in hardware down to the fallback
259 * operation, providing all of the data structures and layouts
260 * expected by those paths.
261 */
262 struct ahash_request fallback_req;
263 struct shash_desc fallback_desc;
264 union { 258 union {
265 struct md5_state md5; 259 struct md5_state md5;
266 struct sha1_state sha1; 260 struct sha1_state sha1;
@@ -269,56 +263,62 @@ struct n2_hash_ctx {
269 263
270 unsigned char hash_key[64]; 264 unsigned char hash_key[64];
271 unsigned char keyed_zero_hash[32]; 265 unsigned char keyed_zero_hash[32];
266
267 struct ahash_request fallback_req;
272}; 268};
273 269
274static int n2_hash_async_init(struct ahash_request *req) 270static int n2_hash_async_init(struct ahash_request *req)
275{ 271{
272 struct n2_hash_req_ctx *rctx = ahash_request_ctx(req);
276 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 273 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
277 struct n2_hash_ctx *ctx = crypto_ahash_ctx(tfm); 274 struct n2_hash_ctx *ctx = crypto_ahash_ctx(tfm);
278 275
279 ctx->fallback_req.base.tfm = crypto_ahash_tfm(ctx->fallback); 276 ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
280 ctx->fallback_req.base.flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP; 277 rctx->fallback_req.base.flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP;
281 278
282 return crypto_ahash_init(&ctx->fallback_req); 279 return crypto_ahash_init(&rctx->fallback_req);
283} 280}
284 281
285static int n2_hash_async_update(struct ahash_request *req) 282static int n2_hash_async_update(struct ahash_request *req)
286{ 283{
284 struct n2_hash_req_ctx *rctx = ahash_request_ctx(req);
287 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 285 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
288 struct n2_hash_ctx *ctx = crypto_ahash_ctx(tfm); 286 struct n2_hash_ctx *ctx = crypto_ahash_ctx(tfm);
289 287
290 ctx->fallback_req.base.tfm = crypto_ahash_tfm(ctx->fallback); 288 ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
291 ctx->fallback_req.base.flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP; 289 rctx->fallback_req.base.flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP;
292 ctx->fallback_req.nbytes = req->nbytes; 290 rctx->fallback_req.nbytes = req->nbytes;
293 ctx->fallback_req.src = req->src; 291 rctx->fallback_req.src = req->src;
294 292
295 return crypto_ahash_update(&ctx->fallback_req); 293 return crypto_ahash_update(&rctx->fallback_req);
296} 294}
297 295
298static int n2_hash_async_final(struct ahash_request *req) 296static int n2_hash_async_final(struct ahash_request *req)
299{ 297{
298 struct n2_hash_req_ctx *rctx = ahash_request_ctx(req);
300 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 299 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
301 struct n2_hash_ctx *ctx = crypto_ahash_ctx(tfm); 300 struct n2_hash_ctx *ctx = crypto_ahash_ctx(tfm);
302 301
303 ctx->fallback_req.base.tfm = crypto_ahash_tfm(ctx->fallback); 302 ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
304 ctx->fallback_req.base.flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP; 303 rctx->fallback_req.base.flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP;
305 ctx->fallback_req.result = req->result; 304 rctx->fallback_req.result = req->result;
306 305
307 return crypto_ahash_final(&ctx->fallback_req); 306 return crypto_ahash_final(&rctx->fallback_req);
308} 307}
309 308
310static int n2_hash_async_finup(struct ahash_request *req) 309static int n2_hash_async_finup(struct ahash_request *req)
311{ 310{
311 struct n2_hash_req_ctx *rctx = ahash_request_ctx(req);
312 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 312 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
313 struct n2_hash_ctx *ctx = crypto_ahash_ctx(tfm); 313 struct n2_hash_ctx *ctx = crypto_ahash_ctx(tfm);
314 314
315 ctx->fallback_req.base.tfm = crypto_ahash_tfm(ctx->fallback); 315 ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
316 ctx->fallback_req.base.flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP; 316 rctx->fallback_req.base.flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP;
317 ctx->fallback_req.nbytes = req->nbytes; 317 rctx->fallback_req.nbytes = req->nbytes;
318 ctx->fallback_req.src = req->src; 318 rctx->fallback_req.src = req->src;
319 ctx->fallback_req.result = req->result; 319 rctx->fallback_req.result = req->result;
320 320
321 return crypto_ahash_finup(&ctx->fallback_req); 321 return crypto_ahash_finup(&rctx->fallback_req);
322} 322}
323 323
324static int n2_hash_cra_init(struct crypto_tfm *tfm) 324static int n2_hash_cra_init(struct crypto_tfm *tfm)
@@ -338,7 +338,10 @@ static int n2_hash_cra_init(struct crypto_tfm *tfm)
338 goto out; 338 goto out;
339 } 339 }
340 340
341 ctx->fallback = fallback_tfm; 341 crypto_ahash_set_reqsize(ahash, (sizeof(struct n2_hash_req_ctx) +
342 crypto_ahash_reqsize(fallback_tfm)));
343
344 ctx->fallback_tfm = fallback_tfm;
342 return 0; 345 return 0;
343 346
344out: 347out:
@@ -350,7 +353,7 @@ static void n2_hash_cra_exit(struct crypto_tfm *tfm)
350 struct crypto_ahash *ahash = __crypto_ahash_cast(tfm); 353 struct crypto_ahash *ahash = __crypto_ahash_cast(tfm);
351 struct n2_hash_ctx *ctx = crypto_ahash_ctx(ahash); 354 struct n2_hash_ctx *ctx = crypto_ahash_ctx(ahash);
352 355
353 crypto_free_ahash(ctx->fallback); 356 crypto_free_ahash(ctx->fallback_tfm);
354} 357}
355 358
356static unsigned long wait_for_tail(struct spu_queue *qp) 359static unsigned long wait_for_tail(struct spu_queue *qp)
@@ -399,14 +402,16 @@ static int n2_hash_async_digest(struct ahash_request *req,
399 * exceed 2^16. 402 * exceed 2^16.
400 */ 403 */
401 if (unlikely(req->nbytes > (1 << 16))) { 404 if (unlikely(req->nbytes > (1 << 16))) {
402 ctx->fallback_req.base.tfm = crypto_ahash_tfm(ctx->fallback); 405 struct n2_hash_req_ctx *rctx = ahash_request_ctx(req);
403 ctx->fallback_req.base.flags = 406
407 ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm);
408 rctx->fallback_req.base.flags =
404 req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP; 409 req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP;
405 ctx->fallback_req.nbytes = req->nbytes; 410 rctx->fallback_req.nbytes = req->nbytes;
406 ctx->fallback_req.src = req->src; 411 rctx->fallback_req.src = req->src;
407 ctx->fallback_req.result = req->result; 412 rctx->fallback_req.result = req->result;
408 413
409 return crypto_ahash_digest(&ctx->fallback_req); 414 return crypto_ahash_digest(&rctx->fallback_req);
410 } 415 }
411 416
412 n2_base_ctx_init(&ctx->base); 417 n2_base_ctx_init(&ctx->base);
@@ -472,9 +477,8 @@ out:
472 477
473static int n2_md5_async_digest(struct ahash_request *req) 478static int n2_md5_async_digest(struct ahash_request *req)
474{ 479{
475 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 480 struct n2_hash_req_ctx *rctx = ahash_request_ctx(req);
476 struct n2_hash_ctx *ctx = crypto_ahash_ctx(tfm); 481 struct md5_state *m = &rctx->u.md5;
477 struct md5_state *m = &ctx->u.md5;
478 482
479 if (unlikely(req->nbytes == 0)) { 483 if (unlikely(req->nbytes == 0)) {
480 static const char md5_zero[MD5_DIGEST_SIZE] = { 484 static const char md5_zero[MD5_DIGEST_SIZE] = {
@@ -497,9 +501,8 @@ static int n2_md5_async_digest(struct ahash_request *req)
497 501
498static int n2_sha1_async_digest(struct ahash_request *req) 502static int n2_sha1_async_digest(struct ahash_request *req)
499{ 503{
500 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 504 struct n2_hash_req_ctx *rctx = ahash_request_ctx(req);
501 struct n2_hash_ctx *ctx = crypto_ahash_ctx(tfm); 505 struct sha1_state *s = &rctx->u.sha1;
502 struct sha1_state *s = &ctx->u.sha1;
503 506
504 if (unlikely(req->nbytes == 0)) { 507 if (unlikely(req->nbytes == 0)) {
505 static const char sha1_zero[SHA1_DIGEST_SIZE] = { 508 static const char sha1_zero[SHA1_DIGEST_SIZE] = {
@@ -524,9 +527,8 @@ static int n2_sha1_async_digest(struct ahash_request *req)
524 527
525static int n2_sha256_async_digest(struct ahash_request *req) 528static int n2_sha256_async_digest(struct ahash_request *req)
526{ 529{
527 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 530 struct n2_hash_req_ctx *rctx = ahash_request_ctx(req);
528 struct n2_hash_ctx *ctx = crypto_ahash_ctx(tfm); 531 struct sha256_state *s = &rctx->u.sha256;
529 struct sha256_state *s = &ctx->u.sha256;
530 532
531 if (req->nbytes == 0) { 533 if (req->nbytes == 0) {
532 static const char sha256_zero[SHA256_DIGEST_SIZE] = { 534 static const char sha256_zero[SHA256_DIGEST_SIZE] = {
@@ -555,9 +557,8 @@ static int n2_sha256_async_digest(struct ahash_request *req)
555 557
556static int n2_sha224_async_digest(struct ahash_request *req) 558static int n2_sha224_async_digest(struct ahash_request *req)
557{ 559{
558 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 560 struct n2_hash_req_ctx *rctx = ahash_request_ctx(req);
559 struct n2_hash_ctx *ctx = crypto_ahash_ctx(tfm); 561 struct sha256_state *s = &rctx->u.sha256;
560 struct sha256_state *s = &ctx->u.sha256;
561 562
562 if (req->nbytes == 0) { 563 if (req->nbytes == 0) {
563 static const char sha224_zero[SHA224_DIGEST_SIZE] = { 564 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,
1398 1399
1399 intr = ip->ino_table[i].intr; 1400 intr = ip->ino_table[i].intr;
1400 1401
1401 dev_intrs = of_get_property(dev->node, "interrupts", NULL); 1402 dev_intrs = of_get_property(dev->dev.of_node, "interrupts", NULL);
1402 if (!dev_intrs) 1403 if (!dev_intrs)
1403 return -ENODEV; 1404 return -ENODEV;
1404 1405
@@ -1449,7 +1450,7 @@ static int queue_cache_init(void)
1449{ 1450{
1450 if (!queue_cache[HV_NCS_QTYPE_MAU - 1]) 1451 if (!queue_cache[HV_NCS_QTYPE_MAU - 1])
1451 queue_cache[HV_NCS_QTYPE_MAU - 1] = 1452 queue_cache[HV_NCS_QTYPE_MAU - 1] =
1452 kmem_cache_create("cwq_queue", 1453 kmem_cache_create("mau_queue",
1453 (MAU_NUM_ENTRIES * 1454 (MAU_NUM_ENTRIES *
1454 MAU_ENTRY_SIZE), 1455 MAU_ENTRY_SIZE),
1455 MAU_ENTRY_SIZE, 0, NULL); 1456 MAU_ENTRY_SIZE, 0, NULL);
@@ -1574,7 +1575,7 @@ static int spu_mdesc_walk_arcs(struct mdesc_handle *mdesc,
1574 id = mdesc_get_property(mdesc, tgt, "id", NULL); 1575 id = mdesc_get_property(mdesc, tgt, "id", NULL);
1575 if (table[*id] != NULL) { 1576 if (table[*id] != NULL) {
1576 dev_err(&dev->dev, "%s: SPU cpu slot already set.\n", 1577 dev_err(&dev->dev, "%s: SPU cpu slot already set.\n",
1577 dev->node->full_name); 1578 dev->dev.of_node->full_name);
1578 return -EINVAL; 1579 return -EINVAL;
1579 } 1580 }
1580 cpu_set(*id, p->sharing); 1581 cpu_set(*id, p->sharing);
@@ -1595,7 +1596,7 @@ static int handle_exec_unit(struct spu_mdesc_info *ip, struct list_head *list,
1595 p = kzalloc(sizeof(struct spu_queue), GFP_KERNEL); 1596 p = kzalloc(sizeof(struct spu_queue), GFP_KERNEL);
1596 if (!p) { 1597 if (!p) {
1597 dev_err(&dev->dev, "%s: Could not allocate SPU queue.\n", 1598 dev_err(&dev->dev, "%s: Could not allocate SPU queue.\n",
1598 dev->node->full_name); 1599 dev->dev.of_node->full_name);
1599 return -ENOMEM; 1600 return -ENOMEM;
1600 } 1601 }
1601 1602
@@ -1684,7 +1685,7 @@ static int __devinit grab_mdesc_irq_props(struct mdesc_handle *mdesc,
1684 const unsigned int *reg; 1685 const unsigned int *reg;
1685 u64 node; 1686 u64 node;
1686 1687
1687 reg = of_get_property(dev->node, "reg", NULL); 1688 reg = of_get_property(dev->dev.of_node, "reg", NULL);
1688 if (!reg) 1689 if (!reg)
1689 return -ENODEV; 1690 return -ENODEV;
1690 1691
@@ -1836,7 +1837,7 @@ static int __devinit n2_crypto_probe(struct of_device *dev,
1836 1837
1837 n2_spu_driver_version(); 1838 n2_spu_driver_version();
1838 1839
1839 full_name = dev->node->full_name; 1840 full_name = dev->dev.of_node->full_name;
1840 pr_info("Found N2CP at %s\n", full_name); 1841 pr_info("Found N2CP at %s\n", full_name);
1841 1842
1842 np = alloc_n2cp(); 1843 np = alloc_n2cp();
@@ -1948,7 +1949,7 @@ static int __devinit n2_mau_probe(struct of_device *dev,
1948 1949
1949 n2_spu_driver_version(); 1950 n2_spu_driver_version();
1950 1951
1951 full_name = dev->node->full_name; 1952 full_name = dev->dev.of_node->full_name;
1952 pr_info("Found NCP at %s\n", full_name); 1953 pr_info("Found NCP at %s\n", full_name);
1953 1954
1954 mp = alloc_ncp(); 1955 mp = alloc_ncp();
@@ -2034,8 +2035,11 @@ static struct of_device_id n2_crypto_match[] = {
2034MODULE_DEVICE_TABLE(of, n2_crypto_match); 2035MODULE_DEVICE_TABLE(of, n2_crypto_match);
2035 2036
2036static struct of_platform_driver n2_crypto_driver = { 2037static struct of_platform_driver n2_crypto_driver = {
2037 .name = "n2cp", 2038 .driver = {
2038 .match_table = n2_crypto_match, 2039 .name = "n2cp",
2040 .owner = THIS_MODULE,
2041 .of_match_table = n2_crypto_match,
2042 },
2039 .probe = n2_crypto_probe, 2043 .probe = n2_crypto_probe,
2040 .remove = __devexit_p(n2_crypto_remove), 2044 .remove = __devexit_p(n2_crypto_remove),
2041}; 2045};
@@ -2055,8 +2059,11 @@ static struct of_device_id n2_mau_match[] = {
2055MODULE_DEVICE_TABLE(of, n2_mau_match); 2059MODULE_DEVICE_TABLE(of, n2_mau_match);
2056 2060
2057static struct of_platform_driver n2_mau_driver = { 2061static struct of_platform_driver n2_mau_driver = {
2058 .name = "ncp", 2062 .driver = {
2059 .match_table = n2_mau_match, 2063 .name = "ncp",
2064 .owner = THIS_MODULE,
2065 .of_match_table = n2_mau_match,
2066 },
2060 .probe = n2_mau_probe, 2067 .probe = n2_mau_probe,
2061 .remove = __devexit_p(n2_mau_remove), 2068 .remove = __devexit_p(n2_mau_remove),
2062}; 2069};
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 1b8877922fb0..9e01e96fee94 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -166,6 +166,15 @@ config TIMB_DMA
166config ARCH_HAS_ASYNC_TX_FIND_CHANNEL 166config ARCH_HAS_ASYNC_TX_FIND_CHANNEL
167 bool 167 bool
168 168
169config PL330_DMA
170 tristate "DMA API Driver for PL330"
171 select DMA_ENGINE
172 depends on PL330
173 help
174 Select if your platform has one or more PL330 DMACs.
175 You need to provide platform specific settings via
176 platform_data for a dma-pl330 device.
177
169config DMA_ENGINE 178config DMA_ENGINE
170 bool 179 bool
171 180
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 20881426c1ac..0fe5ebbfda5d 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -22,3 +22,4 @@ obj-$(CONFIG_COH901318) += coh901318.o coh901318_lli.o
22obj-$(CONFIG_AMCC_PPC440SPE_ADMA) += ppc4xx/ 22obj-$(CONFIG_AMCC_PPC440SPE_ADMA) += ppc4xx/
23obj-$(CONFIG_TIMB_DMA) += timb_dma.o 23obj-$(CONFIG_TIMB_DMA) += timb_dma.o
24obj-$(CONFIG_STE_DMA40) += ste_dma40.o ste_dma40_ll.o 24obj-$(CONFIG_STE_DMA40) += ste_dma40.o ste_dma40_ll.o
25obj-$(CONFIG_PL330_DMA) += pl330.o
diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
index 201e6e19c344..14a8c0f1698e 100644
--- a/drivers/dma/mpc512x_dma.c
+++ b/drivers/dma/mpc512x_dma.c
@@ -630,7 +630,7 @@ mpc_dma_prep_memcpy(struct dma_chan *chan, dma_addr_t dst, dma_addr_t src,
630static int __devinit mpc_dma_probe(struct of_device *op, 630static int __devinit mpc_dma_probe(struct of_device *op,
631 const struct of_device_id *match) 631 const struct of_device_id *match)
632{ 632{
633 struct device_node *dn = op->node; 633 struct device_node *dn = op->dev.of_node;
634 struct device *dev = &op->dev; 634 struct device *dev = &op->dev;
635 struct dma_device *dma; 635 struct dma_device *dma;
636 struct mpc_dma *mdma; 636 struct mpc_dma *mdma;
@@ -771,12 +771,12 @@ static struct of_device_id mpc_dma_match[] = {
771}; 771};
772 772
773static struct of_platform_driver mpc_dma_driver = { 773static struct of_platform_driver mpc_dma_driver = {
774 .match_table = mpc_dma_match,
775 .probe = mpc_dma_probe, 774 .probe = mpc_dma_probe,
776 .remove = __devexit_p(mpc_dma_remove), 775 .remove = __devexit_p(mpc_dma_remove),
777 .driver = { 776 .driver = {
778 .name = DRV_NAME, 777 .name = DRV_NAME,
779 .owner = THIS_MODULE, 778 .owner = THIS_MODULE,
779 .of_match_table = mpc_dma_match,
780 }, 780 },
781}; 781};
782 782
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
new file mode 100644
index 000000000000..7c50f6dfd3f4
--- /dev/null
+++ b/drivers/dma/pl330.c
@@ -0,0 +1,866 @@
1/* linux/drivers/dma/pl330.c
2 *
3 * Copyright (C) 2010 Samsung Electronics Co. Ltd.
4 * Jaswinder Singh <jassi.brar@samsung.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#include <linux/io.h>
13#include <linux/init.h>
14#include <linux/slab.h>
15#include <linux/module.h>
16#include <linux/dmaengine.h>
17#include <linux/interrupt.h>
18#include <linux/amba/bus.h>
19#include <linux/amba/pl330.h>
20
21#define NR_DEFAULT_DESC 16
22
23enum desc_status {
24 /* In the DMAC pool */
25 FREE,
26 /*
27 * Allocted to some channel during prep_xxx
28 * Also may be sitting on the work_list.
29 */
30 PREP,
31 /*
32 * Sitting on the work_list and already submitted
33 * to the PL330 core. Not more than two descriptors
34 * of a channel can be BUSY at any time.
35 */
36 BUSY,
37 /*
38 * Sitting on the channel work_list but xfer done
39 * by PL330 core
40 */
41 DONE,
42};
43
44struct dma_pl330_chan {
45 /* Schedule desc completion */
46 struct tasklet_struct task;
47
48 /* DMA-Engine Channel */
49 struct dma_chan chan;
50
51 /* Last completed cookie */
52 dma_cookie_t completed;
53
54 /* List of to be xfered descriptors */
55 struct list_head work_list;
56
57 /* Pointer to the DMAC that manages this channel,
58 * NULL if the channel is available to be acquired.
59 * As the parent, this DMAC also provides descriptors
60 * to the channel.
61 */
62 struct dma_pl330_dmac *dmac;
63
64 /* To protect channel manipulation */
65 spinlock_t lock;
66
67 /* Token of a hardware channel thread of PL330 DMAC
68 * NULL if the channel is available to be acquired.
69 */
70 void *pl330_chid;
71};
72
73struct dma_pl330_dmac {
74 struct pl330_info pif;
75
76 /* DMA-Engine Device */
77 struct dma_device ddma;
78
79 /* Pool of descriptors available for the DMAC's channels */
80 struct list_head desc_pool;
81 /* To protect desc_pool manipulation */
82 spinlock_t pool_lock;
83
84 /* Peripheral channels connected to this DMAC */
85 struct dma_pl330_chan peripherals[0]; /* keep at end */
86};
87
88struct dma_pl330_desc {
89 /* To attach to a queue as child */
90 struct list_head node;
91
92 /* Descriptor for the DMA Engine API */
93 struct dma_async_tx_descriptor txd;
94
95 /* Xfer for PL330 core */
96 struct pl330_xfer px;
97
98 struct pl330_reqcfg rqcfg;
99 struct pl330_req req;
100
101 enum desc_status status;
102
103 /* The channel which currently holds this desc */
104 struct dma_pl330_chan *pchan;
105};
106
107static inline struct dma_pl330_chan *
108to_pchan(struct dma_chan *ch)
109{
110 if (!ch)
111 return NULL;
112
113 return container_of(ch, struct dma_pl330_chan, chan);
114}
115
116static inline struct dma_pl330_desc *
117to_desc(struct dma_async_tx_descriptor *tx)
118{
119 return container_of(tx, struct dma_pl330_desc, txd);
120}
121
122static inline void free_desc_list(struct list_head *list)
123{
124 struct dma_pl330_dmac *pdmac;
125 struct dma_pl330_desc *desc;
126 struct dma_pl330_chan *pch;
127 unsigned long flags;
128
129 if (list_empty(list))
130 return;
131
132 /* Finish off the work list */
133 list_for_each_entry(desc, list, node) {
134 dma_async_tx_callback callback;
135 void *param;
136
137 /* All desc in a list belong to same channel */
138 pch = desc->pchan;
139 callback = desc->txd.callback;
140 param = desc->txd.callback_param;
141
142 if (callback)
143 callback(param);
144
145 desc->pchan = NULL;
146 }
147
148 pdmac = pch->dmac;
149
150 spin_lock_irqsave(&pdmac->pool_lock, flags);
151 list_splice_tail_init(list, &pdmac->desc_pool);
152 spin_unlock_irqrestore(&pdmac->pool_lock, flags);
153}
154
155static inline void fill_queue(struct dma_pl330_chan *pch)
156{
157 struct dma_pl330_desc *desc;
158 int ret;
159
160 list_for_each_entry(desc, &pch->work_list, node) {
161
162 /* If already submitted */
163 if (desc->status == BUSY)
164 break;
165
166 ret = pl330_submit_req(pch->pl330_chid,
167 &desc->req);
168 if (!ret) {
169 desc->status = BUSY;
170 break;
171 } else if (ret == -EAGAIN) {
172 /* QFull or DMAC Dying */
173 break;
174 } else {
175 /* Unacceptable request */
176 desc->status = DONE;
177 dev_err(pch->dmac->pif.dev, "%s:%d Bad Desc(%d)\n",
178 __func__, __LINE__, desc->txd.cookie);
179 tasklet_schedule(&pch->task);
180 }
181 }
182}
183
184static void pl330_tasklet(unsigned long data)
185{
186 struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;
187 struct dma_pl330_desc *desc, *_dt;
188 unsigned long flags;
189 LIST_HEAD(list);
190
191 spin_lock_irqsave(&pch->lock, flags);
192
193 /* Pick up ripe tomatoes */
194 list_for_each_entry_safe(desc, _dt, &pch->work_list, node)
195 if (desc->status == DONE) {
196 pch->completed = desc->txd.cookie;
197 list_move_tail(&desc->node, &list);
198 }
199
200 /* Try to submit a req imm. next to the last completed cookie */
201 fill_queue(pch);
202
203 /* Make sure the PL330 Channel thread is active */
204 pl330_chan_ctrl(pch->pl330_chid, PL330_OP_START);
205
206 spin_unlock_irqrestore(&pch->lock, flags);
207
208 free_desc_list(&list);
209}
210
211static void dma_pl330_rqcb(void *token, enum pl330_op_err err)
212{
213 struct dma_pl330_desc *desc = token;
214 struct dma_pl330_chan *pch = desc->pchan;
215 unsigned long flags;
216
217 /* If desc aborted */
218 if (!pch)
219 return;
220
221 spin_lock_irqsave(&pch->lock, flags);
222
223 desc->status = DONE;
224
225 spin_unlock_irqrestore(&pch->lock, flags);
226
227 tasklet_schedule(&pch->task);
228}
229
230static int pl330_alloc_chan_resources(struct dma_chan *chan)
231{
232 struct dma_pl330_chan *pch = to_pchan(chan);
233 struct dma_pl330_dmac *pdmac = pch->dmac;
234 unsigned long flags;
235
236 spin_lock_irqsave(&pch->lock, flags);
237
238 pch->completed = chan->cookie = 1;
239
240 pch->pl330_chid = pl330_request_channel(&pdmac->pif);
241 if (!pch->pl330_chid) {
242 spin_unlock_irqrestore(&pch->lock, flags);
243 return 0;
244 }
245
246 tasklet_init(&pch->task, pl330_tasklet, (unsigned long) pch);
247
248 spin_unlock_irqrestore(&pch->lock, flags);
249
250 return 1;
251}
252
253static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned long arg)
254{
255 struct dma_pl330_chan *pch = to_pchan(chan);
256 struct dma_pl330_desc *desc;
257 unsigned long flags;
258
259 /* Only supports DMA_TERMINATE_ALL */
260 if (cmd != DMA_TERMINATE_ALL)
261 return -ENXIO;
262
263 spin_lock_irqsave(&pch->lock, flags);
264
265 /* FLUSH the PL330 Channel thread */
266 pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
267
268 /* Mark all desc done */
269 list_for_each_entry(desc, &pch->work_list, node)
270 desc->status = DONE;
271
272 spin_unlock_irqrestore(&pch->lock, flags);
273
274 pl330_tasklet((unsigned long) pch);
275
276 return 0;
277}
278
279static void pl330_free_chan_resources(struct dma_chan *chan)
280{
281 struct dma_pl330_chan *pch = to_pchan(chan);
282 unsigned long flags;
283
284 spin_lock_irqsave(&pch->lock, flags);
285
286 tasklet_kill(&pch->task);
287
288 pl330_release_channel(pch->pl330_chid);
289 pch->pl330_chid = NULL;
290
291 spin_unlock_irqrestore(&pch->lock, flags);
292}
293
294static enum dma_status
295pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
296 struct dma_tx_state *txstate)
297{
298 struct dma_pl330_chan *pch = to_pchan(chan);
299 dma_cookie_t last_done, last_used;
300 int ret;
301
302 last_done = pch->completed;
303 last_used = chan->cookie;
304
305 ret = dma_async_is_complete(cookie, last_done, last_used);
306
307 dma_set_tx_state(txstate, last_done, last_used, 0);
308
309 return ret;
310}
311
312static void pl330_issue_pending(struct dma_chan *chan)
313{
314 pl330_tasklet((unsigned long) to_pchan(chan));
315}
316
317/*
318 * We returned the last one of the circular list of descriptor(s)
319 * from prep_xxx, so the argument to submit corresponds to the last
320 * descriptor of the list.
321 */
322static dma_cookie_t pl330_tx_submit(struct dma_async_tx_descriptor *tx)
323{
324 struct dma_pl330_desc *desc, *last = to_desc(tx);
325 struct dma_pl330_chan *pch = to_pchan(tx->chan);
326 dma_cookie_t cookie;
327 unsigned long flags;
328
329 spin_lock_irqsave(&pch->lock, flags);
330
331 /* Assign cookies to all nodes */
332 cookie = tx->chan->cookie;
333
334 while (!list_empty(&last->node)) {
335 desc = list_entry(last->node.next, struct dma_pl330_desc, node);
336
337 if (++cookie < 0)
338 cookie = 1;
339 desc->txd.cookie = cookie;
340
341 list_move_tail(&desc->node, &pch->work_list);
342 }
343
344 if (++cookie < 0)
345 cookie = 1;
346 last->txd.cookie = cookie;
347
348 list_add_tail(&last->node, &pch->work_list);
349
350 tx->chan->cookie = cookie;
351
352 spin_unlock_irqrestore(&pch->lock, flags);
353
354 return cookie;
355}
356
357static inline void _init_desc(struct dma_pl330_desc *desc)
358{
359 desc->pchan = NULL;
360 desc->req.x = &desc->px;
361 desc->req.token = desc;
362 desc->rqcfg.swap = SWAP_NO;
363 desc->rqcfg.privileged = 0;
364 desc->rqcfg.insnaccess = 0;
365 desc->rqcfg.scctl = SCCTRL0;
366 desc->rqcfg.dcctl = DCCTRL0;
367 desc->req.cfg = &desc->rqcfg;
368 desc->req.xfer_cb = dma_pl330_rqcb;
369 desc->txd.tx_submit = pl330_tx_submit;
370
371 INIT_LIST_HEAD(&desc->node);
372}
373
374/* Returns the number of descriptors added to the DMAC pool */
375int add_desc(struct dma_pl330_dmac *pdmac, gfp_t flg, int count)
376{
377 struct dma_pl330_desc *desc;
378 unsigned long flags;
379 int i;
380
381 if (!pdmac)
382 return 0;
383
384 desc = kmalloc(count * sizeof(*desc), flg);
385 if (!desc)
386 return 0;
387
388 spin_lock_irqsave(&pdmac->pool_lock, flags);
389
390 for (i = 0; i < count; i++) {
391 _init_desc(&desc[i]);
392 list_add_tail(&desc[i].node, &pdmac->desc_pool);
393 }
394
395 spin_unlock_irqrestore(&pdmac->pool_lock, flags);
396
397 return count;
398}
399
400static struct dma_pl330_desc *
401pluck_desc(struct dma_pl330_dmac *pdmac)
402{
403 struct dma_pl330_desc *desc = NULL;
404 unsigned long flags;
405
406 if (!pdmac)
407 return NULL;
408
409 spin_lock_irqsave(&pdmac->pool_lock, flags);
410
411 if (!list_empty(&pdmac->desc_pool)) {
412 desc = list_entry(pdmac->desc_pool.next,
413 struct dma_pl330_desc, node);
414
415 list_del_init(&desc->node);
416
417 desc->status = PREP;
418 desc->txd.callback = NULL;
419 }
420
421 spin_unlock_irqrestore(&pdmac->pool_lock, flags);
422
423 return desc;
424}
425
426static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch)
427{
428 struct dma_pl330_dmac *pdmac = pch->dmac;
429 struct dma_pl330_peri *peri = pch->chan.private;
430 struct dma_pl330_desc *desc;
431
432 /* Pluck one desc from the pool of DMAC */
433 desc = pluck_desc(pdmac);
434
435 /* If the DMAC pool is empty, alloc new */
436 if (!desc) {
437 if (!add_desc(pdmac, GFP_ATOMIC, 1))
438 return NULL;
439
440 /* Try again */
441 desc = pluck_desc(pdmac);
442 if (!desc) {
443 dev_err(pch->dmac->pif.dev,
444 "%s:%d ALERT!\n", __func__, __LINE__);
445 return NULL;
446 }
447 }
448
449 /* Initialize the descriptor */
450 desc->pchan = pch;
451 desc->txd.cookie = 0;
452 async_tx_ack(&desc->txd);
453
454 desc->req.rqtype = peri->rqtype;
455 desc->req.peri = peri->peri_id;
456
457 dma_async_tx_descriptor_init(&desc->txd, &pch->chan);
458
459 return desc;
460}
461
462static inline void fill_px(struct pl330_xfer *px,
463 dma_addr_t dst, dma_addr_t src, size_t len)
464{
465 px->next = NULL;
466 px->bytes = len;
467 px->dst_addr = dst;
468 px->src_addr = src;
469}
470
471static struct dma_pl330_desc *
472__pl330_prep_dma_memcpy(struct dma_pl330_chan *pch, dma_addr_t dst,
473 dma_addr_t src, size_t len)
474{
475 struct dma_pl330_desc *desc = pl330_get_desc(pch);
476
477 if (!desc) {
478 dev_err(pch->dmac->pif.dev, "%s:%d Unable to fetch desc\n",
479 __func__, __LINE__);
480 return NULL;
481 }
482
483 /*
484 * Ideally we should lookout for reqs bigger than
485 * those that can be programmed with 256 bytes of
486 * MC buffer, but considering a req size is seldom
487 * going to be word-unaligned and more than 200MB,
488 * we take it easy.
489 * Also, should the limit is reached we'd rather
490 * have the platform increase MC buffer size than
491 * complicating this API driver.
492 */
493 fill_px(&desc->px, dst, src, len);
494
495 return desc;
496}
497
498/* Call after fixing burst size */
499static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len)
500{
501 struct dma_pl330_chan *pch = desc->pchan;
502 struct pl330_info *pi = &pch->dmac->pif;
503 int burst_len;
504
505 burst_len = pi->pcfg.data_bus_width / 8;
506 burst_len *= pi->pcfg.data_buf_dep;
507 burst_len >>= desc->rqcfg.brst_size;
508
509 /* src/dst_burst_len can't be more than 16 */
510 if (burst_len > 16)
511 burst_len = 16;
512
513 while (burst_len > 1) {
514 if (!(len % (burst_len << desc->rqcfg.brst_size)))
515 break;
516 burst_len--;
517 }
518
519 return burst_len;
520}
521
522static struct dma_async_tx_descriptor *
523pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst,
524 dma_addr_t src, size_t len, unsigned long flags)
525{
526 struct dma_pl330_desc *desc;
527 struct dma_pl330_chan *pch = to_pchan(chan);
528 struct dma_pl330_peri *peri = chan->private;
529 struct pl330_info *pi;
530 int burst;
531
532 if (unlikely(!pch || !len || !peri))
533 return NULL;
534
535 if (peri->rqtype != MEMTOMEM)
536 return NULL;
537
538 pi = &pch->dmac->pif;
539
540 desc = __pl330_prep_dma_memcpy(pch, dst, src, len);
541 if (!desc)
542 return NULL;
543
544 desc->rqcfg.src_inc = 1;
545 desc->rqcfg.dst_inc = 1;
546
547 /* Select max possible burst size */
548 burst = pi->pcfg.data_bus_width / 8;
549
550 while (burst > 1) {
551 if (!(len % burst))
552 break;
553 burst /= 2;
554 }
555
556 desc->rqcfg.brst_size = 0;
557 while (burst != (1 << desc->rqcfg.brst_size))
558 desc->rqcfg.brst_size++;
559
560 desc->rqcfg.brst_len = get_burst_len(desc, len);
561
562 desc->txd.flags = flags;
563
564 return &desc->txd;
565}
566
567static struct dma_async_tx_descriptor *
568pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
569 unsigned int sg_len, enum dma_data_direction direction,
570 unsigned long flg)
571{
572 struct dma_pl330_desc *first, *desc = NULL;
573 struct dma_pl330_chan *pch = to_pchan(chan);
574 struct dma_pl330_peri *peri = chan->private;
575 struct scatterlist *sg;
576 unsigned long flags;
577 int i, burst_size;
578 dma_addr_t addr;
579
580 if (unlikely(!pch || !sgl || !sg_len))
581 return NULL;
582
583 /* Make sure the direction is consistent */
584 if ((direction == DMA_TO_DEVICE &&
585 peri->rqtype != MEMTODEV) ||
586 (direction == DMA_FROM_DEVICE &&
587 peri->rqtype != DEVTOMEM)) {
588 dev_err(pch->dmac->pif.dev, "%s:%d Invalid Direction\n",
589 __func__, __LINE__);
590 return NULL;
591 }
592
593 addr = peri->fifo_addr;
594 burst_size = peri->burst_sz;
595
596 first = NULL;
597
598 for_each_sg(sgl, sg, sg_len, i) {
599
600 desc = pl330_get_desc(pch);
601 if (!desc) {
602 struct dma_pl330_dmac *pdmac = pch->dmac;
603
604 dev_err(pch->dmac->pif.dev,
605 "%s:%d Unable to fetch desc\n",
606 __func__, __LINE__);
607 if (!first)
608 return NULL;
609
610 spin_lock_irqsave(&pdmac->pool_lock, flags);
611
612 while (!list_empty(&first->node)) {
613 desc = list_entry(first->node.next,
614 struct dma_pl330_desc, node);
615 list_move_tail(&desc->node, &pdmac->desc_pool);
616 }
617
618 list_move_tail(&first->node, &pdmac->desc_pool);
619
620 spin_unlock_irqrestore(&pdmac->pool_lock, flags);
621
622 return NULL;
623 }
624
625 if (!first)
626 first = desc;
627 else
628 list_add_tail(&desc->node, &first->node);
629
630 if (direction == DMA_TO_DEVICE) {
631 desc->rqcfg.src_inc = 1;
632 desc->rqcfg.dst_inc = 0;
633 fill_px(&desc->px,
634 addr, sg_dma_address(sg), sg_dma_len(sg));
635 } else {
636 desc->rqcfg.src_inc = 0;
637 desc->rqcfg.dst_inc = 1;
638 fill_px(&desc->px,
639 sg_dma_address(sg), addr, sg_dma_len(sg));
640 }
641
642 desc->rqcfg.brst_size = burst_size;
643 desc->rqcfg.brst_len = 1;
644 }
645
646 /* Return the last desc in the chain */
647 desc->txd.flags = flg;
648 return &desc->txd;
649}
650
651static irqreturn_t pl330_irq_handler(int irq, void *data)
652{
653 if (pl330_update(data))
654 return IRQ_HANDLED;
655 else
656 return IRQ_NONE;
657}
658
659static int __devinit
660pl330_probe(struct amba_device *adev, struct amba_id *id)
661{
662 struct dma_pl330_platdata *pdat;
663 struct dma_pl330_dmac *pdmac;
664 struct dma_pl330_chan *pch;
665 struct pl330_info *pi;
666 struct dma_device *pd;
667 struct resource *res;
668 int i, ret, irq;
669
670 pdat = adev->dev.platform_data;
671
672 if (!pdat || !pdat->nr_valid_peri) {
673 dev_err(&adev->dev, "platform data missing\n");
674 return -ENODEV;
675 }
676
677 /* Allocate a new DMAC and its Channels */
678 pdmac = kzalloc(pdat->nr_valid_peri * sizeof(*pch)
679 + sizeof(*pdmac), GFP_KERNEL);
680 if (!pdmac) {
681 dev_err(&adev->dev, "unable to allocate mem\n");
682 return -ENOMEM;
683 }
684
685 pi = &pdmac->pif;
686 pi->dev = &adev->dev;
687 pi->pl330_data = NULL;
688 pi->mcbufsz = pdat->mcbuf_sz;
689
690 res = &adev->res;
691 request_mem_region(res->start, resource_size(res), "dma-pl330");
692
693 pi->base = ioremap(res->start, resource_size(res));
694 if (!pi->base) {
695 ret = -ENXIO;
696 goto probe_err1;
697 }
698
699 irq = adev->irq[0];
700 ret = request_irq(irq, pl330_irq_handler, 0,
701 dev_name(&adev->dev), pi);
702 if (ret)
703 goto probe_err2;
704
705 ret = pl330_add(pi);
706 if (ret)
707 goto probe_err3;
708
709 INIT_LIST_HEAD(&pdmac->desc_pool);
710 spin_lock_init(&pdmac->pool_lock);
711
712 /* Create a descriptor pool of default size */
713 if (!add_desc(pdmac, GFP_KERNEL, NR_DEFAULT_DESC))
714 dev_warn(&adev->dev, "unable to allocate desc\n");
715
716 pd = &pdmac->ddma;
717 INIT_LIST_HEAD(&pd->channels);
718
719 /* Initialize channel parameters */
720 for (i = 0; i < pdat->nr_valid_peri; i++) {
721 struct dma_pl330_peri *peri = &pdat->peri[i];
722 pch = &pdmac->peripherals[i];
723
724 switch (peri->rqtype) {
725 case MEMTOMEM:
726 dma_cap_set(DMA_MEMCPY, pd->cap_mask);
727 break;
728 case MEMTODEV:
729 case DEVTOMEM:
730 dma_cap_set(DMA_SLAVE, pd->cap_mask);
731 break;
732 default:
733 dev_err(&adev->dev, "DEVTODEV Not Supported\n");
734 continue;
735 }
736
737 INIT_LIST_HEAD(&pch->work_list);
738 spin_lock_init(&pch->lock);
739 pch->pl330_chid = NULL;
740 pch->chan.private = peri;
741 pch->chan.device = pd;
742 pch->chan.chan_id = i;
743 pch->dmac = pdmac;
744
745 /* Add the channel to the DMAC list */
746 pd->chancnt++;
747 list_add_tail(&pch->chan.device_node, &pd->channels);
748 }
749
750 pd->dev = &adev->dev;
751
752 pd->device_alloc_chan_resources = pl330_alloc_chan_resources;
753 pd->device_free_chan_resources = pl330_free_chan_resources;
754 pd->device_prep_dma_memcpy = pl330_prep_dma_memcpy;
755 pd->device_tx_status = pl330_tx_status;
756 pd->device_prep_slave_sg = pl330_prep_slave_sg;
757 pd->device_control = pl330_control;
758 pd->device_issue_pending = pl330_issue_pending;
759
760 ret = dma_async_device_register(pd);
761 if (ret) {
762 dev_err(&adev->dev, "unable to register DMAC\n");
763 goto probe_err4;
764 }
765
766 amba_set_drvdata(adev, pdmac);
767
768 dev_info(&adev->dev,
769 "Loaded driver for PL330 DMAC-%d\n", adev->periphid);
770 dev_info(&adev->dev,
771 "\tDBUFF-%ux%ubytes Num_Chans-%u Num_Peri-%u Num_Events-%u\n",
772 pi->pcfg.data_buf_dep,
773 pi->pcfg.data_bus_width / 8, pi->pcfg.num_chan,
774 pi->pcfg.num_peri, pi->pcfg.num_events);
775
776 return 0;
777
778probe_err4:
779 pl330_del(pi);
780probe_err3:
781 free_irq(irq, pi);
782probe_err2:
783 iounmap(pi->base);
784probe_err1:
785 release_mem_region(res->start, resource_size(res));
786 kfree(pdmac);
787
788 return ret;
789}
790
791static int __devexit pl330_remove(struct amba_device *adev)
792{
793 struct dma_pl330_dmac *pdmac = amba_get_drvdata(adev);
794 struct dma_pl330_chan *pch, *_p;
795 struct pl330_info *pi;
796 struct resource *res;
797 int irq;
798
799 if (!pdmac)
800 return 0;
801
802 amba_set_drvdata(adev, NULL);
803
804 /* Idle the DMAC */
805 list_for_each_entry_safe(pch, _p, &pdmac->ddma.channels,
806 chan.device_node) {
807
808 /* Remove the channel */
809 list_del(&pch->chan.device_node);
810
811 /* Flush the channel */
812 pl330_control(&pch->chan, DMA_TERMINATE_ALL, 0);
813 pl330_free_chan_resources(&pch->chan);
814 }
815
816 pi = &pdmac->pif;
817
818 pl330_del(pi);
819
820 irq = adev->irq[0];
821 free_irq(irq, pi);
822
823 iounmap(pi->base);
824
825 res = &adev->res;
826 release_mem_region(res->start, resource_size(res));
827
828 kfree(pdmac);
829
830 return 0;
831}
832
833static struct amba_id pl330_ids[] = {
834 {
835 .id = 0x00041330,
836 .mask = 0x000fffff,
837 },
838 { 0, 0 },
839};
840
841static struct amba_driver pl330_driver = {
842 .drv = {
843 .owner = THIS_MODULE,
844 .name = "dma-pl330",
845 },
846 .id_table = pl330_ids,
847 .probe = pl330_probe,
848 .remove = pl330_remove,
849};
850
851static int __init pl330_init(void)
852{
853 return amba_driver_register(&pl330_driver);
854}
855module_init(pl330_init);
856
857static void __exit pl330_exit(void)
858{
859 amba_driver_unregister(&pl330_driver);
860 return;
861}
862module_exit(pl330_exit);
863
864MODULE_AUTHOR("Jaswinder Singh <jassi.brar@samsung.com>");
865MODULE_DESCRIPTION("API Driver for PL330 DMAC");
866MODULE_LICENSE("GPL");
diff --git a/drivers/dma/ppc4xx/adma.c b/drivers/dma/ppc4xx/adma.c
index fa98abe4686f..5a22ca6927e5 100644
--- a/drivers/dma/ppc4xx/adma.c
+++ b/drivers/dma/ppc4xx/adma.c
@@ -4394,7 +4394,7 @@ static void ppc440spe_adma_release_irqs(struct ppc440spe_adma_device *adev,
4394static int __devinit ppc440spe_adma_probe(struct of_device *ofdev, 4394static int __devinit ppc440spe_adma_probe(struct of_device *ofdev,
4395 const struct of_device_id *match) 4395 const struct of_device_id *match)
4396{ 4396{
4397 struct device_node *np = ofdev->node; 4397 struct device_node *np = ofdev->dev.of_node;
4398 struct resource res; 4398 struct resource res;
4399 struct ppc440spe_adma_device *adev; 4399 struct ppc440spe_adma_device *adev;
4400 struct ppc440spe_adma_chan *chan; 4400 struct ppc440spe_adma_chan *chan;
@@ -4626,7 +4626,7 @@ out:
4626static int __devexit ppc440spe_adma_remove(struct of_device *ofdev) 4626static int __devexit ppc440spe_adma_remove(struct of_device *ofdev)
4627{ 4627{
4628 struct ppc440spe_adma_device *adev = dev_get_drvdata(&ofdev->dev); 4628 struct ppc440spe_adma_device *adev = dev_get_drvdata(&ofdev->dev);
4629 struct device_node *np = ofdev->node; 4629 struct device_node *np = ofdev->dev.of_node;
4630 struct resource res; 4630 struct resource res;
4631 struct dma_chan *chan, *_chan; 4631 struct dma_chan *chan, *_chan;
4632 struct ppc_dma_chan_ref *ref, *_ref; 4632 struct ppc_dma_chan_ref *ref, *_ref;
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 55c9c59b3f71..aedef7941b22 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -69,6 +69,9 @@ config EDAC_MM_EDAC
69 occurred so that a particular failing memory module can be 69 occurred so that a particular failing memory module can be
70 replaced. If unsure, select 'Y'. 70 replaced. If unsure, select 'Y'.
71 71
72config EDAC_MCE
73 bool
74
72config EDAC_AMD64 75config EDAC_AMD64
73 tristate "AMD64 (Opteron, Athlon64) K8, F10h, F11h" 76 tristate "AMD64 (Opteron, Athlon64) K8, F10h, F11h"
74 depends on EDAC_MM_EDAC && K8_NB && X86_64 && PCI && EDAC_DECODE_MCE 77 depends on EDAC_MM_EDAC && K8_NB && X86_64 && PCI && EDAC_DECODE_MCE
@@ -166,6 +169,16 @@ config EDAC_I5400
166 Support for error detection and correction the Intel 169 Support for error detection and correction the Intel
167 i5400 MCH chipset (Seaburg). 170 i5400 MCH chipset (Seaburg).
168 171
172config EDAC_I7CORE
173 tristate "Intel i7 Core (Nehalem) processors"
174 depends on EDAC_MM_EDAC && PCI && X86
175 select EDAC_MCE
176 help
177 Support for error detection and correction the Intel
178 i7 Core (Nehalem) Integrated Memory Controller that exists on
179 newer processors like i7 Core, i7 Core Extreme, Xeon 35xx
180 and Xeon 55xx processors.
181
169config EDAC_I82860 182config EDAC_I82860
170 tristate "Intel 82860" 183 tristate "Intel 82860"
171 depends on EDAC_MM_EDAC && PCI && X86_32 184 depends on EDAC_MM_EDAC && PCI && X86_32
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
index bc5dc232a0fb..ca6b1bb24ccc 100644
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -8,6 +8,7 @@
8 8
9obj-$(CONFIG_EDAC) := edac_stub.o 9obj-$(CONFIG_EDAC) := edac_stub.o
10obj-$(CONFIG_EDAC_MM_EDAC) += edac_core.o 10obj-$(CONFIG_EDAC_MM_EDAC) += edac_core.o
11obj-$(CONFIG_EDAC_MCE) += edac_mce.o
11 12
12edac_core-objs := edac_mc.o edac_device.o edac_mc_sysfs.o edac_pci_sysfs.o 13edac_core-objs := edac_mc.o edac_device.o edac_mc_sysfs.o edac_pci_sysfs.o
13edac_core-objs += edac_module.o edac_device_sysfs.o 14edac_core-objs += edac_module.o edac_device_sysfs.o
@@ -23,6 +24,7 @@ obj-$(CONFIG_EDAC_CPC925) += cpc925_edac.o
23obj-$(CONFIG_EDAC_I5000) += i5000_edac.o 24obj-$(CONFIG_EDAC_I5000) += i5000_edac.o
24obj-$(CONFIG_EDAC_I5100) += i5100_edac.o 25obj-$(CONFIG_EDAC_I5100) += i5100_edac.o
25obj-$(CONFIG_EDAC_I5400) += i5400_edac.o 26obj-$(CONFIG_EDAC_I5400) += i5400_edac.o
27obj-$(CONFIG_EDAC_I7CORE) += i7core_edac.o
26obj-$(CONFIG_EDAC_E7XXX) += e7xxx_edac.o 28obj-$(CONFIG_EDAC_E7XXX) += e7xxx_edac.o
27obj-$(CONFIG_EDAC_E752X) += e752x_edac.o 29obj-$(CONFIG_EDAC_E752X) += e752x_edac.o
28obj-$(CONFIG_EDAC_I82443BXGX) += i82443bxgx_edac.o 30obj-$(CONFIG_EDAC_I82443BXGX) += i82443bxgx_edac.o
diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h
index 001b2e797fb3..efca9343d26a 100644
--- a/drivers/edac/edac_core.h
+++ b/drivers/edac/edac_core.h
@@ -341,12 +341,30 @@ struct csrow_info {
341 struct channel_info *channels; 341 struct channel_info *channels;
342}; 342};
343 343
344struct mcidev_sysfs_group {
345 const char *name; /* group name */
346 struct mcidev_sysfs_attribute *mcidev_attr; /* group attributes */
347};
348
349struct mcidev_sysfs_group_kobj {
350 struct list_head list; /* list for all instances within a mc */
351
352 struct kobject kobj; /* kobj for the group */
353
354 struct mcidev_sysfs_group *grp; /* group description table */
355 struct mem_ctl_info *mci; /* the parent */
356};
357
344/* mcidev_sysfs_attribute structure 358/* mcidev_sysfs_attribute structure
345 * used for driver sysfs attributes and in mem_ctl_info 359 * used for driver sysfs attributes and in mem_ctl_info
346 * sysfs top level entries 360 * sysfs top level entries
347 */ 361 */
348struct mcidev_sysfs_attribute { 362struct mcidev_sysfs_attribute {
349 struct attribute attr; 363 /* It should use either attr or grp */
364 struct attribute attr;
365 struct mcidev_sysfs_group *grp; /* Points to a group of attributes */
366
367 /* Ops for show/store values at the attribute - not used on group */
350 ssize_t (*show)(struct mem_ctl_info *,char *); 368 ssize_t (*show)(struct mem_ctl_info *,char *);
351 ssize_t (*store)(struct mem_ctl_info *, const char *,size_t); 369 ssize_t (*store)(struct mem_ctl_info *, const char *,size_t);
352}; 370};
@@ -424,6 +442,9 @@ struct mem_ctl_info {
424 /* edac sysfs device control */ 442 /* edac sysfs device control */
425 struct kobject edac_mci_kobj; 443 struct kobject edac_mci_kobj;
426 444
445 /* list for all grp instances within a mc */
446 struct list_head grp_kobj_list;
447
427 /* Additional top controller level attributes, but specified 448 /* Additional top controller level attributes, but specified
428 * by the low level driver. 449 * by the low level driver.
429 * 450 *
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
index 418b65f1a1da..c200c2fd43ea 100644
--- a/drivers/edac/edac_mc_sysfs.c
+++ b/drivers/edac/edac_mc_sysfs.c
@@ -557,6 +557,8 @@ static ssize_t mcidev_show(struct kobject *kobj, struct attribute *attr,
557 struct mem_ctl_info *mem_ctl_info = to_mci(kobj); 557 struct mem_ctl_info *mem_ctl_info = to_mci(kobj);
558 struct mcidev_sysfs_attribute *mcidev_attr = to_mcidev_attr(attr); 558 struct mcidev_sysfs_attribute *mcidev_attr = to_mcidev_attr(attr);
559 559
560 debugf1("%s() mem_ctl_info %p\n", __func__, mem_ctl_info);
561
560 if (mcidev_attr->show) 562 if (mcidev_attr->show)
561 return mcidev_attr->show(mem_ctl_info, buffer); 563 return mcidev_attr->show(mem_ctl_info, buffer);
562 564
@@ -569,6 +571,8 @@ static ssize_t mcidev_store(struct kobject *kobj, struct attribute *attr,
569 struct mem_ctl_info *mem_ctl_info = to_mci(kobj); 571 struct mem_ctl_info *mem_ctl_info = to_mci(kobj);
570 struct mcidev_sysfs_attribute *mcidev_attr = to_mcidev_attr(attr); 572 struct mcidev_sysfs_attribute *mcidev_attr = to_mcidev_attr(attr);
571 573
574 debugf1("%s() mem_ctl_info %p\n", __func__, mem_ctl_info);
575
572 if (mcidev_attr->store) 576 if (mcidev_attr->store)
573 return mcidev_attr->store(mem_ctl_info, buffer, count); 577 return mcidev_attr->store(mem_ctl_info, buffer, count);
574 578
@@ -726,28 +730,118 @@ void edac_mc_unregister_sysfs_main_kobj(struct mem_ctl_info *mci)
726 730
727#define EDAC_DEVICE_SYMLINK "device" 731#define EDAC_DEVICE_SYMLINK "device"
728 732
733#define grp_to_mci(k) (container_of(k, struct mcidev_sysfs_group_kobj, kobj)->mci)
734
735/* MCI show/store functions for top most object */
736static ssize_t inst_grp_show(struct kobject *kobj, struct attribute *attr,
737 char *buffer)
738{
739 struct mem_ctl_info *mem_ctl_info = grp_to_mci(kobj);
740 struct mcidev_sysfs_attribute *mcidev_attr = to_mcidev_attr(attr);
741
742 debugf1("%s() mem_ctl_info %p\n", __func__, mem_ctl_info);
743
744 if (mcidev_attr->show)
745 return mcidev_attr->show(mem_ctl_info, buffer);
746
747 return -EIO;
748}
749
750static ssize_t inst_grp_store(struct kobject *kobj, struct attribute *attr,
751 const char *buffer, size_t count)
752{
753 struct mem_ctl_info *mem_ctl_info = grp_to_mci(kobj);
754 struct mcidev_sysfs_attribute *mcidev_attr = to_mcidev_attr(attr);
755
756 debugf1("%s() mem_ctl_info %p\n", __func__, mem_ctl_info);
757
758 if (mcidev_attr->store)
759 return mcidev_attr->store(mem_ctl_info, buffer, count);
760
761 return -EIO;
762}
763
764/* No memory to release for this kobj */
765static void edac_inst_grp_release(struct kobject *kobj)
766{
767 struct mcidev_sysfs_group_kobj *grp;
768 struct mem_ctl_info *mci;
769
770 debugf1("%s()\n", __func__);
771
772 grp = container_of(kobj, struct mcidev_sysfs_group_kobj, kobj);
773 mci = grp->mci;
774
775 kobject_put(&mci->edac_mci_kobj);
776}
777
778/* Intermediate show/store table */
779static struct sysfs_ops inst_grp_ops = {
780 .show = inst_grp_show,
781 .store = inst_grp_store
782};
783
784/* the kobj_type instance for a instance group */
785static struct kobj_type ktype_inst_grp = {
786 .release = edac_inst_grp_release,
787 .sysfs_ops = &inst_grp_ops,
788};
789
790
729/* 791/*
730 * edac_create_mci_instance_attributes 792 * edac_create_mci_instance_attributes
731 * create MC driver specific attributes at the topmost level 793 * create MC driver specific attributes bellow an specified kobj
732 * directory of this mci instance. 794 * This routine calls itself recursively, in order to create an entire
795 * object tree.
733 */ 796 */
734static int edac_create_mci_instance_attributes(struct mem_ctl_info *mci) 797static int edac_create_mci_instance_attributes(struct mem_ctl_info *mci,
798 struct mcidev_sysfs_attribute *sysfs_attrib,
799 struct kobject *kobj)
735{ 800{
736 int err; 801 int err;
737 struct mcidev_sysfs_attribute *sysfs_attrib;
738 802
739 /* point to the start of the array and iterate over it 803 debugf1("%s()\n", __func__);
740 * adding each attribute listed to this mci instance's kobject 804
741 */ 805 while (sysfs_attrib) {
742 sysfs_attrib = mci->mc_driver_sysfs_attributes; 806 if (sysfs_attrib->grp) {
807 struct mcidev_sysfs_group_kobj *grp_kobj;
808
809 grp_kobj = kzalloc(sizeof(*grp_kobj), GFP_KERNEL);
810 if (!grp_kobj)
811 return -ENOMEM;
812
813 list_add_tail(&grp_kobj->list, &mci->grp_kobj_list);
814
815 grp_kobj->grp = sysfs_attrib->grp;
816 grp_kobj->mci = mci;
817
818 debugf0("%s() grp %s, mci %p\n", __func__,
819 sysfs_attrib->grp->name, mci);
820
821 err = kobject_init_and_add(&grp_kobj->kobj,
822 &ktype_inst_grp,
823 &mci->edac_mci_kobj,
824 sysfs_attrib->grp->name);
825 if (err)
826 return err;
827
828 err = edac_create_mci_instance_attributes(mci,
829 grp_kobj->grp->mcidev_attr,
830 &grp_kobj->kobj);
831
832 if (err)
833 return err;
834 } else if (sysfs_attrib->attr.name) {
835 debugf0("%s() file %s\n", __func__,
836 sysfs_attrib->attr.name);
837
838 err = sysfs_create_file(kobj, &sysfs_attrib->attr);
839 } else
840 break;
743 841
744 while (sysfs_attrib && sysfs_attrib->attr.name) {
745 err = sysfs_create_file(&mci->edac_mci_kobj,
746 (struct attribute*) sysfs_attrib);
747 if (err) { 842 if (err) {
748 return err; 843 return err;
749 } 844 }
750
751 sysfs_attrib++; 845 sysfs_attrib++;
752 } 846 }
753 847
@@ -759,21 +853,44 @@ static int edac_create_mci_instance_attributes(struct mem_ctl_info *mci)
759 * remove MC driver specific attributes at the topmost level 853 * remove MC driver specific attributes at the topmost level
760 * directory of this mci instance. 854 * directory of this mci instance.
761 */ 855 */
762static void edac_remove_mci_instance_attributes(struct mem_ctl_info *mci) 856static void edac_remove_mci_instance_attributes(struct mem_ctl_info *mci,
857 struct mcidev_sysfs_attribute *sysfs_attrib,
858 struct kobject *kobj, int count)
763{ 859{
764 struct mcidev_sysfs_attribute *sysfs_attrib; 860 struct mcidev_sysfs_group_kobj *grp_kobj, *tmp;
765 861
766 /* point to the start of the array and iterate over it 862 debugf1("%s()\n", __func__);
767 * adding each attribute listed to this mci instance's kobject
768 */
769 sysfs_attrib = mci->mc_driver_sysfs_attributes;
770 863
771 /* loop if there are attributes and until we hit a NULL entry */ 864 /*
772 while (sysfs_attrib && sysfs_attrib->attr.name) { 865 * loop if there are attributes and until we hit a NULL entry
773 sysfs_remove_file(&mci->edac_mci_kobj, 866 * Remove first all the atributes
774 (struct attribute *) sysfs_attrib); 867 */
868 while (sysfs_attrib) {
869 if (sysfs_attrib->grp) {
870 list_for_each_entry(grp_kobj, &mci->grp_kobj_list,
871 list)
872 if (grp_kobj->grp == sysfs_attrib->grp)
873 edac_remove_mci_instance_attributes(mci,
874 grp_kobj->grp->mcidev_attr,
875 &grp_kobj->kobj, count + 1);
876 } else if (sysfs_attrib->attr.name) {
877 debugf0("%s() file %s\n", __func__,
878 sysfs_attrib->attr.name);
879 sysfs_remove_file(kobj, &sysfs_attrib->attr);
880 } else
881 break;
775 sysfs_attrib++; 882 sysfs_attrib++;
776 } 883 }
884
885 /*
886 * Now that all attributes got removed, it is save to remove all groups
887 */
888 if (!count)
889 list_for_each_entry_safe(grp_kobj, tmp, &mci->grp_kobj_list,
890 list) {
891 debugf0("%s() grp %s\n", __func__, grp_kobj->grp->name);
892 kobject_put(&grp_kobj->kobj);
893 }
777} 894}
778 895
779 896
@@ -794,6 +911,8 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
794 911
795 debugf0("%s() idx=%d\n", __func__, mci->mc_idx); 912 debugf0("%s() idx=%d\n", __func__, mci->mc_idx);
796 913
914 INIT_LIST_HEAD(&mci->grp_kobj_list);
915
797 /* create a symlink for the device */ 916 /* create a symlink for the device */
798 err = sysfs_create_link(kobj_mci, &mci->dev->kobj, 917 err = sysfs_create_link(kobj_mci, &mci->dev->kobj,
799 EDAC_DEVICE_SYMLINK); 918 EDAC_DEVICE_SYMLINK);
@@ -806,7 +925,9 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
806 * then create them now for the driver. 925 * then create them now for the driver.
807 */ 926 */
808 if (mci->mc_driver_sysfs_attributes) { 927 if (mci->mc_driver_sysfs_attributes) {
809 err = edac_create_mci_instance_attributes(mci); 928 err = edac_create_mci_instance_attributes(mci,
929 mci->mc_driver_sysfs_attributes,
930 &mci->edac_mci_kobj);
810 if (err) { 931 if (err) {
811 debugf1("%s() failure to create mci attributes\n", 932 debugf1("%s() failure to create mci attributes\n",
812 __func__); 933 __func__);
@@ -841,7 +962,8 @@ fail1:
841 } 962 }
842 963
843 /* remove the mci instance's attributes, if any */ 964 /* remove the mci instance's attributes, if any */
844 edac_remove_mci_instance_attributes(mci); 965 edac_remove_mci_instance_attributes(mci,
966 mci->mc_driver_sysfs_attributes, &mci->edac_mci_kobj, 0);
845 967
846 /* remove the symlink */ 968 /* remove the symlink */
847 sysfs_remove_link(kobj_mci, EDAC_DEVICE_SYMLINK); 969 sysfs_remove_link(kobj_mci, EDAC_DEVICE_SYMLINK);
@@ -875,8 +997,9 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
875 debugf0("%s() remove_mci_instance\n", __func__); 997 debugf0("%s() remove_mci_instance\n", __func__);
876 998
877 /* remove this mci instance's attribtes */ 999 /* remove this mci instance's attribtes */
878 edac_remove_mci_instance_attributes(mci); 1000 edac_remove_mci_instance_attributes(mci,
879 1001 mci->mc_driver_sysfs_attributes,
1002 &mci->edac_mci_kobj, 0);
880 debugf0("%s() unregister this mci kobj\n", __func__); 1003 debugf0("%s() unregister this mci kobj\n", __func__);
881 1004
882 /* unregister this instance's kobject */ 1005 /* unregister this instance's kobject */
diff --git a/drivers/edac/edac_mce.c b/drivers/edac/edac_mce.c
new file mode 100644
index 000000000000..9ccdc5b140e7
--- /dev/null
+++ b/drivers/edac/edac_mce.c
@@ -0,0 +1,61 @@
1/* Provides edac interface to mcelog events
2 *
3 * This file may be distributed under the terms of the
4 * GNU General Public License version 2.
5 *
6 * Copyright (c) 2009 by:
7 * Mauro Carvalho Chehab <mchehab@redhat.com>
8 *
9 * Red Hat Inc. http://www.redhat.com
10 */
11
12#include <linux/module.h>
13#include <linux/edac_mce.h>
14#include <asm/mce.h>
15
16int edac_mce_enabled;
17EXPORT_SYMBOL_GPL(edac_mce_enabled);
18
19
20/*
21 * Extension interface
22 */
23
24static LIST_HEAD(edac_mce_list);
25static DEFINE_MUTEX(edac_mce_lock);
26
27int edac_mce_register(struct edac_mce *edac_mce)
28{
29 mutex_lock(&edac_mce_lock);
30 list_add_tail(&edac_mce->list, &edac_mce_list);
31 mutex_unlock(&edac_mce_lock);
32 return 0;
33}
34EXPORT_SYMBOL(edac_mce_register);
35
36void edac_mce_unregister(struct edac_mce *edac_mce)
37{
38 mutex_lock(&edac_mce_lock);
39 list_del(&edac_mce->list);
40 mutex_unlock(&edac_mce_lock);
41}
42EXPORT_SYMBOL(edac_mce_unregister);
43
44int edac_mce_parse(struct mce *mce)
45{
46 struct edac_mce *edac_mce;
47
48 list_for_each_entry(edac_mce, &edac_mce_list, list) {
49 if (edac_mce->check_error(edac_mce->priv, mce))
50 return 1;
51 }
52
53 /* Nobody queued the error */
54 return 0;
55}
56EXPORT_SYMBOL_GPL(edac_mce_parse);
57
58MODULE_LICENSE("GPL");
59MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
60MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
61MODULE_DESCRIPTION("EDAC Driver for mcelog captured errors");
diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c
index adc10a2ac5f6..996c1bdb5a34 100644
--- a/drivers/edac/i5000_edac.c
+++ b/drivers/edac/i5000_edac.c
@@ -774,7 +774,7 @@ static void i5000_clear_error(struct mem_ctl_info *mci)
774static void i5000_check_error(struct mem_ctl_info *mci) 774static void i5000_check_error(struct mem_ctl_info *mci)
775{ 775{
776 struct i5000_error_info info; 776 struct i5000_error_info info;
777 debugf4("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__); 777 debugf4("MC%d: %s: %s()\n", mci->mc_idx, __FILE__, __func__);
778 i5000_get_error_info(mci, &info); 778 i5000_get_error_info(mci, &info);
779 i5000_process_error_info(mci, &info, 1); 779 i5000_process_error_info(mci, &info, 1);
780} 780}
@@ -1353,8 +1353,8 @@ static int i5000_probe1(struct pci_dev *pdev, int dev_idx)
1353 int num_dimms_per_channel; 1353 int num_dimms_per_channel;
1354 int num_csrows; 1354 int num_csrows;
1355 1355
1356 debugf0("MC: " __FILE__ ": %s(), pdev bus %u dev=0x%x fn=0x%x\n", 1356 debugf0("MC: %s: %s(), pdev bus %u dev=0x%x fn=0x%x\n",
1357 __func__, 1357 __FILE__, __func__,
1358 pdev->bus->number, 1358 pdev->bus->number,
1359 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); 1359 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
1360 1360
@@ -1389,7 +1389,7 @@ static int i5000_probe1(struct pci_dev *pdev, int dev_idx)
1389 return -ENOMEM; 1389 return -ENOMEM;
1390 1390
1391 kobject_get(&mci->edac_mci_kobj); 1391 kobject_get(&mci->edac_mci_kobj);
1392 debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci); 1392 debugf0("MC: %s: %s(): mci = %p\n", __FILE__, __func__, mci);
1393 1393
1394 mci->dev = &pdev->dev; /* record ptr to the generic device */ 1394 mci->dev = &pdev->dev; /* record ptr to the generic device */
1395 1395
@@ -1432,8 +1432,8 @@ static int i5000_probe1(struct pci_dev *pdev, int dev_idx)
1432 1432
1433 /* add this new MC control structure to EDAC's list of MCs */ 1433 /* add this new MC control structure to EDAC's list of MCs */
1434 if (edac_mc_add_mc(mci)) { 1434 if (edac_mc_add_mc(mci)) {
1435 debugf0("MC: " __FILE__ 1435 debugf0("MC: %s: %s(): failed edac_mc_add_mc()\n",
1436 ": %s(): failed edac_mc_add_mc()\n", __func__); 1436 __FILE__, __func__);
1437 /* FIXME: perhaps some code should go here that disables error 1437 /* FIXME: perhaps some code should go here that disables error
1438 * reporting if we just enabled it 1438 * reporting if we just enabled it
1439 */ 1439 */
@@ -1478,7 +1478,7 @@ static int __devinit i5000_init_one(struct pci_dev *pdev,
1478{ 1478{
1479 int rc; 1479 int rc;
1480 1480
1481 debugf0("MC: " __FILE__ ": %s()\n", __func__); 1481 debugf0("MC: %s: %s()\n", __FILE__, __func__);
1482 1482
1483 /* wake up device */ 1483 /* wake up device */
1484 rc = pci_enable_device(pdev); 1484 rc = pci_enable_device(pdev);
@@ -1497,7 +1497,7 @@ static void __devexit i5000_remove_one(struct pci_dev *pdev)
1497{ 1497{
1498 struct mem_ctl_info *mci; 1498 struct mem_ctl_info *mci;
1499 1499
1500 debugf0(__FILE__ ": %s()\n", __func__); 1500 debugf0("%s: %s()\n", __FILE__, __func__);
1501 1501
1502 if (i5000_pci) 1502 if (i5000_pci)
1503 edac_pci_release_generic_ctl(i5000_pci); 1503 edac_pci_release_generic_ctl(i5000_pci);
@@ -1544,7 +1544,7 @@ static int __init i5000_init(void)
1544{ 1544{
1545 int pci_rc; 1545 int pci_rc;
1546 1546
1547 debugf2("MC: " __FILE__ ": %s()\n", __func__); 1547 debugf2("MC: %s: %s()\n", __FILE__, __func__);
1548 1548
1549 /* Ensure that the OPSTATE is set correctly for POLL or NMI */ 1549 /* Ensure that the OPSTATE is set correctly for POLL or NMI */
1550 opstate_init(); 1550 opstate_init();
@@ -1560,7 +1560,7 @@ static int __init i5000_init(void)
1560 */ 1560 */
1561static void __exit i5000_exit(void) 1561static void __exit i5000_exit(void)
1562{ 1562{
1563 debugf2("MC: " __FILE__ ": %s()\n", __func__); 1563 debugf2("MC: %s: %s()\n", __FILE__, __func__);
1564 pci_unregister_driver(&i5000_driver); 1564 pci_unregister_driver(&i5000_driver);
1565} 1565}
1566 1566
diff --git a/drivers/edac/i5400_edac.c b/drivers/edac/i5400_edac.c
index f99d10655ed4..010c1d6526f5 100644
--- a/drivers/edac/i5400_edac.c
+++ b/drivers/edac/i5400_edac.c
@@ -694,7 +694,7 @@ static void i5400_clear_error(struct mem_ctl_info *mci)
694static void i5400_check_error(struct mem_ctl_info *mci) 694static void i5400_check_error(struct mem_ctl_info *mci)
695{ 695{
696 struct i5400_error_info info; 696 struct i5400_error_info info;
697 debugf4("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__); 697 debugf4("MC%d: %s: %s()\n", mci->mc_idx, __FILE__, __func__);
698 i5400_get_error_info(mci, &info); 698 i5400_get_error_info(mci, &info);
699 i5400_process_error_info(mci, &info); 699 i5400_process_error_info(mci, &info);
700} 700}
@@ -1227,8 +1227,8 @@ static int i5400_probe1(struct pci_dev *pdev, int dev_idx)
1227 if (dev_idx >= ARRAY_SIZE(i5400_devs)) 1227 if (dev_idx >= ARRAY_SIZE(i5400_devs))
1228 return -EINVAL; 1228 return -EINVAL;
1229 1229
1230 debugf0("MC: " __FILE__ ": %s(), pdev bus %u dev=0x%x fn=0x%x\n", 1230 debugf0("MC: %s: %s(), pdev bus %u dev=0x%x fn=0x%x\n",
1231 __func__, 1231 __FILE__, __func__,
1232 pdev->bus->number, 1232 pdev->bus->number,
1233 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); 1233 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
1234 1234
@@ -1256,7 +1256,7 @@ static int i5400_probe1(struct pci_dev *pdev, int dev_idx)
1256 if (mci == NULL) 1256 if (mci == NULL)
1257 return -ENOMEM; 1257 return -ENOMEM;
1258 1258
1259 debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci); 1259 debugf0("MC: %s: %s(): mci = %p\n", __FILE__, __func__, mci);
1260 1260
1261 mci->dev = &pdev->dev; /* record ptr to the generic device */ 1261 mci->dev = &pdev->dev; /* record ptr to the generic device */
1262 1262
@@ -1299,8 +1299,8 @@ static int i5400_probe1(struct pci_dev *pdev, int dev_idx)
1299 1299
1300 /* add this new MC control structure to EDAC's list of MCs */ 1300 /* add this new MC control structure to EDAC's list of MCs */
1301 if (edac_mc_add_mc(mci)) { 1301 if (edac_mc_add_mc(mci)) {
1302 debugf0("MC: " __FILE__ 1302 debugf0("MC: %s: %s(): failed edac_mc_add_mc()\n",
1303 ": %s(): failed edac_mc_add_mc()\n", __func__); 1303 __FILE__, __func__);
1304 /* FIXME: perhaps some code should go here that disables error 1304 /* FIXME: perhaps some code should go here that disables error
1305 * reporting if we just enabled it 1305 * reporting if we just enabled it
1306 */ 1306 */
@@ -1344,7 +1344,7 @@ static int __devinit i5400_init_one(struct pci_dev *pdev,
1344{ 1344{
1345 int rc; 1345 int rc;
1346 1346
1347 debugf0("MC: " __FILE__ ": %s()\n", __func__); 1347 debugf0("MC: %s: %s()\n", __FILE__, __func__);
1348 1348
1349 /* wake up device */ 1349 /* wake up device */
1350 rc = pci_enable_device(pdev); 1350 rc = pci_enable_device(pdev);
@@ -1363,7 +1363,7 @@ static void __devexit i5400_remove_one(struct pci_dev *pdev)
1363{ 1363{
1364 struct mem_ctl_info *mci; 1364 struct mem_ctl_info *mci;
1365 1365
1366 debugf0(__FILE__ ": %s()\n", __func__); 1366 debugf0("%s: %s()\n", __FILE__, __func__);
1367 1367
1368 if (i5400_pci) 1368 if (i5400_pci)
1369 edac_pci_release_generic_ctl(i5400_pci); 1369 edac_pci_release_generic_ctl(i5400_pci);
@@ -1409,7 +1409,7 @@ static int __init i5400_init(void)
1409{ 1409{
1410 int pci_rc; 1410 int pci_rc;
1411 1411
1412 debugf2("MC: " __FILE__ ": %s()\n", __func__); 1412 debugf2("MC: %s: %s()\n", __FILE__, __func__);
1413 1413
1414 /* Ensure that the OPSTATE is set correctly for POLL or NMI */ 1414 /* Ensure that the OPSTATE is set correctly for POLL or NMI */
1415 opstate_init(); 1415 opstate_init();
@@ -1425,7 +1425,7 @@ static int __init i5400_init(void)
1425 */ 1425 */
1426static void __exit i5400_exit(void) 1426static void __exit i5400_exit(void)
1427{ 1427{
1428 debugf2("MC: " __FILE__ ": %s()\n", __func__); 1428 debugf2("MC: %s: %s()\n", __FILE__, __func__);
1429 pci_unregister_driver(&i5400_driver); 1429 pci_unregister_driver(&i5400_driver);
1430} 1430}
1431 1431
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c
new file mode 100644
index 000000000000..6b8b7b41ec5f
--- /dev/null
+++ b/drivers/edac/i7core_edac.c
@@ -0,0 +1,2078 @@
1/* Intel i7 core/Nehalem Memory Controller kernel module
2 *
3 * This driver supports yhe memory controllers found on the Intel
4 * processor families i7core, i7core 7xx/8xx, i5core, Xeon 35xx,
5 * Xeon 55xx and Xeon 56xx also known as Nehalem, Nehalem-EP, Lynnfield
6 * and Westmere-EP.
7 *
8 * This file may be distributed under the terms of the
9 * GNU General Public License version 2 only.
10 *
11 * Copyright (c) 2009-2010 by:
12 * Mauro Carvalho Chehab <mchehab@redhat.com>
13 *
14 * Red Hat Inc. http://www.redhat.com
15 *
16 * Forked and adapted from the i5400_edac driver
17 *
18 * Based on the following public Intel datasheets:
19 * Intel Core i7 Processor Extreme Edition and Intel Core i7 Processor
20 * Datasheet, Volume 2:
21 * http://download.intel.com/design/processor/datashts/320835.pdf
22 * Intel Xeon Processor 5500 Series Datasheet Volume 2
23 * http://www.intel.com/Assets/PDF/datasheet/321322.pdf
24 * also available at:
25 * http://www.arrownac.com/manufacturers/intel/s/nehalem/5500-datasheet-v2.pdf
26 */
27
28#include <linux/module.h>
29#include <linux/init.h>
30#include <linux/pci.h>
31#include <linux/pci_ids.h>
32#include <linux/slab.h>
33#include <linux/delay.h>
34#include <linux/edac.h>
35#include <linux/mmzone.h>
36#include <linux/edac_mce.h>
37#include <linux/smp.h>
38#include <asm/processor.h>
39
40#include "edac_core.h"
41
42/*
43 * This is used for Nehalem-EP and Nehalem-EX devices, where the non-core
44 * registers start at bus 255, and are not reported by BIOS.
45 * We currently find devices with only 2 sockets. In order to support more QPI
46 * Quick Path Interconnect, just increment this number.
47 */
48#define MAX_SOCKET_BUSES 2
49
50
51/*
52 * Alter this version for the module when modifications are made
53 */
54#define I7CORE_REVISION " Ver: 1.0.0 " __DATE__
55#define EDAC_MOD_STR "i7core_edac"
56
57/*
58 * Debug macros
59 */
60#define i7core_printk(level, fmt, arg...) \
61 edac_printk(level, "i7core", fmt, ##arg)
62
63#define i7core_mc_printk(mci, level, fmt, arg...) \
64 edac_mc_chipset_printk(mci, level, "i7core", fmt, ##arg)
65
66/*
67 * i7core Memory Controller Registers
68 */
69
70 /* OFFSETS for Device 0 Function 0 */
71
72#define MC_CFG_CONTROL 0x90
73
74 /* OFFSETS for Device 3 Function 0 */
75
76#define MC_CONTROL 0x48
77#define MC_STATUS 0x4c
78#define MC_MAX_DOD 0x64
79
80/*
81 * OFFSETS for Device 3 Function 4, as inicated on Xeon 5500 datasheet:
82 * http://www.arrownac.com/manufacturers/intel/s/nehalem/5500-datasheet-v2.pdf
83 */
84
85#define MC_TEST_ERR_RCV1 0x60
86 #define DIMM2_COR_ERR(r) ((r) & 0x7fff)
87
88#define MC_TEST_ERR_RCV0 0x64
89 #define DIMM1_COR_ERR(r) (((r) >> 16) & 0x7fff)
90 #define DIMM0_COR_ERR(r) ((r) & 0x7fff)
91
92/* OFFSETS for Device 3 Function 2, as inicated on Xeon 5500 datasheet */
93#define MC_COR_ECC_CNT_0 0x80
94#define MC_COR_ECC_CNT_1 0x84
95#define MC_COR_ECC_CNT_2 0x88
96#define MC_COR_ECC_CNT_3 0x8c
97#define MC_COR_ECC_CNT_4 0x90
98#define MC_COR_ECC_CNT_5 0x94
99
100#define DIMM_TOP_COR_ERR(r) (((r) >> 16) & 0x7fff)
101#define DIMM_BOT_COR_ERR(r) ((r) & 0x7fff)
102
103
104 /* OFFSETS for Devices 4,5 and 6 Function 0 */
105
106#define MC_CHANNEL_DIMM_INIT_PARAMS 0x58
107 #define THREE_DIMMS_PRESENT (1 << 24)
108 #define SINGLE_QUAD_RANK_PRESENT (1 << 23)
109 #define QUAD_RANK_PRESENT (1 << 22)
110 #define REGISTERED_DIMM (1 << 15)
111
112#define MC_CHANNEL_MAPPER 0x60
113 #define RDLCH(r, ch) ((((r) >> (3 + (ch * 6))) & 0x07) - 1)
114 #define WRLCH(r, ch) ((((r) >> (ch * 6)) & 0x07) - 1)
115
116#define MC_CHANNEL_RANK_PRESENT 0x7c
117 #define RANK_PRESENT_MASK 0xffff
118
119#define MC_CHANNEL_ADDR_MATCH 0xf0
120#define MC_CHANNEL_ERROR_MASK 0xf8
121#define MC_CHANNEL_ERROR_INJECT 0xfc
122 #define INJECT_ADDR_PARITY 0x10
123 #define INJECT_ECC 0x08
124 #define MASK_CACHELINE 0x06
125 #define MASK_FULL_CACHELINE 0x06
126 #define MASK_MSB32_CACHELINE 0x04
127 #define MASK_LSB32_CACHELINE 0x02
128 #define NO_MASK_CACHELINE 0x00
129 #define REPEAT_EN 0x01
130
131 /* OFFSETS for Devices 4,5 and 6 Function 1 */
132
133#define MC_DOD_CH_DIMM0 0x48
134#define MC_DOD_CH_DIMM1 0x4c
135#define MC_DOD_CH_DIMM2 0x50
136 #define RANKOFFSET_MASK ((1 << 12) | (1 << 11) | (1 << 10))
137 #define RANKOFFSET(x) ((x & RANKOFFSET_MASK) >> 10)
138 #define DIMM_PRESENT_MASK (1 << 9)
139 #define DIMM_PRESENT(x) (((x) & DIMM_PRESENT_MASK) >> 9)
140 #define MC_DOD_NUMBANK_MASK ((1 << 8) | (1 << 7))
141 #define MC_DOD_NUMBANK(x) (((x) & MC_DOD_NUMBANK_MASK) >> 7)
142 #define MC_DOD_NUMRANK_MASK ((1 << 6) | (1 << 5))
143 #define MC_DOD_NUMRANK(x) (((x) & MC_DOD_NUMRANK_MASK) >> 5)
144 #define MC_DOD_NUMROW_MASK ((1 << 4) | (1 << 3) | (1 << 2))
145 #define MC_DOD_NUMROW(x) (((x) & MC_DOD_NUMROW_MASK) >> 2)
146 #define MC_DOD_NUMCOL_MASK 3
147 #define MC_DOD_NUMCOL(x) ((x) & MC_DOD_NUMCOL_MASK)
148
149#define MC_RANK_PRESENT 0x7c
150
151#define MC_SAG_CH_0 0x80
152#define MC_SAG_CH_1 0x84
153#define MC_SAG_CH_2 0x88
154#define MC_SAG_CH_3 0x8c
155#define MC_SAG_CH_4 0x90
156#define MC_SAG_CH_5 0x94
157#define MC_SAG_CH_6 0x98
158#define MC_SAG_CH_7 0x9c
159
160#define MC_RIR_LIMIT_CH_0 0x40
161#define MC_RIR_LIMIT_CH_1 0x44
162#define MC_RIR_LIMIT_CH_2 0x48
163#define MC_RIR_LIMIT_CH_3 0x4C
164#define MC_RIR_LIMIT_CH_4 0x50
165#define MC_RIR_LIMIT_CH_5 0x54
166#define MC_RIR_LIMIT_CH_6 0x58
167#define MC_RIR_LIMIT_CH_7 0x5C
168#define MC_RIR_LIMIT_MASK ((1 << 10) - 1)
169
170#define MC_RIR_WAY_CH 0x80
171 #define MC_RIR_WAY_OFFSET_MASK (((1 << 14) - 1) & ~0x7)
172 #define MC_RIR_WAY_RANK_MASK 0x7
173
174/*
175 * i7core structs
176 */
177
178#define NUM_CHANS 3
179#define MAX_DIMMS 3 /* Max DIMMS per channel */
180#define MAX_MCR_FUNC 4
181#define MAX_CHAN_FUNC 3
182
183struct i7core_info {
184 u32 mc_control;
185 u32 mc_status;
186 u32 max_dod;
187 u32 ch_map;
188};
189
190
191struct i7core_inject {
192 int enable;
193
194 u32 section;
195 u32 type;
196 u32 eccmask;
197
198 /* Error address mask */
199 int channel, dimm, rank, bank, page, col;
200};
201
202struct i7core_channel {
203 u32 ranks;
204 u32 dimms;
205};
206
207struct pci_id_descr {
208 int dev;
209 int func;
210 int dev_id;
211 int optional;
212};
213
214struct pci_id_table {
215 struct pci_id_descr *descr;
216 int n_devs;
217};
218
219struct i7core_dev {
220 struct list_head list;
221 u8 socket;
222 struct pci_dev **pdev;
223 int n_devs;
224 struct mem_ctl_info *mci;
225};
226
227struct i7core_pvt {
228 struct pci_dev *pci_noncore;
229 struct pci_dev *pci_mcr[MAX_MCR_FUNC + 1];
230 struct pci_dev *pci_ch[NUM_CHANS][MAX_CHAN_FUNC + 1];
231
232 struct i7core_dev *i7core_dev;
233
234 struct i7core_info info;
235 struct i7core_inject inject;
236 struct i7core_channel channel[NUM_CHANS];
237
238 int channels; /* Number of active channels */
239
240 int ce_count_available;
241 int csrow_map[NUM_CHANS][MAX_DIMMS];
242
243 /* ECC corrected errors counts per udimm */
244 unsigned long udimm_ce_count[MAX_DIMMS];
245 int udimm_last_ce_count[MAX_DIMMS];
246 /* ECC corrected errors counts per rdimm */
247 unsigned long rdimm_ce_count[NUM_CHANS][MAX_DIMMS];
248 int rdimm_last_ce_count[NUM_CHANS][MAX_DIMMS];
249
250 unsigned int is_registered;
251
252 /* mcelog glue */
253 struct edac_mce edac_mce;
254
255 /* Fifo double buffers */
256 struct mce mce_entry[MCE_LOG_LEN];
257 struct mce mce_outentry[MCE_LOG_LEN];
258
259 /* Fifo in/out counters */
260 unsigned mce_in, mce_out;
261
262 /* Count indicator to show errors not got */
263 unsigned mce_overrun;
264};
265
266/* Static vars */
267static LIST_HEAD(i7core_edac_list);
268static DEFINE_MUTEX(i7core_edac_lock);
269
270#define PCI_DESCR(device, function, device_id) \
271 .dev = (device), \
272 .func = (function), \
273 .dev_id = (device_id)
274
275struct pci_id_descr pci_dev_descr_i7core_nehalem[] = {
276 /* Memory controller */
277 { PCI_DESCR(3, 0, PCI_DEVICE_ID_INTEL_I7_MCR) },
278 { PCI_DESCR(3, 1, PCI_DEVICE_ID_INTEL_I7_MC_TAD) },
279 /* Exists only for RDIMM */
280 { PCI_DESCR(3, 2, PCI_DEVICE_ID_INTEL_I7_MC_RAS), .optional = 1 },
281 { PCI_DESCR(3, 4, PCI_DEVICE_ID_INTEL_I7_MC_TEST) },
282
283 /* Channel 0 */
284 { PCI_DESCR(4, 0, PCI_DEVICE_ID_INTEL_I7_MC_CH0_CTRL) },
285 { PCI_DESCR(4, 1, PCI_DEVICE_ID_INTEL_I7_MC_CH0_ADDR) },
286 { PCI_DESCR(4, 2, PCI_DEVICE_ID_INTEL_I7_MC_CH0_RANK) },
287 { PCI_DESCR(4, 3, PCI_DEVICE_ID_INTEL_I7_MC_CH0_TC) },
288
289 /* Channel 1 */
290 { PCI_DESCR(5, 0, PCI_DEVICE_ID_INTEL_I7_MC_CH1_CTRL) },
291 { PCI_DESCR(5, 1, PCI_DEVICE_ID_INTEL_I7_MC_CH1_ADDR) },
292 { PCI_DESCR(5, 2, PCI_DEVICE_ID_INTEL_I7_MC_CH1_RANK) },
293 { PCI_DESCR(5, 3, PCI_DEVICE_ID_INTEL_I7_MC_CH1_TC) },
294
295 /* Channel 2 */
296 { PCI_DESCR(6, 0, PCI_DEVICE_ID_INTEL_I7_MC_CH2_CTRL) },
297 { PCI_DESCR(6, 1, PCI_DEVICE_ID_INTEL_I7_MC_CH2_ADDR) },
298 { PCI_DESCR(6, 2, PCI_DEVICE_ID_INTEL_I7_MC_CH2_RANK) },
299 { PCI_DESCR(6, 3, PCI_DEVICE_ID_INTEL_I7_MC_CH2_TC) },
300
301 /* Generic Non-core registers */
302 /*
303 * This is the PCI device on i7core and on Xeon 35xx (8086:2c41)
304 * On Xeon 55xx, however, it has a different id (8086:2c40). So,
305 * the probing code needs to test for the other address in case of
306 * failure of this one
307 */
308 { PCI_DESCR(0, 0, PCI_DEVICE_ID_INTEL_I7_NONCORE) },
309
310};
311
312struct pci_id_descr pci_dev_descr_lynnfield[] = {
313 { PCI_DESCR( 3, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_MCR) },
314 { PCI_DESCR( 3, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TAD) },
315 { PCI_DESCR( 3, 4, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TEST) },
316
317 { PCI_DESCR( 4, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_CTRL) },
318 { PCI_DESCR( 4, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_ADDR) },
319 { PCI_DESCR( 4, 2, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_RANK) },
320 { PCI_DESCR( 4, 3, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_TC) },
321
322 { PCI_DESCR( 5, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_CTRL) },
323 { PCI_DESCR( 5, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_ADDR) },
324 { PCI_DESCR( 5, 2, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_RANK) },
325 { PCI_DESCR( 5, 3, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_TC) },
326
327 /*
328 * This is the PCI device has an alternate address on some
329 * processors like Core i7 860
330 */
331 { PCI_DESCR( 0, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE) },
332};
333
334struct pci_id_descr pci_dev_descr_i7core_westmere[] = {
335 /* Memory controller */
336 { PCI_DESCR(3, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_MCR_REV2) },
337 { PCI_DESCR(3, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TAD_REV2) },
338 /* Exists only for RDIMM */
339 { PCI_DESCR(3, 2, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_RAS_REV2), .optional = 1 },
340 { PCI_DESCR(3, 4, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TEST_REV2) },
341
342 /* Channel 0 */
343 { PCI_DESCR(4, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_CTRL_REV2) },
344 { PCI_DESCR(4, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_ADDR_REV2) },
345 { PCI_DESCR(4, 2, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_RANK_REV2) },
346 { PCI_DESCR(4, 3, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_TC_REV2) },
347
348 /* Channel 1 */
349 { PCI_DESCR(5, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_CTRL_REV2) },
350 { PCI_DESCR(5, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_ADDR_REV2) },
351 { PCI_DESCR(5, 2, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_RANK_REV2) },
352 { PCI_DESCR(5, 3, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_TC_REV2) },
353
354 /* Channel 2 */
355 { PCI_DESCR(6, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_CTRL_REV2) },
356 { PCI_DESCR(6, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_ADDR_REV2) },
357 { PCI_DESCR(6, 2, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_RANK_REV2) },
358 { PCI_DESCR(6, 3, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_TC_REV2) },
359
360 /* Generic Non-core registers */
361 { PCI_DESCR(0, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_REV2) },
362
363};
364
365#define PCI_ID_TABLE_ENTRY(A) { A, ARRAY_SIZE(A) }
366struct pci_id_table pci_dev_table[] = {
367 PCI_ID_TABLE_ENTRY(pci_dev_descr_i7core_nehalem),
368 PCI_ID_TABLE_ENTRY(pci_dev_descr_lynnfield),
369 PCI_ID_TABLE_ENTRY(pci_dev_descr_i7core_westmere),
370};
371
372/*
373 * pci_device_id table for which devices we are looking for
374 */
375static const struct pci_device_id i7core_pci_tbl[] __devinitdata = {
376 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_X58_HUB_MGMT)},
377 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNNFIELD_QPI_LINK0)},
378 {0,} /* 0 terminated list. */
379};
380
381static struct edac_pci_ctl_info *i7core_pci;
382
383/****************************************************************************
384 Anciliary status routines
385 ****************************************************************************/
386
387 /* MC_CONTROL bits */
388#define CH_ACTIVE(pvt, ch) ((pvt)->info.mc_control & (1 << (8 + ch)))
389#define ECCx8(pvt) ((pvt)->info.mc_control & (1 << 1))
390
391 /* MC_STATUS bits */
392#define ECC_ENABLED(pvt) ((pvt)->info.mc_status & (1 << 4))
393#define CH_DISABLED(pvt, ch) ((pvt)->info.mc_status & (1 << ch))
394
395 /* MC_MAX_DOD read functions */
396static inline int numdimms(u32 dimms)
397{
398 return (dimms & 0x3) + 1;
399}
400
401static inline int numrank(u32 rank)
402{
403 static int ranks[4] = { 1, 2, 4, -EINVAL };
404
405 return ranks[rank & 0x3];
406}
407
408static inline int numbank(u32 bank)
409{
410 static int banks[4] = { 4, 8, 16, -EINVAL };
411
412 return banks[bank & 0x3];
413}
414
415static inline int numrow(u32 row)
416{
417 static int rows[8] = {
418 1 << 12, 1 << 13, 1 << 14, 1 << 15,
419 1 << 16, -EINVAL, -EINVAL, -EINVAL,
420 };
421
422 return rows[row & 0x7];
423}
424
425static inline int numcol(u32 col)
426{
427 static int cols[8] = {
428 1 << 10, 1 << 11, 1 << 12, -EINVAL,
429 };
430 return cols[col & 0x3];
431}
432
433static struct i7core_dev *get_i7core_dev(u8 socket)
434{
435 struct i7core_dev *i7core_dev;
436
437 list_for_each_entry(i7core_dev, &i7core_edac_list, list) {
438 if (i7core_dev->socket == socket)
439 return i7core_dev;
440 }
441
442 return NULL;
443}
444
445/****************************************************************************
446 Memory check routines
447 ****************************************************************************/
448static struct pci_dev *get_pdev_slot_func(u8 socket, unsigned slot,
449 unsigned func)
450{
451 struct i7core_dev *i7core_dev = get_i7core_dev(socket);
452 int i;
453
454 if (!i7core_dev)
455 return NULL;
456
457 for (i = 0; i < i7core_dev->n_devs; i++) {
458 if (!i7core_dev->pdev[i])
459 continue;
460
461 if (PCI_SLOT(i7core_dev->pdev[i]->devfn) == slot &&
462 PCI_FUNC(i7core_dev->pdev[i]->devfn) == func) {
463 return i7core_dev->pdev[i];
464 }
465 }
466
467 return NULL;
468}
469
470/**
471 * i7core_get_active_channels() - gets the number of channels and csrows
472 * @socket: Quick Path Interconnect socket
473 * @channels: Number of channels that will be returned
474 * @csrows: Number of csrows found
475 *
476 * Since EDAC core needs to know in advance the number of available channels
477 * and csrows, in order to allocate memory for csrows/channels, it is needed
478 * to run two similar steps. At the first step, implemented on this function,
479 * it checks the number of csrows/channels present at one socket.
480 * this is used in order to properly allocate the size of mci components.
481 *
482 * It should be noticed that none of the current available datasheets explain
483 * or even mention how csrows are seen by the memory controller. So, we need
484 * to add a fake description for csrows.
485 * So, this driver is attributing one DIMM memory for one csrow.
486 */
487static int i7core_get_active_channels(u8 socket, unsigned *channels,
488 unsigned *csrows)
489{
490 struct pci_dev *pdev = NULL;
491 int i, j;
492 u32 status, control;
493
494 *channels = 0;
495 *csrows = 0;
496
497 pdev = get_pdev_slot_func(socket, 3, 0);
498 if (!pdev) {
499 i7core_printk(KERN_ERR, "Couldn't find socket %d fn 3.0!!!\n",
500 socket);
501 return -ENODEV;
502 }
503
504 /* Device 3 function 0 reads */
505 pci_read_config_dword(pdev, MC_STATUS, &status);
506 pci_read_config_dword(pdev, MC_CONTROL, &control);
507
508 for (i = 0; i < NUM_CHANS; i++) {
509 u32 dimm_dod[3];
510 /* Check if the channel is active */
511 if (!(control & (1 << (8 + i))))
512 continue;
513
514 /* Check if the channel is disabled */
515 if (status & (1 << i))
516 continue;
517
518 pdev = get_pdev_slot_func(socket, i + 4, 1);
519 if (!pdev) {
520 i7core_printk(KERN_ERR, "Couldn't find socket %d "
521 "fn %d.%d!!!\n",
522 socket, i + 4, 1);
523 return -ENODEV;
524 }
525 /* Devices 4-6 function 1 */
526 pci_read_config_dword(pdev,
527 MC_DOD_CH_DIMM0, &dimm_dod[0]);
528 pci_read_config_dword(pdev,
529 MC_DOD_CH_DIMM1, &dimm_dod[1]);
530 pci_read_config_dword(pdev,
531 MC_DOD_CH_DIMM2, &dimm_dod[2]);
532
533 (*channels)++;
534
535 for (j = 0; j < 3; j++) {
536 if (!DIMM_PRESENT(dimm_dod[j]))
537 continue;
538 (*csrows)++;
539 }
540 }
541
542 debugf0("Number of active channels on socket %d: %d\n",
543 socket, *channels);
544
545 return 0;
546}
547
548static int get_dimm_config(struct mem_ctl_info *mci, int *csrow)
549{
550 struct i7core_pvt *pvt = mci->pvt_info;
551 struct csrow_info *csr;
552 struct pci_dev *pdev;
553 int i, j;
554 unsigned long last_page = 0;
555 enum edac_type mode;
556 enum mem_type mtype;
557
558 /* Get data from the MC register, function 0 */
559 pdev = pvt->pci_mcr[0];
560 if (!pdev)
561 return -ENODEV;
562
563 /* Device 3 function 0 reads */
564 pci_read_config_dword(pdev, MC_CONTROL, &pvt->info.mc_control);
565 pci_read_config_dword(pdev, MC_STATUS, &pvt->info.mc_status);
566 pci_read_config_dword(pdev, MC_MAX_DOD, &pvt->info.max_dod);
567 pci_read_config_dword(pdev, MC_CHANNEL_MAPPER, &pvt->info.ch_map);
568
569 debugf0("QPI %d control=0x%08x status=0x%08x dod=0x%08x map=0x%08x\n",
570 pvt->i7core_dev->socket, pvt->info.mc_control, pvt->info.mc_status,
571 pvt->info.max_dod, pvt->info.ch_map);
572
573 if (ECC_ENABLED(pvt)) {
574 debugf0("ECC enabled with x%d SDCC\n", ECCx8(pvt) ? 8 : 4);
575 if (ECCx8(pvt))
576 mode = EDAC_S8ECD8ED;
577 else
578 mode = EDAC_S4ECD4ED;
579 } else {
580 debugf0("ECC disabled\n");
581 mode = EDAC_NONE;
582 }
583
584 /* FIXME: need to handle the error codes */
585 debugf0("DOD Max limits: DIMMS: %d, %d-ranked, %d-banked "
586 "x%x x 0x%x\n",
587 numdimms(pvt->info.max_dod),
588 numrank(pvt->info.max_dod >> 2),
589 numbank(pvt->info.max_dod >> 4),
590 numrow(pvt->info.max_dod >> 6),
591 numcol(pvt->info.max_dod >> 9));
592
593 for (i = 0; i < NUM_CHANS; i++) {
594 u32 data, dimm_dod[3], value[8];
595
596 if (!pvt->pci_ch[i][0])
597 continue;
598
599 if (!CH_ACTIVE(pvt, i)) {
600 debugf0("Channel %i is not active\n", i);
601 continue;
602 }
603 if (CH_DISABLED(pvt, i)) {
604 debugf0("Channel %i is disabled\n", i);
605 continue;
606 }
607
608 /* Devices 4-6 function 0 */
609 pci_read_config_dword(pvt->pci_ch[i][0],
610 MC_CHANNEL_DIMM_INIT_PARAMS, &data);
611
612 pvt->channel[i].ranks = (data & QUAD_RANK_PRESENT) ?
613 4 : 2;
614
615 if (data & REGISTERED_DIMM)
616 mtype = MEM_RDDR3;
617 else
618 mtype = MEM_DDR3;
619#if 0
620 if (data & THREE_DIMMS_PRESENT)
621 pvt->channel[i].dimms = 3;
622 else if (data & SINGLE_QUAD_RANK_PRESENT)
623 pvt->channel[i].dimms = 1;
624 else
625 pvt->channel[i].dimms = 2;
626#endif
627
628 /* Devices 4-6 function 1 */
629 pci_read_config_dword(pvt->pci_ch[i][1],
630 MC_DOD_CH_DIMM0, &dimm_dod[0]);
631 pci_read_config_dword(pvt->pci_ch[i][1],
632 MC_DOD_CH_DIMM1, &dimm_dod[1]);
633 pci_read_config_dword(pvt->pci_ch[i][1],
634 MC_DOD_CH_DIMM2, &dimm_dod[2]);
635
636 debugf0("Ch%d phy rd%d, wr%d (0x%08x): "
637 "%d ranks, %cDIMMs\n",
638 i,
639 RDLCH(pvt->info.ch_map, i), WRLCH(pvt->info.ch_map, i),
640 data,
641 pvt->channel[i].ranks,
642 (data & REGISTERED_DIMM) ? 'R' : 'U');
643
644 for (j = 0; j < 3; j++) {
645 u32 banks, ranks, rows, cols;
646 u32 size, npages;
647
648 if (!DIMM_PRESENT(dimm_dod[j]))
649 continue;
650
651 banks = numbank(MC_DOD_NUMBANK(dimm_dod[j]));
652 ranks = numrank(MC_DOD_NUMRANK(dimm_dod[j]));
653 rows = numrow(MC_DOD_NUMROW(dimm_dod[j]));
654 cols = numcol(MC_DOD_NUMCOL(dimm_dod[j]));
655
656 /* DDR3 has 8 I/O banks */
657 size = (rows * cols * banks * ranks) >> (20 - 3);
658
659 pvt->channel[i].dimms++;
660
661 debugf0("\tdimm %d %d Mb offset: %x, "
662 "bank: %d, rank: %d, row: %#x, col: %#x\n",
663 j, size,
664 RANKOFFSET(dimm_dod[j]),
665 banks, ranks, rows, cols);
666
667#if PAGE_SHIFT > 20
668 npages = size >> (PAGE_SHIFT - 20);
669#else
670 npages = size << (20 - PAGE_SHIFT);
671#endif
672
673 csr = &mci->csrows[*csrow];
674 csr->first_page = last_page + 1;
675 last_page += npages;
676 csr->last_page = last_page;
677 csr->nr_pages = npages;
678
679 csr->page_mask = 0;
680 csr->grain = 8;
681 csr->csrow_idx = *csrow;
682 csr->nr_channels = 1;
683
684 csr->channels[0].chan_idx = i;
685 csr->channels[0].ce_count = 0;
686
687 pvt->csrow_map[i][j] = *csrow;
688
689 switch (banks) {
690 case 4:
691 csr->dtype = DEV_X4;
692 break;
693 case 8:
694 csr->dtype = DEV_X8;
695 break;
696 case 16:
697 csr->dtype = DEV_X16;
698 break;
699 default:
700 csr->dtype = DEV_UNKNOWN;
701 }
702
703 csr->edac_mode = mode;
704 csr->mtype = mtype;
705
706 (*csrow)++;
707 }
708
709 pci_read_config_dword(pdev, MC_SAG_CH_0, &value[0]);
710 pci_read_config_dword(pdev, MC_SAG_CH_1, &value[1]);
711 pci_read_config_dword(pdev, MC_SAG_CH_2, &value[2]);
712 pci_read_config_dword(pdev, MC_SAG_CH_3, &value[3]);
713 pci_read_config_dword(pdev, MC_SAG_CH_4, &value[4]);
714 pci_read_config_dword(pdev, MC_SAG_CH_5, &value[5]);
715 pci_read_config_dword(pdev, MC_SAG_CH_6, &value[6]);
716 pci_read_config_dword(pdev, MC_SAG_CH_7, &value[7]);
717 debugf1("\t[%i] DIVBY3\tREMOVED\tOFFSET\n", i);
718 for (j = 0; j < 8; j++)
719 debugf1("\t\t%#x\t%#x\t%#x\n",
720 (value[j] >> 27) & 0x1,
721 (value[j] >> 24) & 0x7,
722 (value[j] && ((1 << 24) - 1)));
723 }
724
725 return 0;
726}
727
728/****************************************************************************
729 Error insertion routines
730 ****************************************************************************/
731
732/* The i7core has independent error injection features per channel.
733 However, to have a simpler code, we don't allow enabling error injection
734 on more than one channel.
735 Also, since a change at an inject parameter will be applied only at enable,
736 we're disabling error injection on all write calls to the sysfs nodes that
737 controls the error code injection.
738 */
739static int disable_inject(struct mem_ctl_info *mci)
740{
741 struct i7core_pvt *pvt = mci->pvt_info;
742
743 pvt->inject.enable = 0;
744
745 if (!pvt->pci_ch[pvt->inject.channel][0])
746 return -ENODEV;
747
748 pci_write_config_dword(pvt->pci_ch[pvt->inject.channel][0],
749 MC_CHANNEL_ERROR_INJECT, 0);
750
751 return 0;
752}
753
754/*
755 * i7core inject inject.section
756 *
757 * accept and store error injection inject.section value
758 * bit 0 - refers to the lower 32-byte half cacheline
759 * bit 1 - refers to the upper 32-byte half cacheline
760 */
761static ssize_t i7core_inject_section_store(struct mem_ctl_info *mci,
762 const char *data, size_t count)
763{
764 struct i7core_pvt *pvt = mci->pvt_info;
765 unsigned long value;
766 int rc;
767
768 if (pvt->inject.enable)
769 disable_inject(mci);
770
771 rc = strict_strtoul(data, 10, &value);
772 if ((rc < 0) || (value > 3))
773 return -EIO;
774
775 pvt->inject.section = (u32) value;
776 return count;
777}
778
779static ssize_t i7core_inject_section_show(struct mem_ctl_info *mci,
780 char *data)
781{
782 struct i7core_pvt *pvt = mci->pvt_info;
783 return sprintf(data, "0x%08x\n", pvt->inject.section);
784}
785
786/*
787 * i7core inject.type
788 *
789 * accept and store error injection inject.section value
790 * bit 0 - repeat enable - Enable error repetition
791 * bit 1 - inject ECC error
792 * bit 2 - inject parity error
793 */
794static ssize_t i7core_inject_type_store(struct mem_ctl_info *mci,
795 const char *data, size_t count)
796{
797 struct i7core_pvt *pvt = mci->pvt_info;
798 unsigned long value;
799 int rc;
800
801 if (pvt->inject.enable)
802 disable_inject(mci);
803
804 rc = strict_strtoul(data, 10, &value);
805 if ((rc < 0) || (value > 7))
806 return -EIO;
807
808 pvt->inject.type = (u32) value;
809 return count;
810}
811
812static ssize_t i7core_inject_type_show(struct mem_ctl_info *mci,
813 char *data)
814{
815 struct i7core_pvt *pvt = mci->pvt_info;
816 return sprintf(data, "0x%08x\n", pvt->inject.type);
817}
818
819/*
820 * i7core_inject_inject.eccmask_store
821 *
822 * The type of error (UE/CE) will depend on the inject.eccmask value:
823 * Any bits set to a 1 will flip the corresponding ECC bit
824 * Correctable errors can be injected by flipping 1 bit or the bits within
825 * a symbol pair (2 consecutive aligned 8-bit pairs - i.e. 7:0 and 15:8 or
826 * 23:16 and 31:24). Flipping bits in two symbol pairs will cause an
827 * uncorrectable error to be injected.
828 */
829static ssize_t i7core_inject_eccmask_store(struct mem_ctl_info *mci,
830 const char *data, size_t count)
831{
832 struct i7core_pvt *pvt = mci->pvt_info;
833 unsigned long value;
834 int rc;
835
836 if (pvt->inject.enable)
837 disable_inject(mci);
838
839 rc = strict_strtoul(data, 10, &value);
840 if (rc < 0)
841 return -EIO;
842
843 pvt->inject.eccmask = (u32) value;
844 return count;
845}
846
847static ssize_t i7core_inject_eccmask_show(struct mem_ctl_info *mci,
848 char *data)
849{
850 struct i7core_pvt *pvt = mci->pvt_info;
851 return sprintf(data, "0x%08x\n", pvt->inject.eccmask);
852}
853
854/*
855 * i7core_addrmatch
856 *
857 * The type of error (UE/CE) will depend on the inject.eccmask value:
858 * Any bits set to a 1 will flip the corresponding ECC bit
859 * Correctable errors can be injected by flipping 1 bit or the bits within
860 * a symbol pair (2 consecutive aligned 8-bit pairs - i.e. 7:0 and 15:8 or
861 * 23:16 and 31:24). Flipping bits in two symbol pairs will cause an
862 * uncorrectable error to be injected.
863 */
864
865#define DECLARE_ADDR_MATCH(param, limit) \
866static ssize_t i7core_inject_store_##param( \
867 struct mem_ctl_info *mci, \
868 const char *data, size_t count) \
869{ \
870 struct i7core_pvt *pvt; \
871 long value; \
872 int rc; \
873 \
874 debugf1("%s()\n", __func__); \
875 pvt = mci->pvt_info; \
876 \
877 if (pvt->inject.enable) \
878 disable_inject(mci); \
879 \
880 if (!strcasecmp(data, "any") || !strcasecmp(data, "any\n"))\
881 value = -1; \
882 else { \
883 rc = strict_strtoul(data, 10, &value); \
884 if ((rc < 0) || (value >= limit)) \
885 return -EIO; \
886 } \
887 \
888 pvt->inject.param = value; \
889 \
890 return count; \
891} \
892 \
893static ssize_t i7core_inject_show_##param( \
894 struct mem_ctl_info *mci, \
895 char *data) \
896{ \
897 struct i7core_pvt *pvt; \
898 \
899 pvt = mci->pvt_info; \
900 debugf1("%s() pvt=%p\n", __func__, pvt); \
901 if (pvt->inject.param < 0) \
902 return sprintf(data, "any\n"); \
903 else \
904 return sprintf(data, "%d\n", pvt->inject.param);\
905}
906
907#define ATTR_ADDR_MATCH(param) \
908 { \
909 .attr = { \
910 .name = #param, \
911 .mode = (S_IRUGO | S_IWUSR) \
912 }, \
913 .show = i7core_inject_show_##param, \
914 .store = i7core_inject_store_##param, \
915 }
916
917DECLARE_ADDR_MATCH(channel, 3);
918DECLARE_ADDR_MATCH(dimm, 3);
919DECLARE_ADDR_MATCH(rank, 4);
920DECLARE_ADDR_MATCH(bank, 32);
921DECLARE_ADDR_MATCH(page, 0x10000);
922DECLARE_ADDR_MATCH(col, 0x4000);
923
924static int write_and_test(struct pci_dev *dev, int where, u32 val)
925{
926 u32 read;
927 int count;
928
929 debugf0("setting pci %02x:%02x.%x reg=%02x value=%08x\n",
930 dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn),
931 where, val);
932
933 for (count = 0; count < 10; count++) {
934 if (count)
935 msleep(100);
936 pci_write_config_dword(dev, where, val);
937 pci_read_config_dword(dev, where, &read);
938
939 if (read == val)
940 return 0;
941 }
942
943 i7core_printk(KERN_ERR, "Error during set pci %02x:%02x.%x reg=%02x "
944 "write=%08x. Read=%08x\n",
945 dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn),
946 where, val, read);
947
948 return -EINVAL;
949}
950
951/*
952 * This routine prepares the Memory Controller for error injection.
953 * The error will be injected when some process tries to write to the
954 * memory that matches the given criteria.
955 * The criteria can be set in terms of a mask where dimm, rank, bank, page
956 * and col can be specified.
957 * A -1 value for any of the mask items will make the MCU to ignore
958 * that matching criteria for error injection.
959 *
960 * It should be noticed that the error will only happen after a write operation
961 * on a memory that matches the condition. if REPEAT_EN is not enabled at
962 * inject mask, then it will produce just one error. Otherwise, it will repeat
963 * until the injectmask would be cleaned.
964 *
965 * FIXME: This routine assumes that MAXNUMDIMMS value of MC_MAX_DOD
966 * is reliable enough to check if the MC is using the
967 * three channels. However, this is not clear at the datasheet.
968 */
969static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci,
970 const char *data, size_t count)
971{
972 struct i7core_pvt *pvt = mci->pvt_info;
973 u32 injectmask;
974 u64 mask = 0;
975 int rc;
976 long enable;
977
978 if (!pvt->pci_ch[pvt->inject.channel][0])
979 return 0;
980
981 rc = strict_strtoul(data, 10, &enable);
982 if ((rc < 0))
983 return 0;
984
985 if (enable) {
986 pvt->inject.enable = 1;
987 } else {
988 disable_inject(mci);
989 return count;
990 }
991
992 /* Sets pvt->inject.dimm mask */
993 if (pvt->inject.dimm < 0)
994 mask |= 1LL << 41;
995 else {
996 if (pvt->channel[pvt->inject.channel].dimms > 2)
997 mask |= (pvt->inject.dimm & 0x3LL) << 35;
998 else
999 mask |= (pvt->inject.dimm & 0x1LL) << 36;
1000 }
1001
1002 /* Sets pvt->inject.rank mask */
1003 if (pvt->inject.rank < 0)
1004 mask |= 1LL << 40;
1005 else {
1006 if (pvt->channel[pvt->inject.channel].dimms > 2)
1007 mask |= (pvt->inject.rank & 0x1LL) << 34;
1008 else
1009 mask |= (pvt->inject.rank & 0x3LL) << 34;
1010 }
1011
1012 /* Sets pvt->inject.bank mask */
1013 if (pvt->inject.bank < 0)
1014 mask |= 1LL << 39;
1015 else
1016 mask |= (pvt->inject.bank & 0x15LL) << 30;
1017
1018 /* Sets pvt->inject.page mask */
1019 if (pvt->inject.page < 0)
1020 mask |= 1LL << 38;
1021 else
1022 mask |= (pvt->inject.page & 0xffff) << 14;
1023
1024 /* Sets pvt->inject.column mask */
1025 if (pvt->inject.col < 0)
1026 mask |= 1LL << 37;
1027 else
1028 mask |= (pvt->inject.col & 0x3fff);
1029
1030 /*
1031 * bit 0: REPEAT_EN
1032 * bits 1-2: MASK_HALF_CACHELINE
1033 * bit 3: INJECT_ECC
1034 * bit 4: INJECT_ADDR_PARITY
1035 */
1036
1037 injectmask = (pvt->inject.type & 1) |
1038 (pvt->inject.section & 0x3) << 1 |
1039 (pvt->inject.type & 0x6) << (3 - 1);
1040
1041 /* Unlock writes to registers - this register is write only */
1042 pci_write_config_dword(pvt->pci_noncore,
1043 MC_CFG_CONTROL, 0x2);
1044
1045 write_and_test(pvt->pci_ch[pvt->inject.channel][0],
1046 MC_CHANNEL_ADDR_MATCH, mask);
1047 write_and_test(pvt->pci_ch[pvt->inject.channel][0],
1048 MC_CHANNEL_ADDR_MATCH + 4, mask >> 32L);
1049
1050 write_and_test(pvt->pci_ch[pvt->inject.channel][0],
1051 MC_CHANNEL_ERROR_MASK, pvt->inject.eccmask);
1052
1053 write_and_test(pvt->pci_ch[pvt->inject.channel][0],
1054 MC_CHANNEL_ERROR_INJECT, injectmask);
1055
1056 /*
1057 * This is something undocumented, based on my tests
1058 * Without writing 8 to this register, errors aren't injected. Not sure
1059 * why.
1060 */
1061 pci_write_config_dword(pvt->pci_noncore,
1062 MC_CFG_CONTROL, 8);
1063
1064 debugf0("Error inject addr match 0x%016llx, ecc 0x%08x,"
1065 " inject 0x%08x\n",
1066 mask, pvt->inject.eccmask, injectmask);
1067
1068
1069 return count;
1070}
1071
1072static ssize_t i7core_inject_enable_show(struct mem_ctl_info *mci,
1073 char *data)
1074{
1075 struct i7core_pvt *pvt = mci->pvt_info;
1076 u32 injectmask;
1077
1078 if (!pvt->pci_ch[pvt->inject.channel][0])
1079 return 0;
1080
1081 pci_read_config_dword(pvt->pci_ch[pvt->inject.channel][0],
1082 MC_CHANNEL_ERROR_INJECT, &injectmask);
1083
1084 debugf0("Inject error read: 0x%018x\n", injectmask);
1085
1086 if (injectmask & 0x0c)
1087 pvt->inject.enable = 1;
1088
1089 return sprintf(data, "%d\n", pvt->inject.enable);
1090}
1091
1092#define DECLARE_COUNTER(param) \
1093static ssize_t i7core_show_counter_##param( \
1094 struct mem_ctl_info *mci, \
1095 char *data) \
1096{ \
1097 struct i7core_pvt *pvt = mci->pvt_info; \
1098 \
1099 debugf1("%s() \n", __func__); \
1100 if (!pvt->ce_count_available || (pvt->is_registered)) \
1101 return sprintf(data, "data unavailable\n"); \
1102 return sprintf(data, "%lu\n", \
1103 pvt->udimm_ce_count[param]); \
1104}
1105
1106#define ATTR_COUNTER(param) \
1107 { \
1108 .attr = { \
1109 .name = __stringify(udimm##param), \
1110 .mode = (S_IRUGO | S_IWUSR) \
1111 }, \
1112 .show = i7core_show_counter_##param \
1113 }
1114
1115DECLARE_COUNTER(0);
1116DECLARE_COUNTER(1);
1117DECLARE_COUNTER(2);
1118
1119/*
1120 * Sysfs struct
1121 */
1122
1123
1124static struct mcidev_sysfs_attribute i7core_addrmatch_attrs[] = {
1125 ATTR_ADDR_MATCH(channel),
1126 ATTR_ADDR_MATCH(dimm),
1127 ATTR_ADDR_MATCH(rank),
1128 ATTR_ADDR_MATCH(bank),
1129 ATTR_ADDR_MATCH(page),
1130 ATTR_ADDR_MATCH(col),
1131 { .attr = { .name = NULL } }
1132};
1133
1134static struct mcidev_sysfs_group i7core_inject_addrmatch = {
1135 .name = "inject_addrmatch",
1136 .mcidev_attr = i7core_addrmatch_attrs,
1137};
1138
1139static struct mcidev_sysfs_attribute i7core_udimm_counters_attrs[] = {
1140 ATTR_COUNTER(0),
1141 ATTR_COUNTER(1),
1142 ATTR_COUNTER(2),
1143};
1144
1145static struct mcidev_sysfs_group i7core_udimm_counters = {
1146 .name = "all_channel_counts",
1147 .mcidev_attr = i7core_udimm_counters_attrs,
1148};
1149
1150static struct mcidev_sysfs_attribute i7core_sysfs_attrs[] = {
1151 {
1152 .attr = {
1153 .name = "inject_section",
1154 .mode = (S_IRUGO | S_IWUSR)
1155 },
1156 .show = i7core_inject_section_show,
1157 .store = i7core_inject_section_store,
1158 }, {
1159 .attr = {
1160 .name = "inject_type",
1161 .mode = (S_IRUGO | S_IWUSR)
1162 },
1163 .show = i7core_inject_type_show,
1164 .store = i7core_inject_type_store,
1165 }, {
1166 .attr = {
1167 .name = "inject_eccmask",
1168 .mode = (S_IRUGO | S_IWUSR)
1169 },
1170 .show = i7core_inject_eccmask_show,
1171 .store = i7core_inject_eccmask_store,
1172 }, {
1173 .grp = &i7core_inject_addrmatch,
1174 }, {
1175 .attr = {
1176 .name = "inject_enable",
1177 .mode = (S_IRUGO | S_IWUSR)
1178 },
1179 .show = i7core_inject_enable_show,
1180 .store = i7core_inject_enable_store,
1181 },
1182 { .attr = { .name = NULL } }, /* Reserved for udimm counters */
1183 { .attr = { .name = NULL } }
1184};
1185
1186/****************************************************************************
1187 Device initialization routines: put/get, init/exit
1188 ****************************************************************************/
1189
1190/*
1191 * i7core_put_devices 'put' all the devices that we have
1192 * reserved via 'get'
1193 */
1194static void i7core_put_devices(struct i7core_dev *i7core_dev)
1195{
1196 int i;
1197
1198 debugf0(__FILE__ ": %s()\n", __func__);
1199 for (i = 0; i < i7core_dev->n_devs; i++) {
1200 struct pci_dev *pdev = i7core_dev->pdev[i];
1201 if (!pdev)
1202 continue;
1203 debugf0("Removing dev %02x:%02x.%d\n",
1204 pdev->bus->number,
1205 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
1206 pci_dev_put(pdev);
1207 }
1208 kfree(i7core_dev->pdev);
1209 list_del(&i7core_dev->list);
1210 kfree(i7core_dev);
1211}
1212
1213static void i7core_put_all_devices(void)
1214{
1215 struct i7core_dev *i7core_dev, *tmp;
1216
1217 list_for_each_entry_safe(i7core_dev, tmp, &i7core_edac_list, list)
1218 i7core_put_devices(i7core_dev);
1219}
1220
1221static void __init i7core_xeon_pci_fixup(struct pci_id_table *table)
1222{
1223 struct pci_dev *pdev = NULL;
1224 int i;
1225 /*
1226 * On Xeon 55xx, the Intel Quckpath Arch Generic Non-core pci buses
1227 * aren't announced by acpi. So, we need to use a legacy scan probing
1228 * to detect them
1229 */
1230 while (table && table->descr) {
1231 pdev = pci_get_device(PCI_VENDOR_ID_INTEL, table->descr[0].dev_id, NULL);
1232 if (unlikely(!pdev)) {
1233 for (i = 0; i < MAX_SOCKET_BUSES; i++)
1234 pcibios_scan_specific_bus(255-i);
1235 }
1236 table++;
1237 }
1238}
1239
1240/*
1241 * i7core_get_devices Find and perform 'get' operation on the MCH's
1242 * device/functions we want to reference for this driver
1243 *
1244 * Need to 'get' device 16 func 1 and func 2
1245 */
1246int i7core_get_onedevice(struct pci_dev **prev, int devno,
1247 struct pci_id_descr *dev_descr, unsigned n_devs)
1248{
1249 struct i7core_dev *i7core_dev;
1250
1251 struct pci_dev *pdev = NULL;
1252 u8 bus = 0;
1253 u8 socket = 0;
1254
1255 pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
1256 dev_descr->dev_id, *prev);
1257
1258 /*
1259 * On Xeon 55xx, the Intel Quckpath Arch Generic Non-core regs
1260 * is at addr 8086:2c40, instead of 8086:2c41. So, we need
1261 * to probe for the alternate address in case of failure
1262 */
1263 if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_I7_NONCORE && !pdev)
1264 pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
1265 PCI_DEVICE_ID_INTEL_I7_NONCORE_ALT, *prev);
1266
1267 if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE && !pdev)
1268 pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
1269 PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_ALT,
1270 *prev);
1271
1272 if (!pdev) {
1273 if (*prev) {
1274 *prev = pdev;
1275 return 0;
1276 }
1277
1278 if (dev_descr->optional)
1279 return 0;
1280
1281 if (devno == 0)
1282 return -ENODEV;
1283
1284 i7core_printk(KERN_ERR,
1285 "Device not found: dev %02x.%d PCI ID %04x:%04x\n",
1286 dev_descr->dev, dev_descr->func,
1287 PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
1288
1289 /* End of list, leave */
1290 return -ENODEV;
1291 }
1292 bus = pdev->bus->number;
1293
1294 if (bus == 0x3f)
1295 socket = 0;
1296 else
1297 socket = 255 - bus;
1298
1299 i7core_dev = get_i7core_dev(socket);
1300 if (!i7core_dev) {
1301 i7core_dev = kzalloc(sizeof(*i7core_dev), GFP_KERNEL);
1302 if (!i7core_dev)
1303 return -ENOMEM;
1304 i7core_dev->pdev = kzalloc(sizeof(*i7core_dev->pdev) * n_devs,
1305 GFP_KERNEL);
1306 if (!i7core_dev->pdev) {
1307 kfree(i7core_dev);
1308 return -ENOMEM;
1309 }
1310 i7core_dev->socket = socket;
1311 i7core_dev->n_devs = n_devs;
1312 list_add_tail(&i7core_dev->list, &i7core_edac_list);
1313 }
1314
1315 if (i7core_dev->pdev[devno]) {
1316 i7core_printk(KERN_ERR,
1317 "Duplicated device for "
1318 "dev %02x:%02x.%d PCI ID %04x:%04x\n",
1319 bus, dev_descr->dev, dev_descr->func,
1320 PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
1321 pci_dev_put(pdev);
1322 return -ENODEV;
1323 }
1324
1325 i7core_dev->pdev[devno] = pdev;
1326
1327 /* Sanity check */
1328 if (unlikely(PCI_SLOT(pdev->devfn) != dev_descr->dev ||
1329 PCI_FUNC(pdev->devfn) != dev_descr->func)) {
1330 i7core_printk(KERN_ERR,
1331 "Device PCI ID %04x:%04x "
1332 "has dev %02x:%02x.%d instead of dev %02x:%02x.%d\n",
1333 PCI_VENDOR_ID_INTEL, dev_descr->dev_id,
1334 bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
1335 bus, dev_descr->dev, dev_descr->func);
1336 return -ENODEV;
1337 }
1338
1339 /* Be sure that the device is enabled */
1340 if (unlikely(pci_enable_device(pdev) < 0)) {
1341 i7core_printk(KERN_ERR,
1342 "Couldn't enable "
1343 "dev %02x:%02x.%d PCI ID %04x:%04x\n",
1344 bus, dev_descr->dev, dev_descr->func,
1345 PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
1346 return -ENODEV;
1347 }
1348
1349 debugf0("Detected socket %d dev %02x:%02x.%d PCI ID %04x:%04x\n",
1350 socket, bus, dev_descr->dev,
1351 dev_descr->func,
1352 PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
1353
1354 *prev = pdev;
1355
1356 return 0;
1357}
1358
1359static int i7core_get_devices(struct pci_id_table *table)
1360{
1361 int i, rc;
1362 struct pci_dev *pdev = NULL;
1363 struct pci_id_descr *dev_descr;
1364
1365 while (table && table->descr) {
1366 dev_descr = table->descr;
1367 for (i = 0; i < table->n_devs; i++) {
1368 pdev = NULL;
1369 do {
1370 rc = i7core_get_onedevice(&pdev, i, &dev_descr[i],
1371 table->n_devs);
1372 if (rc < 0) {
1373 if (i == 0) {
1374 i = table->n_devs;
1375 break;
1376 }
1377 i7core_put_all_devices();
1378 return -ENODEV;
1379 }
1380 } while (pdev);
1381 }
1382 table++;
1383 }
1384
1385 return 0;
1386 return 0;
1387}
1388
1389static int mci_bind_devs(struct mem_ctl_info *mci,
1390 struct i7core_dev *i7core_dev)
1391{
1392 struct i7core_pvt *pvt = mci->pvt_info;
1393 struct pci_dev *pdev;
1394 int i, func, slot;
1395
1396 /* Associates i7core_dev and mci for future usage */
1397 pvt->i7core_dev = i7core_dev;
1398 i7core_dev->mci = mci;
1399
1400 pvt->is_registered = 0;
1401 for (i = 0; i < i7core_dev->n_devs; i++) {
1402 pdev = i7core_dev->pdev[i];
1403 if (!pdev)
1404 continue;
1405
1406 func = PCI_FUNC(pdev->devfn);
1407 slot = PCI_SLOT(pdev->devfn);
1408 if (slot == 3) {
1409 if (unlikely(func > MAX_MCR_FUNC))
1410 goto error;
1411 pvt->pci_mcr[func] = pdev;
1412 } else if (likely(slot >= 4 && slot < 4 + NUM_CHANS)) {
1413 if (unlikely(func > MAX_CHAN_FUNC))
1414 goto error;
1415 pvt->pci_ch[slot - 4][func] = pdev;
1416 } else if (!slot && !func)
1417 pvt->pci_noncore = pdev;
1418 else
1419 goto error;
1420
1421 debugf0("Associated fn %d.%d, dev = %p, socket %d\n",
1422 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
1423 pdev, i7core_dev->socket);
1424
1425 if (PCI_SLOT(pdev->devfn) == 3 &&
1426 PCI_FUNC(pdev->devfn) == 2)
1427 pvt->is_registered = 1;
1428 }
1429
1430 /*
1431 * Add extra nodes to count errors on udimm
1432 * For registered memory, this is not needed, since the counters
1433 * are already displayed at the standard locations
1434 */
1435 if (!pvt->is_registered)
1436 i7core_sysfs_attrs[ARRAY_SIZE(i7core_sysfs_attrs)-2].grp =
1437 &i7core_udimm_counters;
1438
1439 return 0;
1440
1441error:
1442 i7core_printk(KERN_ERR, "Device %d, function %d "
1443 "is out of the expected range\n",
1444 slot, func);
1445 return -EINVAL;
1446}
1447
1448/****************************************************************************
1449 Error check routines
1450 ****************************************************************************/
1451static void i7core_rdimm_update_csrow(struct mem_ctl_info *mci,
1452 int chan, int dimm, int add)
1453{
1454 char *msg;
1455 struct i7core_pvt *pvt = mci->pvt_info;
1456 int row = pvt->csrow_map[chan][dimm], i;
1457
1458 for (i = 0; i < add; i++) {
1459 msg = kasprintf(GFP_KERNEL, "Corrected error "
1460 "(Socket=%d channel=%d dimm=%d)",
1461 pvt->i7core_dev->socket, chan, dimm);
1462
1463 edac_mc_handle_fbd_ce(mci, row, 0, msg);
1464 kfree (msg);
1465 }
1466}
1467
1468static void i7core_rdimm_update_ce_count(struct mem_ctl_info *mci,
1469 int chan, int new0, int new1, int new2)
1470{
1471 struct i7core_pvt *pvt = mci->pvt_info;
1472 int add0 = 0, add1 = 0, add2 = 0;
1473 /* Updates CE counters if it is not the first time here */
1474 if (pvt->ce_count_available) {
1475 /* Updates CE counters */
1476
1477 add2 = new2 - pvt->rdimm_last_ce_count[chan][2];
1478 add1 = new1 - pvt->rdimm_last_ce_count[chan][1];
1479 add0 = new0 - pvt->rdimm_last_ce_count[chan][0];
1480
1481 if (add2 < 0)
1482 add2 += 0x7fff;
1483 pvt->rdimm_ce_count[chan][2] += add2;
1484
1485 if (add1 < 0)
1486 add1 += 0x7fff;
1487 pvt->rdimm_ce_count[chan][1] += add1;
1488
1489 if (add0 < 0)
1490 add0 += 0x7fff;
1491 pvt->rdimm_ce_count[chan][0] += add0;
1492 } else
1493 pvt->ce_count_available = 1;
1494
1495 /* Store the new values */
1496 pvt->rdimm_last_ce_count[chan][2] = new2;
1497 pvt->rdimm_last_ce_count[chan][1] = new1;
1498 pvt->rdimm_last_ce_count[chan][0] = new0;
1499
1500 /*updated the edac core */
1501 if (add0 != 0)
1502 i7core_rdimm_update_csrow(mci, chan, 0, add0);
1503 if (add1 != 0)
1504 i7core_rdimm_update_csrow(mci, chan, 1, add1);
1505 if (add2 != 0)
1506 i7core_rdimm_update_csrow(mci, chan, 2, add2);
1507
1508}
1509
1510static void i7core_rdimm_check_mc_ecc_err(struct mem_ctl_info *mci)
1511{
1512 struct i7core_pvt *pvt = mci->pvt_info;
1513 u32 rcv[3][2];
1514 int i, new0, new1, new2;
1515
1516 /*Read DEV 3: FUN 2: MC_COR_ECC_CNT regs directly*/
1517 pci_read_config_dword(pvt->pci_mcr[2], MC_COR_ECC_CNT_0,
1518 &rcv[0][0]);
1519 pci_read_config_dword(pvt->pci_mcr[2], MC_COR_ECC_CNT_1,
1520 &rcv[0][1]);
1521 pci_read_config_dword(pvt->pci_mcr[2], MC_COR_ECC_CNT_2,
1522 &rcv[1][0]);
1523 pci_read_config_dword(pvt->pci_mcr[2], MC_COR_ECC_CNT_3,
1524 &rcv[1][1]);
1525 pci_read_config_dword(pvt->pci_mcr[2], MC_COR_ECC_CNT_4,
1526 &rcv[2][0]);
1527 pci_read_config_dword(pvt->pci_mcr[2], MC_COR_ECC_CNT_5,
1528 &rcv[2][1]);
1529 for (i = 0 ; i < 3; i++) {
1530 debugf3("MC_COR_ECC_CNT%d = 0x%x; MC_COR_ECC_CNT%d = 0x%x\n",
1531 (i * 2), rcv[i][0], (i * 2) + 1, rcv[i][1]);
1532 /*if the channel has 3 dimms*/
1533 if (pvt->channel[i].dimms > 2) {
1534 new0 = DIMM_BOT_COR_ERR(rcv[i][0]);
1535 new1 = DIMM_TOP_COR_ERR(rcv[i][0]);
1536 new2 = DIMM_BOT_COR_ERR(rcv[i][1]);
1537 } else {
1538 new0 = DIMM_TOP_COR_ERR(rcv[i][0]) +
1539 DIMM_BOT_COR_ERR(rcv[i][0]);
1540 new1 = DIMM_TOP_COR_ERR(rcv[i][1]) +
1541 DIMM_BOT_COR_ERR(rcv[i][1]);
1542 new2 = 0;
1543 }
1544
1545 i7core_rdimm_update_ce_count(mci, i, new0, new1, new2);
1546 }
1547}
1548
1549/* This function is based on the device 3 function 4 registers as described on:
1550 * Intel Xeon Processor 5500 Series Datasheet Volume 2
1551 * http://www.intel.com/Assets/PDF/datasheet/321322.pdf
1552 * also available at:
1553 * http://www.arrownac.com/manufacturers/intel/s/nehalem/5500-datasheet-v2.pdf
1554 */
1555static void i7core_udimm_check_mc_ecc_err(struct mem_ctl_info *mci)
1556{
1557 struct i7core_pvt *pvt = mci->pvt_info;
1558 u32 rcv1, rcv0;
1559 int new0, new1, new2;
1560
1561 if (!pvt->pci_mcr[4]) {
1562 debugf0("%s MCR registers not found\n", __func__);
1563 return;
1564 }
1565
1566 /* Corrected test errors */
1567 pci_read_config_dword(pvt->pci_mcr[4], MC_TEST_ERR_RCV1, &rcv1);
1568 pci_read_config_dword(pvt->pci_mcr[4], MC_TEST_ERR_RCV0, &rcv0);
1569
1570 /* Store the new values */
1571 new2 = DIMM2_COR_ERR(rcv1);
1572 new1 = DIMM1_COR_ERR(rcv0);
1573 new0 = DIMM0_COR_ERR(rcv0);
1574
1575 /* Updates CE counters if it is not the first time here */
1576 if (pvt->ce_count_available) {
1577 /* Updates CE counters */
1578 int add0, add1, add2;
1579
1580 add2 = new2 - pvt->udimm_last_ce_count[2];
1581 add1 = new1 - pvt->udimm_last_ce_count[1];
1582 add0 = new0 - pvt->udimm_last_ce_count[0];
1583
1584 if (add2 < 0)
1585 add2 += 0x7fff;
1586 pvt->udimm_ce_count[2] += add2;
1587
1588 if (add1 < 0)
1589 add1 += 0x7fff;
1590 pvt->udimm_ce_count[1] += add1;
1591
1592 if (add0 < 0)
1593 add0 += 0x7fff;
1594 pvt->udimm_ce_count[0] += add0;
1595
1596 if (add0 | add1 | add2)
1597 i7core_printk(KERN_ERR, "New Corrected error(s): "
1598 "dimm0: +%d, dimm1: +%d, dimm2 +%d\n",
1599 add0, add1, add2);
1600 } else
1601 pvt->ce_count_available = 1;
1602
1603 /* Store the new values */
1604 pvt->udimm_last_ce_count[2] = new2;
1605 pvt->udimm_last_ce_count[1] = new1;
1606 pvt->udimm_last_ce_count[0] = new0;
1607}
1608
1609/*
1610 * According with tables E-11 and E-12 of chapter E.3.3 of Intel 64 and IA-32
1611 * Architectures Software Developer’s Manual Volume 3B.
1612 * Nehalem are defined as family 0x06, model 0x1a
1613 *
1614 * The MCA registers used here are the following ones:
1615 * struct mce field MCA Register
1616 * m->status MSR_IA32_MC8_STATUS
1617 * m->addr MSR_IA32_MC8_ADDR
1618 * m->misc MSR_IA32_MC8_MISC
1619 * In the case of Nehalem, the error information is masked at .status and .misc
1620 * fields
1621 */
1622static void i7core_mce_output_error(struct mem_ctl_info *mci,
1623 struct mce *m)
1624{
1625 struct i7core_pvt *pvt = mci->pvt_info;
1626 char *type, *optype, *err, *msg;
1627 unsigned long error = m->status & 0x1ff0000l;
1628 u32 optypenum = (m->status >> 4) & 0x07;
1629 u32 core_err_cnt = (m->status >> 38) && 0x7fff;
1630 u32 dimm = (m->misc >> 16) & 0x3;
1631 u32 channel = (m->misc >> 18) & 0x3;
1632 u32 syndrome = m->misc >> 32;
1633 u32 errnum = find_first_bit(&error, 32);
1634 int csrow;
1635
1636 if (m->mcgstatus & 1)
1637 type = "FATAL";
1638 else
1639 type = "NON_FATAL";
1640
1641 switch (optypenum) {
1642 case 0:
1643 optype = "generic undef request";
1644 break;
1645 case 1:
1646 optype = "read error";
1647 break;
1648 case 2:
1649 optype = "write error";
1650 break;
1651 case 3:
1652 optype = "addr/cmd error";
1653 break;
1654 case 4:
1655 optype = "scrubbing error";
1656 break;
1657 default:
1658 optype = "reserved";
1659 break;
1660 }
1661
1662 switch (errnum) {
1663 case 16:
1664 err = "read ECC error";
1665 break;
1666 case 17:
1667 err = "RAS ECC error";
1668 break;
1669 case 18:
1670 err = "write parity error";
1671 break;
1672 case 19:
1673 err = "redundacy loss";
1674 break;
1675 case 20:
1676 err = "reserved";
1677 break;
1678 case 21:
1679 err = "memory range error";
1680 break;
1681 case 22:
1682 err = "RTID out of range";
1683 break;
1684 case 23:
1685 err = "address parity error";
1686 break;
1687 case 24:
1688 err = "byte enable parity error";
1689 break;
1690 default:
1691 err = "unknown";
1692 }
1693
1694 /* FIXME: should convert addr into bank and rank information */
1695 msg = kasprintf(GFP_ATOMIC,
1696 "%s (addr = 0x%08llx, cpu=%d, Dimm=%d, Channel=%d, "
1697 "syndrome=0x%08x, count=%d, Err=%08llx:%08llx (%s: %s))\n",
1698 type, (long long) m->addr, m->cpu, dimm, channel,
1699 syndrome, core_err_cnt, (long long)m->status,
1700 (long long)m->misc, optype, err);
1701
1702 debugf0("%s", msg);
1703
1704 csrow = pvt->csrow_map[channel][dimm];
1705
1706 /* Call the helper to output message */
1707 if (m->mcgstatus & 1)
1708 edac_mc_handle_fbd_ue(mci, csrow, 0,
1709 0 /* FIXME: should be channel here */, msg);
1710 else if (!pvt->is_registered)
1711 edac_mc_handle_fbd_ce(mci, csrow,
1712 0 /* FIXME: should be channel here */, msg);
1713
1714 kfree(msg);
1715}
1716
1717/*
1718 * i7core_check_error Retrieve and process errors reported by the
1719 * hardware. Called by the Core module.
1720 */
1721static void i7core_check_error(struct mem_ctl_info *mci)
1722{
1723 struct i7core_pvt *pvt = mci->pvt_info;
1724 int i;
1725 unsigned count = 0;
1726 struct mce *m;
1727
1728 /*
1729 * MCE first step: Copy all mce errors into a temporary buffer
1730 * We use a double buffering here, to reduce the risk of
1731 * loosing an error.
1732 */
1733 smp_rmb();
1734 count = (pvt->mce_out + MCE_LOG_LEN - pvt->mce_in)
1735 % MCE_LOG_LEN;
1736 if (!count)
1737 goto check_ce_error;
1738
1739 m = pvt->mce_outentry;
1740 if (pvt->mce_in + count > MCE_LOG_LEN) {
1741 unsigned l = MCE_LOG_LEN - pvt->mce_in;
1742
1743 memcpy(m, &pvt->mce_entry[pvt->mce_in], sizeof(*m) * l);
1744 smp_wmb();
1745 pvt->mce_in = 0;
1746 count -= l;
1747 m += l;
1748 }
1749 memcpy(m, &pvt->mce_entry[pvt->mce_in], sizeof(*m) * count);
1750 smp_wmb();
1751 pvt->mce_in += count;
1752
1753 smp_rmb();
1754 if (pvt->mce_overrun) {
1755 i7core_printk(KERN_ERR, "Lost %d memory errors\n",
1756 pvt->mce_overrun);
1757 smp_wmb();
1758 pvt->mce_overrun = 0;
1759 }
1760
1761 /*
1762 * MCE second step: parse errors and display
1763 */
1764 for (i = 0; i < count; i++)
1765 i7core_mce_output_error(mci, &pvt->mce_outentry[i]);
1766
1767 /*
1768 * Now, let's increment CE error counts
1769 */
1770check_ce_error:
1771 if (!pvt->is_registered)
1772 i7core_udimm_check_mc_ecc_err(mci);
1773 else
1774 i7core_rdimm_check_mc_ecc_err(mci);
1775}
1776
1777/*
1778 * i7core_mce_check_error Replicates mcelog routine to get errors
1779 * This routine simply queues mcelog errors, and
1780 * return. The error itself should be handled later
1781 * by i7core_check_error.
1782 * WARNING: As this routine should be called at NMI time, extra care should
1783 * be taken to avoid deadlocks, and to be as fast as possible.
1784 */
1785static int i7core_mce_check_error(void *priv, struct mce *mce)
1786{
1787 struct mem_ctl_info *mci = priv;
1788 struct i7core_pvt *pvt = mci->pvt_info;
1789
1790 /*
1791 * Just let mcelog handle it if the error is
1792 * outside the memory controller
1793 */
1794 if (((mce->status & 0xffff) >> 7) != 1)
1795 return 0;
1796
1797 /* Bank 8 registers are the only ones that we know how to handle */
1798 if (mce->bank != 8)
1799 return 0;
1800
1801#ifdef CONFIG_SMP
1802 /* Only handle if it is the right mc controller */
1803 if (cpu_data(mce->cpu).phys_proc_id != pvt->i7core_dev->socket)
1804 return 0;
1805#endif
1806
1807 smp_rmb();
1808 if ((pvt->mce_out + 1) % MCE_LOG_LEN == pvt->mce_in) {
1809 smp_wmb();
1810 pvt->mce_overrun++;
1811 return 0;
1812 }
1813
1814 /* Copy memory error at the ringbuffer */
1815 memcpy(&pvt->mce_entry[pvt->mce_out], mce, sizeof(*mce));
1816 smp_wmb();
1817 pvt->mce_out = (pvt->mce_out + 1) % MCE_LOG_LEN;
1818
1819 /* Handle fatal errors immediately */
1820 if (mce->mcgstatus & 1)
1821 i7core_check_error(mci);
1822
1823 /* Advice mcelog that the error were handled */
1824 return 1;
1825}
1826
1827static int i7core_register_mci(struct i7core_dev *i7core_dev,
1828 int num_channels, int num_csrows)
1829{
1830 struct mem_ctl_info *mci;
1831 struct i7core_pvt *pvt;
1832 int csrow = 0;
1833 int rc;
1834
1835 /* allocate a new MC control structure */
1836 mci = edac_mc_alloc(sizeof(*pvt), num_csrows, num_channels,
1837 i7core_dev->socket);
1838 if (unlikely(!mci))
1839 return -ENOMEM;
1840
1841 debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci);
1842
1843 /* record ptr to the generic device */
1844 mci->dev = &i7core_dev->pdev[0]->dev;
1845
1846 pvt = mci->pvt_info;
1847 memset(pvt, 0, sizeof(*pvt));
1848
1849 /*
1850 * FIXME: how to handle RDDR3 at MCI level? It is possible to have
1851 * Mixed RDDR3/UDDR3 with Nehalem, provided that they are on different
1852 * memory channels
1853 */
1854 mci->mtype_cap = MEM_FLAG_DDR3;
1855 mci->edac_ctl_cap = EDAC_FLAG_NONE;
1856 mci->edac_cap = EDAC_FLAG_NONE;
1857 mci->mod_name = "i7core_edac.c";
1858 mci->mod_ver = I7CORE_REVISION;
1859 mci->ctl_name = kasprintf(GFP_KERNEL, "i7 core #%d",
1860 i7core_dev->socket);
1861 mci->dev_name = pci_name(i7core_dev->pdev[0]);
1862 mci->ctl_page_to_phys = NULL;
1863 mci->mc_driver_sysfs_attributes = i7core_sysfs_attrs;
1864 /* Set the function pointer to an actual operation function */
1865 mci->edac_check = i7core_check_error;
1866
1867 /* Store pci devices at mci for faster access */
1868 rc = mci_bind_devs(mci, i7core_dev);
1869 if (unlikely(rc < 0))
1870 goto fail;
1871
1872 /* Get dimm basic config */
1873 get_dimm_config(mci, &csrow);
1874
1875 /* add this new MC control structure to EDAC's list of MCs */
1876 if (unlikely(edac_mc_add_mc(mci))) {
1877 debugf0("MC: " __FILE__
1878 ": %s(): failed edac_mc_add_mc()\n", __func__);
1879 /* FIXME: perhaps some code should go here that disables error
1880 * reporting if we just enabled it
1881 */
1882
1883 rc = -EINVAL;
1884 goto fail;
1885 }
1886
1887 /* allocating generic PCI control info */
1888 i7core_pci = edac_pci_create_generic_ctl(&i7core_dev->pdev[0]->dev,
1889 EDAC_MOD_STR);
1890 if (unlikely(!i7core_pci)) {
1891 printk(KERN_WARNING
1892 "%s(): Unable to create PCI control\n",
1893 __func__);
1894 printk(KERN_WARNING
1895 "%s(): PCI error report via EDAC not setup\n",
1896 __func__);
1897 }
1898
1899 /* Default error mask is any memory */
1900 pvt->inject.channel = 0;
1901 pvt->inject.dimm = -1;
1902 pvt->inject.rank = -1;
1903 pvt->inject.bank = -1;
1904 pvt->inject.page = -1;
1905 pvt->inject.col = -1;
1906
1907 /* Registers on edac_mce in order to receive memory errors */
1908 pvt->edac_mce.priv = mci;
1909 pvt->edac_mce.check_error = i7core_mce_check_error;
1910
1911 rc = edac_mce_register(&pvt->edac_mce);
1912 if (unlikely(rc < 0)) {
1913 debugf0("MC: " __FILE__
1914 ": %s(): failed edac_mce_register()\n", __func__);
1915 }
1916
1917fail:
1918 if (rc < 0)
1919 edac_mc_free(mci);
1920 return rc;
1921}
1922
1923/*
1924 * i7core_probe Probe for ONE instance of device to see if it is
1925 * present.
1926 * return:
1927 * 0 for FOUND a device
1928 * < 0 for error code
1929 */
1930static int __devinit i7core_probe(struct pci_dev *pdev,
1931 const struct pci_device_id *id)
1932{
1933 int dev_idx = id->driver_data;
1934 int rc;
1935 struct i7core_dev *i7core_dev;
1936
1937 /*
1938 * All memory controllers are allocated at the first pass.
1939 */
1940 if (unlikely(dev_idx >= 1))
1941 return -EINVAL;
1942
1943 /* get the pci devices we want to reserve for our use */
1944 mutex_lock(&i7core_edac_lock);
1945
1946 rc = i7core_get_devices(pci_dev_table);
1947 if (unlikely(rc < 0))
1948 goto fail0;
1949
1950 list_for_each_entry(i7core_dev, &i7core_edac_list, list) {
1951 int channels;
1952 int csrows;
1953
1954 /* Check the number of active and not disabled channels */
1955 rc = i7core_get_active_channels(i7core_dev->socket,
1956 &channels, &csrows);
1957 if (unlikely(rc < 0))
1958 goto fail1;
1959
1960 rc = i7core_register_mci(i7core_dev, channels, csrows);
1961 if (unlikely(rc < 0))
1962 goto fail1;
1963 }
1964
1965 i7core_printk(KERN_INFO, "Driver loaded.\n");
1966
1967 mutex_unlock(&i7core_edac_lock);
1968 return 0;
1969
1970fail1:
1971 i7core_put_all_devices();
1972fail0:
1973 mutex_unlock(&i7core_edac_lock);
1974 return rc;
1975}
1976
1977/*
1978 * i7core_remove destructor for one instance of device
1979 *
1980 */
1981static void __devexit i7core_remove(struct pci_dev *pdev)
1982{
1983 struct mem_ctl_info *mci;
1984 struct i7core_dev *i7core_dev, *tmp;
1985
1986 debugf0(__FILE__ ": %s()\n", __func__);
1987
1988 if (i7core_pci)
1989 edac_pci_release_generic_ctl(i7core_pci);
1990
1991 /*
1992 * we have a trouble here: pdev value for removal will be wrong, since
1993 * it will point to the X58 register used to detect that the machine
1994 * is a Nehalem or upper design. However, due to the way several PCI
1995 * devices are grouped together to provide MC functionality, we need
1996 * to use a different method for releasing the devices
1997 */
1998
1999 mutex_lock(&i7core_edac_lock);
2000 list_for_each_entry_safe(i7core_dev, tmp, &i7core_edac_list, list) {
2001 mci = edac_mc_del_mc(&i7core_dev->pdev[0]->dev);
2002 if (mci) {
2003 struct i7core_pvt *pvt = mci->pvt_info;
2004
2005 i7core_dev = pvt->i7core_dev;
2006 edac_mce_unregister(&pvt->edac_mce);
2007 kfree(mci->ctl_name);
2008 edac_mc_free(mci);
2009 i7core_put_devices(i7core_dev);
2010 } else {
2011 i7core_printk(KERN_ERR,
2012 "Couldn't find mci for socket %d\n",
2013 i7core_dev->socket);
2014 }
2015 }
2016 mutex_unlock(&i7core_edac_lock);
2017}
2018
2019MODULE_DEVICE_TABLE(pci, i7core_pci_tbl);
2020
2021/*
2022 * i7core_driver pci_driver structure for this module
2023 *
2024 */
2025static struct pci_driver i7core_driver = {
2026 .name = "i7core_edac",
2027 .probe = i7core_probe,
2028 .remove = __devexit_p(i7core_remove),
2029 .id_table = i7core_pci_tbl,
2030};
2031
2032/*
2033 * i7core_init Module entry function
2034 * Try to initialize this module for its devices
2035 */
2036static int __init i7core_init(void)
2037{
2038 int pci_rc;
2039
2040 debugf2("MC: " __FILE__ ": %s()\n", __func__);
2041
2042 /* Ensure that the OPSTATE is set correctly for POLL or NMI */
2043 opstate_init();
2044
2045 i7core_xeon_pci_fixup(pci_dev_table);
2046
2047 pci_rc = pci_register_driver(&i7core_driver);
2048
2049 if (pci_rc >= 0)
2050 return 0;
2051
2052 i7core_printk(KERN_ERR, "Failed to register device with error %d.\n",
2053 pci_rc);
2054
2055 return pci_rc;
2056}
2057
2058/*
2059 * i7core_exit() Module exit function
2060 * Unregister the driver
2061 */
2062static void __exit i7core_exit(void)
2063{
2064 debugf2("MC: " __FILE__ ": %s()\n", __func__);
2065 pci_unregister_driver(&i7core_driver);
2066}
2067
2068module_init(i7core_init);
2069module_exit(i7core_exit);
2070
2071MODULE_LICENSE("GPL");
2072MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
2073MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
2074MODULE_DESCRIPTION("MC Driver for Intel i7 Core memory controllers - "
2075 I7CORE_REVISION);
2076
2077module_param(edac_op_state, int, 0444);
2078MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
diff --git a/drivers/edac/i82443bxgx_edac.c b/drivers/edac/i82443bxgx_edac.c
index 2bf2c5051bfe..a2fa1feed724 100644
--- a/drivers/edac/i82443bxgx_edac.c
+++ b/drivers/edac/i82443bxgx_edac.c
@@ -178,7 +178,7 @@ static void i82443bxgx_edacmc_check(struct mem_ctl_info *mci)
178{ 178{
179 struct i82443bxgx_edacmc_error_info info; 179 struct i82443bxgx_edacmc_error_info info;
180 180
181 debugf1("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__); 181 debugf1("MC%d: %s: %s()\n", mci->mc_idx, __FILE__, __func__);
182 i82443bxgx_edacmc_get_error_info(mci, &info); 182 i82443bxgx_edacmc_get_error_info(mci, &info);
183 i82443bxgx_edacmc_process_error_info(mci, &info, 1); 183 i82443bxgx_edacmc_process_error_info(mci, &info, 1);
184} 184}
@@ -198,13 +198,13 @@ static void i82443bxgx_init_csrows(struct mem_ctl_info *mci,
198 for (index = 0; index < mci->nr_csrows; index++) { 198 for (index = 0; index < mci->nr_csrows; index++) {
199 csrow = &mci->csrows[index]; 199 csrow = &mci->csrows[index];
200 pci_read_config_byte(pdev, I82443BXGX_DRB + index, &drbar); 200 pci_read_config_byte(pdev, I82443BXGX_DRB + index, &drbar);
201 debugf1("MC%d: " __FILE__ ": %s() Row=%d DRB = %#0x\n", 201 debugf1("MC%d: %s: %s() Row=%d DRB = %#0x\n",
202 mci->mc_idx, __func__, index, drbar); 202 mci->mc_idx, __FILE__, __func__, index, drbar);
203 row_high_limit = ((u32) drbar << 23); 203 row_high_limit = ((u32) drbar << 23);
204 /* find the DRAM Chip Select Base address and mask */ 204 /* find the DRAM Chip Select Base address and mask */
205 debugf1("MC%d: " __FILE__ ": %s() Row=%d, " 205 debugf1("MC%d: %s: %s() Row=%d, "
206 "Boundry Address=%#0x, Last = %#0x \n", 206 "Boundry Address=%#0x, Last = %#0x\n",
207 mci->mc_idx, __func__, index, row_high_limit, 207 mci->mc_idx, __FILE__, __func__, index, row_high_limit,
208 row_high_limit_last); 208 row_high_limit_last);
209 209
210 /* 440GX goes to 2GB, represented with a DRB of 0. */ 210 /* 440GX goes to 2GB, represented with a DRB of 0. */
@@ -237,7 +237,7 @@ static int i82443bxgx_edacmc_probe1(struct pci_dev *pdev, int dev_idx)
237 enum mem_type mtype; 237 enum mem_type mtype;
238 enum edac_type edac_mode; 238 enum edac_type edac_mode;
239 239
240 debugf0("MC: " __FILE__ ": %s()\n", __func__); 240 debugf0("MC: %s: %s()\n", __FILE__, __func__);
241 241
242 /* Something is really hosed if PCI config space reads from 242 /* Something is really hosed if PCI config space reads from
243 * the MC aren't working. 243 * the MC aren't working.
@@ -250,7 +250,7 @@ static int i82443bxgx_edacmc_probe1(struct pci_dev *pdev, int dev_idx)
250 if (mci == NULL) 250 if (mci == NULL)
251 return -ENOMEM; 251 return -ENOMEM;
252 252
253 debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci); 253 debugf0("MC: %s: %s(): mci = %p\n", __FILE__, __func__, mci);
254 mci->dev = &pdev->dev; 254 mci->dev = &pdev->dev;
255 mci->mtype_cap = MEM_FLAG_EDO | MEM_FLAG_SDR | MEM_FLAG_RDR; 255 mci->mtype_cap = MEM_FLAG_EDO | MEM_FLAG_SDR | MEM_FLAG_RDR;
256 mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; 256 mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED;
@@ -336,7 +336,7 @@ static int i82443bxgx_edacmc_probe1(struct pci_dev *pdev, int dev_idx)
336 __func__); 336 __func__);
337 } 337 }
338 338
339 debugf3("MC: " __FILE__ ": %s(): success\n", __func__); 339 debugf3("MC: %s: %s(): success\n", __FILE__, __func__);
340 return 0; 340 return 0;
341 341
342fail: 342fail:
@@ -352,7 +352,7 @@ static int __devinit i82443bxgx_edacmc_init_one(struct pci_dev *pdev,
352{ 352{
353 int rc; 353 int rc;
354 354
355 debugf0("MC: " __FILE__ ": %s()\n", __func__); 355 debugf0("MC: %s: %s()\n", __FILE__, __func__);
356 356
357 /* don't need to call pci_enable_device() */ 357 /* don't need to call pci_enable_device() */
358 rc = i82443bxgx_edacmc_probe1(pdev, ent->driver_data); 358 rc = i82443bxgx_edacmc_probe1(pdev, ent->driver_data);
@@ -367,7 +367,7 @@ static void __devexit i82443bxgx_edacmc_remove_one(struct pci_dev *pdev)
367{ 367{
368 struct mem_ctl_info *mci; 368 struct mem_ctl_info *mci;
369 369
370 debugf0(__FILE__ ": %s()\n", __func__); 370 debugf0("%s: %s()\n", __FILE__, __func__);
371 371
372 if (i82443bxgx_pci) 372 if (i82443bxgx_pci)
373 edac_pci_release_generic_ctl(i82443bxgx_pci); 373 edac_pci_release_generic_ctl(i82443bxgx_pci);
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
index 6c1886b497ff..52ca09bf4726 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/mpc85xx_edac.c
@@ -229,7 +229,7 @@ static int __devinit mpc85xx_pci_err_probe(struct of_device *op,
229 229
230 pdata->edac_idx = edac_pci_idx++; 230 pdata->edac_idx = edac_pci_idx++;
231 231
232 res = of_address_to_resource(op->node, 0, &r); 232 res = of_address_to_resource(op->dev.of_node, 0, &r);
233 if (res) { 233 if (res) {
234 printk(KERN_ERR "%s: Unable to get resource for " 234 printk(KERN_ERR "%s: Unable to get resource for "
235 "PCI err regs\n", __func__); 235 "PCI err regs\n", __func__);
@@ -274,7 +274,7 @@ static int __devinit mpc85xx_pci_err_probe(struct of_device *op,
274 } 274 }
275 275
276 if (edac_op_state == EDAC_OPSTATE_INT) { 276 if (edac_op_state == EDAC_OPSTATE_INT) {
277 pdata->irq = irq_of_parse_and_map(op->node, 0); 277 pdata->irq = irq_of_parse_and_map(op->dev.of_node, 0);
278 res = devm_request_irq(&op->dev, pdata->irq, 278 res = devm_request_irq(&op->dev, pdata->irq,
279 mpc85xx_pci_isr, IRQF_DISABLED, 279 mpc85xx_pci_isr, IRQF_DISABLED,
280 "[EDAC] PCI err", pci); 280 "[EDAC] PCI err", pci);
@@ -529,7 +529,7 @@ static int __devinit mpc85xx_l2_err_probe(struct of_device *op,
529 edac_dev->ctl_name = pdata->name; 529 edac_dev->ctl_name = pdata->name;
530 edac_dev->dev_name = pdata->name; 530 edac_dev->dev_name = pdata->name;
531 531
532 res = of_address_to_resource(op->node, 0, &r); 532 res = of_address_to_resource(op->dev.of_node, 0, &r);
533 if (res) { 533 if (res) {
534 printk(KERN_ERR "%s: Unable to get resource for " 534 printk(KERN_ERR "%s: Unable to get resource for "
535 "L2 err regs\n", __func__); 535 "L2 err regs\n", __func__);
@@ -576,7 +576,7 @@ static int __devinit mpc85xx_l2_err_probe(struct of_device *op,
576 } 576 }
577 577
578 if (edac_op_state == EDAC_OPSTATE_INT) { 578 if (edac_op_state == EDAC_OPSTATE_INT) {
579 pdata->irq = irq_of_parse_and_map(op->node, 0); 579 pdata->irq = irq_of_parse_and_map(op->dev.of_node, 0);
580 res = devm_request_irq(&op->dev, pdata->irq, 580 res = devm_request_irq(&op->dev, pdata->irq,
581 mpc85xx_l2_isr, IRQF_DISABLED, 581 mpc85xx_l2_isr, IRQF_DISABLED,
582 "[EDAC] L2 err", edac_dev); 582 "[EDAC] L2 err", edac_dev);
@@ -978,7 +978,7 @@ static int __devinit mpc85xx_mc_err_probe(struct of_device *op,
978 mci->ctl_name = pdata->name; 978 mci->ctl_name = pdata->name;
979 mci->dev_name = pdata->name; 979 mci->dev_name = pdata->name;
980 980
981 res = of_address_to_resource(op->node, 0, &r); 981 res = of_address_to_resource(op->dev.of_node, 0, &r);
982 if (res) { 982 if (res) {
983 printk(KERN_ERR "%s: Unable to get resource for MC err regs\n", 983 printk(KERN_ERR "%s: Unable to get resource for MC err regs\n",
984 __func__); 984 __func__);
@@ -1052,7 +1052,7 @@ static int __devinit mpc85xx_mc_err_probe(struct of_device *op,
1052 out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_SBE, 0x10000); 1052 out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_SBE, 0x10000);
1053 1053
1054 /* register interrupts */ 1054 /* register interrupts */
1055 pdata->irq = irq_of_parse_and_map(op->node, 0); 1055 pdata->irq = irq_of_parse_and_map(op->dev.of_node, 0);
1056 res = devm_request_irq(&op->dev, pdata->irq, 1056 res = devm_request_irq(&op->dev, pdata->irq,
1057 mpc85xx_mc_isr, 1057 mpc85xx_mc_isr,
1058 IRQF_DISABLED | IRQF_SHARED, 1058 IRQF_DISABLED | IRQF_SHARED,
diff --git a/drivers/edac/ppc4xx_edac.c b/drivers/edac/ppc4xx_edac.c
index 9d6f6783328c..e78839e89a06 100644
--- a/drivers/edac/ppc4xx_edac.c
+++ b/drivers/edac/ppc4xx_edac.c
@@ -1022,7 +1022,7 @@ ppc4xx_edac_mc_init(struct mem_ctl_info *mci,
1022 int status = 0; 1022 int status = 0;
1023 const u32 memcheck = (mcopt1 & SDRAM_MCOPT1_MCHK_MASK); 1023 const u32 memcheck = (mcopt1 & SDRAM_MCOPT1_MCHK_MASK);
1024 struct ppc4xx_edac_pdata *pdata = NULL; 1024 struct ppc4xx_edac_pdata *pdata = NULL;
1025 const struct device_node *np = op->node; 1025 const struct device_node *np = op->dev.of_node;
1026 1026
1027 if (match == NULL) 1027 if (match == NULL)
1028 return -EINVAL; 1028 return -EINVAL;
@@ -1113,7 +1113,7 @@ ppc4xx_edac_register_irq(struct of_device *op, struct mem_ctl_info *mci)
1113 int status = 0; 1113 int status = 0;
1114 int ded_irq, sec_irq; 1114 int ded_irq, sec_irq;
1115 struct ppc4xx_edac_pdata *pdata = mci->pvt_info; 1115 struct ppc4xx_edac_pdata *pdata = mci->pvt_info;
1116 struct device_node *np = op->node; 1116 struct device_node *np = op->dev.of_node;
1117 1117
1118 ded_irq = irq_of_parse_and_map(np, INTMAP_ECCDED_INDEX); 1118 ded_irq = irq_of_parse_and_map(np, INTMAP_ECCDED_INDEX);
1119 sec_irq = irq_of_parse_and_map(np, INTMAP_ECCSEC_INDEX); 1119 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)
1243 int status = 0; 1243 int status = 0;
1244 u32 mcopt1, memcheck; 1244 u32 mcopt1, memcheck;
1245 dcr_host_t dcr_host; 1245 dcr_host_t dcr_host;
1246 const struct device_node *np = op->node; 1246 const struct device_node *np = op->dev.of_node;
1247 struct mem_ctl_info *mci = NULL; 1247 struct mem_ctl_info *mci = NULL;
1248 static int ppc4xx_edac_instance; 1248 static int ppc4xx_edac_instance;
1249 1249
diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c
index 5045156c5313..371713ff0266 100644
--- a/drivers/firewire/core-card.c
+++ b/drivers/firewire/core-card.c
@@ -30,7 +30,6 @@
30#include <linux/module.h> 30#include <linux/module.h>
31#include <linux/mutex.h> 31#include <linux/mutex.h>
32#include <linux/spinlock.h> 32#include <linux/spinlock.h>
33#include <linux/timer.h>
34#include <linux/workqueue.h> 33#include <linux/workqueue.h>
35 34
36#include <asm/atomic.h> 35#include <asm/atomic.h>
@@ -63,7 +62,7 @@ static size_t config_rom_length = 1 + 4 + 1 + 1;
63#define BIB_CRC(v) ((v) << 0) 62#define BIB_CRC(v) ((v) << 0)
64#define BIB_CRC_LENGTH(v) ((v) << 16) 63#define BIB_CRC_LENGTH(v) ((v) << 16)
65#define BIB_INFO_LENGTH(v) ((v) << 24) 64#define BIB_INFO_LENGTH(v) ((v) << 24)
66 65#define BIB_BUS_NAME 0x31333934 /* "1394" */
67#define BIB_LINK_SPEED(v) ((v) << 0) 66#define BIB_LINK_SPEED(v) ((v) << 0)
68#define BIB_GENERATION(v) ((v) << 4) 67#define BIB_GENERATION(v) ((v) << 4)
69#define BIB_MAX_ROM(v) ((v) << 8) 68#define BIB_MAX_ROM(v) ((v) << 8)
@@ -73,7 +72,8 @@ static size_t config_rom_length = 1 + 4 + 1 + 1;
73#define BIB_BMC ((1) << 28) 72#define BIB_BMC ((1) << 28)
74#define BIB_ISC ((1) << 29) 73#define BIB_ISC ((1) << 29)
75#define BIB_CMC ((1) << 30) 74#define BIB_CMC ((1) << 30)
76#define BIB_IMC ((1) << 31) 75#define BIB_IRMC ((1) << 31)
76#define NODE_CAPABILITIES 0x0c0083c0 /* per IEEE 1394 clause 8.3.2.6.5.2 */
77 77
78static void generate_config_rom(struct fw_card *card, __be32 *config_rom) 78static void generate_config_rom(struct fw_card *card, __be32 *config_rom)
79{ 79{
@@ -91,18 +91,18 @@ static void generate_config_rom(struct fw_card *card, __be32 *config_rom)
91 91
92 config_rom[0] = cpu_to_be32( 92 config_rom[0] = cpu_to_be32(
93 BIB_CRC_LENGTH(4) | BIB_INFO_LENGTH(4) | BIB_CRC(0)); 93 BIB_CRC_LENGTH(4) | BIB_INFO_LENGTH(4) | BIB_CRC(0));
94 config_rom[1] = cpu_to_be32(0x31333934); 94 config_rom[1] = cpu_to_be32(BIB_BUS_NAME);
95 config_rom[2] = cpu_to_be32( 95 config_rom[2] = cpu_to_be32(
96 BIB_LINK_SPEED(card->link_speed) | 96 BIB_LINK_SPEED(card->link_speed) |
97 BIB_GENERATION(card->config_rom_generation++ % 14 + 2) | 97 BIB_GENERATION(card->config_rom_generation++ % 14 + 2) |
98 BIB_MAX_ROM(2) | 98 BIB_MAX_ROM(2) |
99 BIB_MAX_RECEIVE(card->max_receive) | 99 BIB_MAX_RECEIVE(card->max_receive) |
100 BIB_BMC | BIB_ISC | BIB_CMC | BIB_IMC); 100 BIB_BMC | BIB_ISC | BIB_CMC | BIB_IRMC);
101 config_rom[3] = cpu_to_be32(card->guid >> 32); 101 config_rom[3] = cpu_to_be32(card->guid >> 32);
102 config_rom[4] = cpu_to_be32(card->guid); 102 config_rom[4] = cpu_to_be32(card->guid);
103 103
104 /* Generate root directory. */ 104 /* Generate root directory. */
105 config_rom[6] = cpu_to_be32(0x0c0083c0); /* node capabilities */ 105 config_rom[6] = cpu_to_be32(NODE_CAPABILITIES);
106 i = 7; 106 i = 7;
107 j = 7 + descriptor_count; 107 j = 7 + descriptor_count;
108 108
@@ -231,7 +231,7 @@ void fw_schedule_bm_work(struct fw_card *card, unsigned long delay)
231static void fw_card_bm_work(struct work_struct *work) 231static void fw_card_bm_work(struct work_struct *work)
232{ 232{
233 struct fw_card *card = container_of(work, struct fw_card, work.work); 233 struct fw_card *card = container_of(work, struct fw_card, work.work);
234 struct fw_device *root_device; 234 struct fw_device *root_device, *irm_device;
235 struct fw_node *root_node; 235 struct fw_node *root_node;
236 unsigned long flags; 236 unsigned long flags;
237 int root_id, new_root_id, irm_id, local_id; 237 int root_id, new_root_id, irm_id, local_id;
@@ -239,6 +239,7 @@ static void fw_card_bm_work(struct work_struct *work)
239 bool do_reset = false; 239 bool do_reset = false;
240 bool root_device_is_running; 240 bool root_device_is_running;
241 bool root_device_is_cmc; 241 bool root_device_is_cmc;
242 bool irm_is_1394_1995_only;
242 243
243 spin_lock_irqsave(&card->lock, flags); 244 spin_lock_irqsave(&card->lock, flags);
244 245
@@ -248,12 +249,18 @@ static void fw_card_bm_work(struct work_struct *work)
248 } 249 }
249 250
250 generation = card->generation; 251 generation = card->generation;
252
251 root_node = card->root_node; 253 root_node = card->root_node;
252 fw_node_get(root_node); 254 fw_node_get(root_node);
253 root_device = root_node->data; 255 root_device = root_node->data;
254 root_device_is_running = root_device && 256 root_device_is_running = root_device &&
255 atomic_read(&root_device->state) == FW_DEVICE_RUNNING; 257 atomic_read(&root_device->state) == FW_DEVICE_RUNNING;
256 root_device_is_cmc = root_device && root_device->cmc; 258 root_device_is_cmc = root_device && root_device->cmc;
259
260 irm_device = card->irm_node->data;
261 irm_is_1394_1995_only = irm_device && irm_device->config_rom &&
262 (irm_device->config_rom[2] & 0x000000f0) == 0;
263
257 root_id = root_node->node_id; 264 root_id = root_node->node_id;
258 irm_id = card->irm_node->node_id; 265 irm_id = card->irm_node->node_id;
259 local_id = card->local_node->node_id; 266 local_id = card->local_node->node_id;
@@ -276,8 +283,15 @@ static void fw_card_bm_work(struct work_struct *work)
276 283
277 if (!card->irm_node->link_on) { 284 if (!card->irm_node->link_on) {
278 new_root_id = local_id; 285 new_root_id = local_id;
279 fw_notify("IRM has link off, making local node (%02x) root.\n", 286 fw_notify("%s, making local node (%02x) root.\n",
280 new_root_id); 287 "IRM has link off", new_root_id);
288 goto pick_me;
289 }
290
291 if (irm_is_1394_1995_only) {
292 new_root_id = local_id;
293 fw_notify("%s, making local node (%02x) root.\n",
294 "IRM is not 1394a compliant", new_root_id);
281 goto pick_me; 295 goto pick_me;
282 } 296 }
283 297
@@ -316,8 +330,8 @@ static void fw_card_bm_work(struct work_struct *work)
316 * root, and thus, IRM. 330 * root, and thus, IRM.
317 */ 331 */
318 new_root_id = local_id; 332 new_root_id = local_id;
319 fw_notify("BM lock failed, making local node (%02x) root.\n", 333 fw_notify("%s, making local node (%02x) root.\n",
320 new_root_id); 334 "BM lock failed", new_root_id);
321 goto pick_me; 335 goto pick_me;
322 } 336 }
323 } else if (card->bm_generation != generation) { 337 } else if (card->bm_generation != generation) {
@@ -407,13 +421,6 @@ static void fw_card_bm_work(struct work_struct *work)
407 fw_card_put(card); 421 fw_card_put(card);
408} 422}
409 423
410static void flush_timer_callback(unsigned long data)
411{
412 struct fw_card *card = (struct fw_card *)data;
413
414 fw_flush_transactions(card);
415}
416
417void fw_card_initialize(struct fw_card *card, 424void fw_card_initialize(struct fw_card *card,
418 const struct fw_card_driver *driver, 425 const struct fw_card_driver *driver,
419 struct device *device) 426 struct device *device)
@@ -432,8 +439,6 @@ void fw_card_initialize(struct fw_card *card,
432 init_completion(&card->done); 439 init_completion(&card->done);
433 INIT_LIST_HEAD(&card->transaction_list); 440 INIT_LIST_HEAD(&card->transaction_list);
434 spin_lock_init(&card->lock); 441 spin_lock_init(&card->lock);
435 setup_timer(&card->flush_timer,
436 flush_timer_callback, (unsigned long)card);
437 442
438 card->local_node = NULL; 443 card->local_node = NULL;
439 444
@@ -558,7 +563,6 @@ void fw_core_remove_card(struct fw_card *card)
558 wait_for_completion(&card->done); 563 wait_for_completion(&card->done);
559 564
560 WARN_ON(!list_empty(&card->transaction_list)); 565 WARN_ON(!list_empty(&card->transaction_list));
561 del_timer_sync(&card->flush_timer);
562} 566}
563EXPORT_SYMBOL(fw_core_remove_card); 567EXPORT_SYMBOL(fw_core_remove_card);
564 568
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c
index 14a34d99eea2..5bf106b9d791 100644
--- a/drivers/firewire/core-cdev.c
+++ b/drivers/firewire/core-cdev.c
@@ -227,7 +227,7 @@ static int fw_device_op_open(struct inode *inode, struct file *file)
227 list_add_tail(&client->link, &device->client_list); 227 list_add_tail(&client->link, &device->client_list);
228 mutex_unlock(&device->client_list_mutex); 228 mutex_unlock(&device->client_list_mutex);
229 229
230 return 0; 230 return nonseekable_open(inode, file);
231} 231}
232 232
233static void queue_event(struct client *client, struct event *event, 233static void queue_event(struct client *client, struct event *event,
@@ -1496,13 +1496,13 @@ static unsigned int fw_device_op_poll(struct file *file, poll_table * pt)
1496 1496
1497const struct file_operations fw_device_ops = { 1497const struct file_operations fw_device_ops = {
1498 .owner = THIS_MODULE, 1498 .owner = THIS_MODULE,
1499 .llseek = no_llseek,
1499 .open = fw_device_op_open, 1500 .open = fw_device_op_open,
1500 .read = fw_device_op_read, 1501 .read = fw_device_op_read,
1501 .unlocked_ioctl = fw_device_op_ioctl, 1502 .unlocked_ioctl = fw_device_op_ioctl,
1502 .poll = fw_device_op_poll,
1503 .release = fw_device_op_release,
1504 .mmap = fw_device_op_mmap, 1503 .mmap = fw_device_op_mmap,
1505 1504 .release = fw_device_op_release,
1505 .poll = fw_device_op_poll,
1506#ifdef CONFIG_COMPAT 1506#ifdef CONFIG_COMPAT
1507 .compat_ioctl = fw_device_op_compat_ioctl, 1507 .compat_ioctl = fw_device_op_compat_ioctl,
1508#endif 1508#endif
diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c
index 673b03f8b4ec..fdc33ff06dc1 100644
--- a/drivers/firewire/core-transaction.c
+++ b/drivers/firewire/core-transaction.c
@@ -81,7 +81,7 @@ static int close_transaction(struct fw_transaction *transaction,
81 spin_lock_irqsave(&card->lock, flags); 81 spin_lock_irqsave(&card->lock, flags);
82 list_for_each_entry(t, &card->transaction_list, link) { 82 list_for_each_entry(t, &card->transaction_list, link) {
83 if (t == transaction) { 83 if (t == transaction) {
84 list_del(&t->link); 84 list_del_init(&t->link);
85 card->tlabel_mask &= ~(1ULL << t->tlabel); 85 card->tlabel_mask &= ~(1ULL << t->tlabel);
86 break; 86 break;
87 } 87 }
@@ -89,6 +89,7 @@ static int close_transaction(struct fw_transaction *transaction,
89 spin_unlock_irqrestore(&card->lock, flags); 89 spin_unlock_irqrestore(&card->lock, flags);
90 90
91 if (&t->link != &card->transaction_list) { 91 if (&t->link != &card->transaction_list) {
92 del_timer_sync(&t->split_timeout_timer);
92 t->callback(card, rcode, NULL, 0, t->callback_data); 93 t->callback(card, rcode, NULL, 0, t->callback_data);
93 return 0; 94 return 0;
94 } 95 }
@@ -121,6 +122,31 @@ int fw_cancel_transaction(struct fw_card *card,
121} 122}
122EXPORT_SYMBOL(fw_cancel_transaction); 123EXPORT_SYMBOL(fw_cancel_transaction);
123 124
125static void split_transaction_timeout_callback(unsigned long data)
126{
127 struct fw_transaction *t = (struct fw_transaction *)data;
128 struct fw_card *card = t->card;
129 unsigned long flags;
130
131 spin_lock_irqsave(&card->lock, flags);
132 if (list_empty(&t->link)) {
133 spin_unlock_irqrestore(&card->lock, flags);
134 return;
135 }
136 list_del(&t->link);
137 card->tlabel_mask &= ~(1ULL << t->tlabel);
138 spin_unlock_irqrestore(&card->lock, flags);
139
140 card->driver->cancel_packet(card, &t->packet);
141
142 /*
143 * At this point cancel_packet will never call the transaction
144 * callback, since we just took the transaction out of the list.
145 * So do it here.
146 */
147 t->callback(card, RCODE_CANCELLED, NULL, 0, t->callback_data);
148}
149
124static void transmit_complete_callback(struct fw_packet *packet, 150static void transmit_complete_callback(struct fw_packet *packet,
125 struct fw_card *card, int status) 151 struct fw_card *card, int status)
126{ 152{
@@ -229,6 +255,23 @@ static void fw_fill_request(struct fw_packet *packet, int tcode, int tlabel,
229 packet->payload_mapped = false; 255 packet->payload_mapped = false;
230} 256}
231 257
258static int allocate_tlabel(struct fw_card *card)
259{
260 int tlabel;
261
262 tlabel = card->current_tlabel;
263 while (card->tlabel_mask & (1ULL << tlabel)) {
264 tlabel = (tlabel + 1) & 0x3f;
265 if (tlabel == card->current_tlabel)
266 return -EBUSY;
267 }
268
269 card->current_tlabel = (tlabel + 1) & 0x3f;
270 card->tlabel_mask |= 1ULL << tlabel;
271
272 return tlabel;
273}
274
232/** 275/**
233 * This function provides low-level access to the IEEE1394 transaction 276 * This function provides low-level access to the IEEE1394 transaction
234 * logic. Most C programs would use either fw_read(), fw_write() or 277 * logic. Most C programs would use either fw_read(), fw_write() or
@@ -277,31 +320,26 @@ void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode,
277 int tlabel; 320 int tlabel;
278 321
279 /* 322 /*
280 * Bump the flush timer up 100ms first of all so we
281 * don't race with a flush timer callback.
282 */
283
284 mod_timer(&card->flush_timer, jiffies + DIV_ROUND_UP(HZ, 10));
285
286 /*
287 * Allocate tlabel from the bitmap and put the transaction on 323 * Allocate tlabel from the bitmap and put the transaction on
288 * the list while holding the card spinlock. 324 * the list while holding the card spinlock.
289 */ 325 */
290 326
291 spin_lock_irqsave(&card->lock, flags); 327 spin_lock_irqsave(&card->lock, flags);
292 328
293 tlabel = card->current_tlabel; 329 tlabel = allocate_tlabel(card);
294 if (card->tlabel_mask & (1ULL << tlabel)) { 330 if (tlabel < 0) {
295 spin_unlock_irqrestore(&card->lock, flags); 331 spin_unlock_irqrestore(&card->lock, flags);
296 callback(card, RCODE_SEND_ERROR, NULL, 0, callback_data); 332 callback(card, RCODE_SEND_ERROR, NULL, 0, callback_data);
297 return; 333 return;
298 } 334 }
299 335
300 card->current_tlabel = (card->current_tlabel + 1) & 0x3f;
301 card->tlabel_mask |= (1ULL << tlabel);
302
303 t->node_id = destination_id; 336 t->node_id = destination_id;
304 t->tlabel = tlabel; 337 t->tlabel = tlabel;
338 t->card = card;
339 setup_timer(&t->split_timeout_timer,
340 split_transaction_timeout_callback, (unsigned long)t);
341 /* FIXME: start this timer later, relative to t->timestamp */
342 mod_timer(&t->split_timeout_timer, jiffies + DIV_ROUND_UP(HZ, 10));
305 t->callback = callback; 343 t->callback = callback;
306 t->callback_data = callback_data; 344 t->callback_data = callback_data;
307 345
@@ -347,11 +385,13 @@ int fw_run_transaction(struct fw_card *card, int tcode, int destination_id,
347 struct transaction_callback_data d; 385 struct transaction_callback_data d;
348 struct fw_transaction t; 386 struct fw_transaction t;
349 387
388 init_timer_on_stack(&t.split_timeout_timer);
350 init_completion(&d.done); 389 init_completion(&d.done);
351 d.payload = payload; 390 d.payload = payload;
352 fw_send_request(card, &t, tcode, destination_id, generation, speed, 391 fw_send_request(card, &t, tcode, destination_id, generation, speed,
353 offset, payload, length, transaction_callback, &d); 392 offset, payload, length, transaction_callback, &d);
354 wait_for_completion(&d.done); 393 wait_for_completion(&d.done);
394 destroy_timer_on_stack(&t.split_timeout_timer);
355 395
356 return d.rcode; 396 return d.rcode;
357} 397}
@@ -394,30 +434,6 @@ void fw_send_phy_config(struct fw_card *card,
394 mutex_unlock(&phy_config_mutex); 434 mutex_unlock(&phy_config_mutex);
395} 435}
396 436
397void fw_flush_transactions(struct fw_card *card)
398{
399 struct fw_transaction *t, *next;
400 struct list_head list;
401 unsigned long flags;
402
403 INIT_LIST_HEAD(&list);
404 spin_lock_irqsave(&card->lock, flags);
405 list_splice_init(&card->transaction_list, &list);
406 card->tlabel_mask = 0;
407 spin_unlock_irqrestore(&card->lock, flags);
408
409 list_for_each_entry_safe(t, next, &list, link) {
410 card->driver->cancel_packet(card, &t->packet);
411
412 /*
413 * At this point cancel_packet will never call the
414 * transaction callback, since we just took all the
415 * transactions out of the list. So do it here.
416 */
417 t->callback(card, RCODE_CANCELLED, NULL, 0, t->callback_data);
418 }
419}
420
421static struct fw_address_handler *lookup_overlapping_address_handler( 437static struct fw_address_handler *lookup_overlapping_address_handler(
422 struct list_head *list, unsigned long long offset, size_t length) 438 struct list_head *list, unsigned long long offset, size_t length)
423{ 439{
@@ -827,8 +843,8 @@ void fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
827 spin_lock_irqsave(&card->lock, flags); 843 spin_lock_irqsave(&card->lock, flags);
828 list_for_each_entry(t, &card->transaction_list, link) { 844 list_for_each_entry(t, &card->transaction_list, link) {
829 if (t->node_id == source && t->tlabel == tlabel) { 845 if (t->node_id == source && t->tlabel == tlabel) {
830 list_del(&t->link); 846 list_del_init(&t->link);
831 card->tlabel_mask &= ~(1 << t->tlabel); 847 card->tlabel_mask &= ~(1ULL << t->tlabel);
832 break; 848 break;
833 } 849 }
834 } 850 }
@@ -869,6 +885,8 @@ void fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
869 break; 885 break;
870 } 886 }
871 887
888 del_timer_sync(&t->split_timeout_timer);
889
872 /* 890 /*
873 * The response handler may be executed while the request handler 891 * The response handler may be executed while the request handler
874 * is still pending. Cancel the request handler. 892 * is still pending. Cancel the request handler.
diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h
index fb0321300cce..0ecfcd95f4c5 100644
--- a/drivers/firewire/core.h
+++ b/drivers/firewire/core.h
@@ -27,7 +27,12 @@ struct fw_packet;
27#define PHY_LINK_ACTIVE 0x80 27#define PHY_LINK_ACTIVE 0x80
28#define PHY_CONTENDER 0x40 28#define PHY_CONTENDER 0x40
29#define PHY_BUS_RESET 0x40 29#define PHY_BUS_RESET 0x40
30#define PHY_EXTENDED_REGISTERS 0xe0
30#define PHY_BUS_SHORT_RESET 0x40 31#define PHY_BUS_SHORT_RESET 0x40
32#define PHY_INT_STATUS_BITS 0x3c
33#define PHY_ENABLE_ACCEL 0x02
34#define PHY_ENABLE_MULTI 0x01
35#define PHY_PAGE_SELECT 0xe0
31 36
32#define BANDWIDTH_AVAILABLE_INITIAL 4915 37#define BANDWIDTH_AVAILABLE_INITIAL 4915
33#define BROADCAST_CHANNEL_INITIAL (1 << 31 | 31) 38#define BROADCAST_CHANNEL_INITIAL (1 << 31 | 31)
@@ -215,7 +220,6 @@ void fw_core_handle_request(struct fw_card *card, struct fw_packet *request);
215void fw_core_handle_response(struct fw_card *card, struct fw_packet *packet); 220void fw_core_handle_response(struct fw_card *card, struct fw_packet *packet);
216void fw_fill_response(struct fw_packet *response, u32 *request_header, 221void fw_fill_response(struct fw_packet *response, u32 *request_header,
217 int rcode, void *payload, size_t length); 222 int rcode, void *payload, size_t length);
218void fw_flush_transactions(struct fw_card *card);
219void fw_send_phy_config(struct fw_card *card, 223void fw_send_phy_config(struct fw_card *card,
220 int node_id, int generation, int gap_count); 224 int node_id, int generation, int gap_count);
221 225
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index a3b083a7403a..9f627e758cfc 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -236,13 +236,15 @@ static char ohci_driver_name[] = KBUILD_MODNAME;
236#define QUIRK_CYCLE_TIMER 1 236#define QUIRK_CYCLE_TIMER 1
237#define QUIRK_RESET_PACKET 2 237#define QUIRK_RESET_PACKET 2
238#define QUIRK_BE_HEADERS 4 238#define QUIRK_BE_HEADERS 4
239#define QUIRK_NO_1394A 8
239 240
240/* In case of multiple matches in ohci_quirks[], only the first one is used. */ 241/* In case of multiple matches in ohci_quirks[], only the first one is used. */
241static const struct { 242static const struct {
242 unsigned short vendor, device, flags; 243 unsigned short vendor, device, flags;
243} ohci_quirks[] = { 244} ohci_quirks[] = {
244 {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV22, QUIRK_CYCLE_TIMER | 245 {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV22, QUIRK_CYCLE_TIMER |
245 QUIRK_RESET_PACKET}, 246 QUIRK_RESET_PACKET |
247 QUIRK_NO_1394A},
246 {PCI_VENDOR_ID_TI, PCI_ANY_ID, QUIRK_RESET_PACKET}, 248 {PCI_VENDOR_ID_TI, PCI_ANY_ID, QUIRK_RESET_PACKET},
247 {PCI_VENDOR_ID_AL, PCI_ANY_ID, QUIRK_CYCLE_TIMER}, 249 {PCI_VENDOR_ID_AL, PCI_ANY_ID, QUIRK_CYCLE_TIMER},
248 {PCI_VENDOR_ID_NEC, PCI_ANY_ID, QUIRK_CYCLE_TIMER}, 250 {PCI_VENDOR_ID_NEC, PCI_ANY_ID, QUIRK_CYCLE_TIMER},
@@ -257,15 +259,16 @@ MODULE_PARM_DESC(quirks, "Chip quirks (default = 0"
257 ", nonatomic cycle timer = " __stringify(QUIRK_CYCLE_TIMER) 259 ", nonatomic cycle timer = " __stringify(QUIRK_CYCLE_TIMER)
258 ", reset packet generation = " __stringify(QUIRK_RESET_PACKET) 260 ", reset packet generation = " __stringify(QUIRK_RESET_PACKET)
259 ", AR/selfID endianess = " __stringify(QUIRK_BE_HEADERS) 261 ", AR/selfID endianess = " __stringify(QUIRK_BE_HEADERS)
262 ", no 1394a enhancements = " __stringify(QUIRK_NO_1394A)
260 ")"); 263 ")");
261 264
262#ifdef CONFIG_FIREWIRE_OHCI_DEBUG
263
264#define OHCI_PARAM_DEBUG_AT_AR 1 265#define OHCI_PARAM_DEBUG_AT_AR 1
265#define OHCI_PARAM_DEBUG_SELFIDS 2 266#define OHCI_PARAM_DEBUG_SELFIDS 2
266#define OHCI_PARAM_DEBUG_IRQS 4 267#define OHCI_PARAM_DEBUG_IRQS 4
267#define OHCI_PARAM_DEBUG_BUSRESETS 8 /* only effective before chip init */ 268#define OHCI_PARAM_DEBUG_BUSRESETS 8 /* only effective before chip init */
268 269
270#ifdef CONFIG_FIREWIRE_OHCI_DEBUG
271
269static int param_debug; 272static int param_debug;
270module_param_named(debug, param_debug, int, 0644); 273module_param_named(debug, param_debug, int, 0644);
271MODULE_PARM_DESC(debug, "Verbose logging (default = 0" 274MODULE_PARM_DESC(debug, "Verbose logging (default = 0"
@@ -438,9 +441,10 @@ static void log_ar_at_event(char dir, int speed, u32 *header, int evt)
438 441
439#else 442#else
440 443
441#define log_irqs(evt) 444#define param_debug 0
442#define log_selfids(node_id, generation, self_id_count, sid) 445static inline void log_irqs(u32 evt) {}
443#define log_ar_at_event(dir, speed, header, evt) 446static inline void log_selfids(int node_id, int generation, int self_id_count, u32 *s) {}
447static inline void log_ar_at_event(char dir, int speed, u32 *header, int evt) {}
444 448
445#endif /* CONFIG_FIREWIRE_OHCI_DEBUG */ 449#endif /* CONFIG_FIREWIRE_OHCI_DEBUG */
446 450
@@ -460,27 +464,71 @@ static inline void flush_writes(const struct fw_ohci *ohci)
460 reg_read(ohci, OHCI1394_Version); 464 reg_read(ohci, OHCI1394_Version);
461} 465}
462 466
463static int ohci_update_phy_reg(struct fw_card *card, int addr, 467static int read_phy_reg(struct fw_ohci *ohci, int addr)
464 int clear_bits, int set_bits)
465{ 468{
466 struct fw_ohci *ohci = fw_ohci(card); 469 u32 val;
467 u32 val, old; 470 int i;
468 471
469 reg_write(ohci, OHCI1394_PhyControl, OHCI1394_PhyControl_Read(addr)); 472 reg_write(ohci, OHCI1394_PhyControl, OHCI1394_PhyControl_Read(addr));
470 flush_writes(ohci); 473 for (i = 0; i < 10; i++) {
471 msleep(2); 474 val = reg_read(ohci, OHCI1394_PhyControl);
472 val = reg_read(ohci, OHCI1394_PhyControl); 475 if (val & OHCI1394_PhyControl_ReadDone)
473 if ((val & OHCI1394_PhyControl_ReadDone) == 0) { 476 return OHCI1394_PhyControl_ReadData(val);
474 fw_error("failed to set phy reg bits.\n"); 477
475 return -EBUSY; 478 msleep(1);
476 } 479 }
480 fw_error("failed to read phy reg\n");
481
482 return -EBUSY;
483}
484
485static int write_phy_reg(const struct fw_ohci *ohci, int addr, u32 val)
486{
487 int i;
477 488
478 old = OHCI1394_PhyControl_ReadData(val);
479 old = (old & ~clear_bits) | set_bits;
480 reg_write(ohci, OHCI1394_PhyControl, 489 reg_write(ohci, OHCI1394_PhyControl,
481 OHCI1394_PhyControl_Write(addr, old)); 490 OHCI1394_PhyControl_Write(addr, val));
491 for (i = 0; i < 100; i++) {
492 val = reg_read(ohci, OHCI1394_PhyControl);
493 if (!(val & OHCI1394_PhyControl_WritePending))
494 return 0;
482 495
483 return 0; 496 msleep(1);
497 }
498 fw_error("failed to write phy reg\n");
499
500 return -EBUSY;
501}
502
503static int ohci_update_phy_reg(struct fw_card *card, int addr,
504 int clear_bits, int set_bits)
505{
506 struct fw_ohci *ohci = fw_ohci(card);
507 int ret;
508
509 ret = read_phy_reg(ohci, addr);
510 if (ret < 0)
511 return ret;
512
513 /*
514 * The interrupt status bits are cleared by writing a one bit.
515 * Avoid clearing them unless explicitly requested in set_bits.
516 */
517 if (addr == 5)
518 clear_bits |= PHY_INT_STATUS_BITS;
519
520 return write_phy_reg(ohci, addr, (ret & ~clear_bits) | set_bits);
521}
522
523static int read_paged_phy_reg(struct fw_ohci *ohci, int page, int addr)
524{
525 int ret;
526
527 ret = ohci_update_phy_reg(&ohci->card, 7, PHY_PAGE_SELECT, page << 5);
528 if (ret < 0)
529 return ret;
530
531 return read_phy_reg(ohci, addr);
484} 532}
485 533
486static int ar_context_add_page(struct ar_context *ctx) 534static int ar_context_add_page(struct ar_context *ctx)
@@ -1495,13 +1543,64 @@ static void copy_config_rom(__be32 *dest, const __be32 *src, size_t length)
1495 memset(&dest[length], 0, CONFIG_ROM_SIZE - size); 1543 memset(&dest[length], 0, CONFIG_ROM_SIZE - size);
1496} 1544}
1497 1545
1546static int configure_1394a_enhancements(struct fw_ohci *ohci)
1547{
1548 bool enable_1394a;
1549 int ret, clear, set, offset;
1550
1551 /* Check if the driver should configure link and PHY. */
1552 if (!(reg_read(ohci, OHCI1394_HCControlSet) &
1553 OHCI1394_HCControl_programPhyEnable))
1554 return 0;
1555
1556 /* Paranoia: check whether the PHY supports 1394a, too. */
1557 enable_1394a = false;
1558 ret = read_phy_reg(ohci, 2);
1559 if (ret < 0)
1560 return ret;
1561 if ((ret & PHY_EXTENDED_REGISTERS) == PHY_EXTENDED_REGISTERS) {
1562 ret = read_paged_phy_reg(ohci, 1, 8);
1563 if (ret < 0)
1564 return ret;
1565 if (ret >= 1)
1566 enable_1394a = true;
1567 }
1568
1569 if (ohci->quirks & QUIRK_NO_1394A)
1570 enable_1394a = false;
1571
1572 /* Configure PHY and link consistently. */
1573 if (enable_1394a) {
1574 clear = 0;
1575 set = PHY_ENABLE_ACCEL | PHY_ENABLE_MULTI;
1576 } else {
1577 clear = PHY_ENABLE_ACCEL | PHY_ENABLE_MULTI;
1578 set = 0;
1579 }
1580 ret = ohci_update_phy_reg(&ohci->card, 5, clear, set);
1581 if (ret < 0)
1582 return ret;
1583
1584 if (enable_1394a)
1585 offset = OHCI1394_HCControlSet;
1586 else
1587 offset = OHCI1394_HCControlClear;
1588 reg_write(ohci, offset, OHCI1394_HCControl_aPhyEnhanceEnable);
1589
1590 /* Clean up: configuration has been taken care of. */
1591 reg_write(ohci, OHCI1394_HCControlClear,
1592 OHCI1394_HCControl_programPhyEnable);
1593
1594 return 0;
1595}
1596
1498static int ohci_enable(struct fw_card *card, 1597static int ohci_enable(struct fw_card *card,
1499 const __be32 *config_rom, size_t length) 1598 const __be32 *config_rom, size_t length)
1500{ 1599{
1501 struct fw_ohci *ohci = fw_ohci(card); 1600 struct fw_ohci *ohci = fw_ohci(card);
1502 struct pci_dev *dev = to_pci_dev(card->device); 1601 struct pci_dev *dev = to_pci_dev(card->device);
1503 u32 lps; 1602 u32 lps;
1504 int i; 1603 int i, ret;
1505 1604
1506 if (software_reset(ohci)) { 1605 if (software_reset(ohci)) {
1507 fw_error("Failed to reset ohci card.\n"); 1606 fw_error("Failed to reset ohci card.\n");
@@ -1565,10 +1664,14 @@ static int ohci_enable(struct fw_card *card,
1565 if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS) 1664 if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS)
1566 reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset); 1665 reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset);
1567 1666
1667 ret = configure_1394a_enhancements(ohci);
1668 if (ret < 0)
1669 return ret;
1670
1568 /* Activate link_on bit and contender bit in our self ID packets.*/ 1671 /* Activate link_on bit and contender bit in our self ID packets.*/
1569 if (ohci_update_phy_reg(card, 4, 0, 1672 ret = ohci_update_phy_reg(card, 4, 0, PHY_LINK_ACTIVE | PHY_CONTENDER);
1570 PHY_LINK_ACTIVE | PHY_CONTENDER) < 0) 1673 if (ret < 0)
1571 return -EIO; 1674 return ret;
1572 1675
1573 /* 1676 /*
1574 * When the link is not yet enabled, the atomic config rom 1677 * When the link is not yet enabled, the atomic config rom
@@ -2304,7 +2407,7 @@ static const struct fw_card_driver ohci_driver = {
2304}; 2407};
2305 2408
2306#ifdef CONFIG_PPC_PMAC 2409#ifdef CONFIG_PPC_PMAC
2307static void ohci_pmac_on(struct pci_dev *dev) 2410static void pmac_ohci_on(struct pci_dev *dev)
2308{ 2411{
2309 if (machine_is(powermac)) { 2412 if (machine_is(powermac)) {
2310 struct device_node *ofn = pci_device_to_OF_node(dev); 2413 struct device_node *ofn = pci_device_to_OF_node(dev);
@@ -2316,7 +2419,7 @@ static void ohci_pmac_on(struct pci_dev *dev)
2316 } 2419 }
2317} 2420}
2318 2421
2319static void ohci_pmac_off(struct pci_dev *dev) 2422static void pmac_ohci_off(struct pci_dev *dev)
2320{ 2423{
2321 if (machine_is(powermac)) { 2424 if (machine_is(powermac)) {
2322 struct device_node *ofn = pci_device_to_OF_node(dev); 2425 struct device_node *ofn = pci_device_to_OF_node(dev);
@@ -2328,15 +2431,15 @@ static void ohci_pmac_off(struct pci_dev *dev)
2328 } 2431 }
2329} 2432}
2330#else 2433#else
2331#define ohci_pmac_on(dev) 2434static inline void pmac_ohci_on(struct pci_dev *dev) {}
2332#define ohci_pmac_off(dev) 2435static inline void pmac_ohci_off(struct pci_dev *dev) {}
2333#endif /* CONFIG_PPC_PMAC */ 2436#endif /* CONFIG_PPC_PMAC */
2334 2437
2335static int __devinit pci_probe(struct pci_dev *dev, 2438static int __devinit pci_probe(struct pci_dev *dev,
2336 const struct pci_device_id *ent) 2439 const struct pci_device_id *ent)
2337{ 2440{
2338 struct fw_ohci *ohci; 2441 struct fw_ohci *ohci;
2339 u32 bus_options, max_receive, link_speed, version; 2442 u32 bus_options, max_receive, link_speed, version, link_enh;
2340 u64 guid; 2443 u64 guid;
2341 int i, err, n_ir, n_it; 2444 int i, err, n_ir, n_it;
2342 size_t size; 2445 size_t size;
@@ -2349,7 +2452,7 @@ static int __devinit pci_probe(struct pci_dev *dev,
2349 2452
2350 fw_card_initialize(&ohci->card, &ohci_driver, &dev->dev); 2453 fw_card_initialize(&ohci->card, &ohci_driver, &dev->dev);
2351 2454
2352 ohci_pmac_on(dev); 2455 pmac_ohci_on(dev);
2353 2456
2354 err = pci_enable_device(dev); 2457 err = pci_enable_device(dev);
2355 if (err) { 2458 if (err) {
@@ -2389,6 +2492,23 @@ static int __devinit pci_probe(struct pci_dev *dev,
2389 if (param_quirks) 2492 if (param_quirks)
2390 ohci->quirks = param_quirks; 2493 ohci->quirks = param_quirks;
2391 2494
2495 /* TI OHCI-Lynx and compatible: set recommended configuration bits. */
2496 if (dev->vendor == PCI_VENDOR_ID_TI) {
2497 pci_read_config_dword(dev, PCI_CFG_TI_LinkEnh, &link_enh);
2498
2499 /* adjust latency of ATx FIFO: use 1.7 KB threshold */
2500 link_enh &= ~TI_LinkEnh_atx_thresh_mask;
2501 link_enh |= TI_LinkEnh_atx_thresh_1_7K;
2502
2503 /* use priority arbitration for asynchronous responses */
2504 link_enh |= TI_LinkEnh_enab_unfair;
2505
2506 /* required for aPhyEnhanceEnable to work */
2507 link_enh |= TI_LinkEnh_enab_accel;
2508
2509 pci_write_config_dword(dev, PCI_CFG_TI_LinkEnh, link_enh);
2510 }
2511
2392 ar_context_init(&ohci->ar_request_ctx, ohci, 2512 ar_context_init(&ohci->ar_request_ctx, ohci,
2393 OHCI1394_AsReqRcvContextControlSet); 2513 OHCI1394_AsReqRcvContextControlSet);
2394 2514
@@ -2466,7 +2586,7 @@ static int __devinit pci_probe(struct pci_dev *dev,
2466 pci_disable_device(dev); 2586 pci_disable_device(dev);
2467 fail_free: 2587 fail_free:
2468 kfree(&ohci->card); 2588 kfree(&ohci->card);
2469 ohci_pmac_off(dev); 2589 pmac_ohci_off(dev);
2470 fail: 2590 fail:
2471 if (err == -ENOMEM) 2591 if (err == -ENOMEM)
2472 fw_error("Out of memory\n"); 2592 fw_error("Out of memory\n");
@@ -2509,7 +2629,7 @@ static void pci_remove(struct pci_dev *dev)
2509 pci_release_region(dev, 0); 2629 pci_release_region(dev, 0);
2510 pci_disable_device(dev); 2630 pci_disable_device(dev);
2511 kfree(&ohci->card); 2631 kfree(&ohci->card);
2512 ohci_pmac_off(dev); 2632 pmac_ohci_off(dev);
2513 2633
2514 fw_notify("Removed fw-ohci device.\n"); 2634 fw_notify("Removed fw-ohci device.\n");
2515} 2635}
@@ -2530,7 +2650,7 @@ static int pci_suspend(struct pci_dev *dev, pm_message_t state)
2530 err = pci_set_power_state(dev, pci_choose_state(dev, state)); 2650 err = pci_set_power_state(dev, pci_choose_state(dev, state));
2531 if (err) 2651 if (err)
2532 fw_error("pci_set_power_state failed with %d\n", err); 2652 fw_error("pci_set_power_state failed with %d\n", err);
2533 ohci_pmac_off(dev); 2653 pmac_ohci_off(dev);
2534 2654
2535 return 0; 2655 return 0;
2536} 2656}
@@ -2540,7 +2660,7 @@ static int pci_resume(struct pci_dev *dev)
2540 struct fw_ohci *ohci = pci_get_drvdata(dev); 2660 struct fw_ohci *ohci = pci_get_drvdata(dev);
2541 int err; 2661 int err;
2542 2662
2543 ohci_pmac_on(dev); 2663 pmac_ohci_on(dev);
2544 pci_set_power_state(dev, PCI_D0); 2664 pci_set_power_state(dev, PCI_D0);
2545 pci_restore_state(dev); 2665 pci_restore_state(dev);
2546 err = pci_enable_device(dev); 2666 err = pci_enable_device(dev);
diff --git a/drivers/firewire/ohci.h b/drivers/firewire/ohci.h
index ba492d85c516..3bc9a5d744eb 100644
--- a/drivers/firewire/ohci.h
+++ b/drivers/firewire/ohci.h
@@ -67,7 +67,7 @@
67#define OHCI1394_PhyControl_ReadDone 0x80000000 67#define OHCI1394_PhyControl_ReadDone 0x80000000
68#define OHCI1394_PhyControl_ReadData(r) (((r) & 0x00ff0000) >> 16) 68#define OHCI1394_PhyControl_ReadData(r) (((r) & 0x00ff0000) >> 16)
69#define OHCI1394_PhyControl_Write(addr, data) (((addr) << 8) | (data) | 0x00004000) 69#define OHCI1394_PhyControl_Write(addr, data) (((addr) << 8) | (data) | 0x00004000)
70#define OHCI1394_PhyControl_WriteDone 0x00004000 70#define OHCI1394_PhyControl_WritePending 0x00004000
71#define OHCI1394_IsochronousCycleTimer 0x0F0 71#define OHCI1394_IsochronousCycleTimer 0x0F0
72#define OHCI1394_AsReqFilterHiSet 0x100 72#define OHCI1394_AsReqFilterHiSet 0x100
73#define OHCI1394_AsReqFilterHiClear 0x104 73#define OHCI1394_AsReqFilterHiClear 0x104
@@ -154,4 +154,12 @@
154 154
155#define OHCI1394_phy_tcode 0xe 155#define OHCI1394_phy_tcode 0xe
156 156
157/* TI extensions */
158
159#define PCI_CFG_TI_LinkEnh 0xf4
160#define TI_LinkEnh_enab_accel 0x00000002
161#define TI_LinkEnh_enab_unfair 0x00000080
162#define TI_LinkEnh_atx_thresh_mask 0x00003000
163#define TI_LinkEnh_atx_thresh_1_7K 0x00001000
164
157#endif /* _FIREWIRE_OHCI_H */ 165#endif /* _FIREWIRE_OHCI_H */
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index fee678f74a19..724038dab4ca 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -139,6 +139,13 @@ config GPIO_MAX732X
139 Board setup code must specify the model to use, and the start 139 Board setup code must specify the model to use, and the start
140 number for these GPIOs. 140 number for these GPIOs.
141 141
142config GPIO_MAX732X_IRQ
143 bool "Interrupt controller support for MAX732x"
144 depends on GPIO_MAX732X=y && GENERIC_HARDIRQS
145 help
146 Say yes here to enable the max732x to be used as an interrupt
147 controller. It requires the driver to be built in the kernel.
148
142config GPIO_PCA953X 149config GPIO_PCA953X
143 tristate "PCA953x, PCA955x, TCA64xx, and MAX7310 I/O ports" 150 tristate "PCA953x, PCA955x, TCA64xx, and MAX7310 I/O ports"
144 depends on I2C 151 depends on I2C
@@ -188,6 +195,13 @@ config GPIO_PCF857X
188 This driver provides an in-kernel interface to those GPIOs using 195 This driver provides an in-kernel interface to those GPIOs using
189 platform-neutral GPIO calls. 196 platform-neutral GPIO calls.
190 197
198config GPIO_TC35892
199 bool "TC35892 GPIOs"
200 depends on MFD_TC35892
201 help
202 This enables support for the GPIOs found on the TC35892
203 I/O Expander.
204
191config GPIO_TWL4030 205config GPIO_TWL4030
192 tristate "TWL4030, TWL5030, and TPS659x0 GPIOs" 206 tristate "TWL4030, TWL5030, and TPS659x0 GPIOs"
193 depends on TWL4030_CORE 207 depends on TWL4030_CORE
@@ -264,10 +278,10 @@ config GPIO_BT8XX
264 If unsure, say N. 278 If unsure, say N.
265 279
266config GPIO_LANGWELL 280config GPIO_LANGWELL
267 bool "Intel Moorestown Platform Langwell GPIO support" 281 bool "Intel Langwell/Penwell GPIO support"
268 depends on PCI 282 depends on PCI
269 help 283 help
270 Say Y here to support Intel Moorestown platform GPIO. 284 Say Y here to support Intel Langwell/Penwell GPIO.
271 285
272config GPIO_TIMBERDALE 286config GPIO_TIMBERDALE
273 bool "Support for timberdale GPIO IP" 287 bool "Support for timberdale GPIO IP"
@@ -275,6 +289,15 @@ config GPIO_TIMBERDALE
275 ---help--- 289 ---help---
276 Add support for the GPIO IP in the timberdale FPGA. 290 Add support for the GPIO IP in the timberdale FPGA.
277 291
292config GPIO_RDC321X
293 tristate "RDC R-321x GPIO support"
294 depends on PCI && GPIOLIB
295 select MFD_CORE
296 select MFD_RDC321X
297 help
298 Support for the RDC R321x SoC GPIOs over southbridge
299 PCI configuration space.
300
278comment "SPI GPIO expanders:" 301comment "SPI GPIO expanders:"
279 302
280config GPIO_MAX7301 303config GPIO_MAX7301
@@ -310,4 +333,14 @@ config GPIO_UCB1400
310 To compile this driver as a module, choose M here: the 333 To compile this driver as a module, choose M here: the
311 module will be called ucb1400_gpio. 334 module will be called ucb1400_gpio.
312 335
336comment "MODULbus GPIO expanders:"
337
338config GPIO_JANZ_TTL
339 tristate "Janz VMOD-TTL Digital IO Module"
340 depends on MFD_JANZ_CMODIO
341 help
342 This enables support for the Janz VMOD-TTL Digital IO module.
343 This driver provides support for driving the pins in output
344 mode only. Input mode is not supported.
345
313endif 346endif
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 10f3f8d958b1..51c3cdd41b5a 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o
16obj-$(CONFIG_GPIO_PCA953X) += pca953x.o 16obj-$(CONFIG_GPIO_PCA953X) += pca953x.o
17obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o 17obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o
18obj-$(CONFIG_GPIO_PL061) += pl061.o 18obj-$(CONFIG_GPIO_PL061) += pl061.o
19obj-$(CONFIG_GPIO_TC35892) += tc35892-gpio.o
19obj-$(CONFIG_GPIO_TIMBERDALE) += timbgpio.o 20obj-$(CONFIG_GPIO_TIMBERDALE) += timbgpio.o
20obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o 21obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o
21obj-$(CONFIG_GPIO_UCB1400) += ucb1400_gpio.o 22obj-$(CONFIG_GPIO_UCB1400) += ucb1400_gpio.o
@@ -27,4 +28,6 @@ obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o
27obj-$(CONFIG_GPIO_WM831X) += wm831x-gpio.o 28obj-$(CONFIG_GPIO_WM831X) += wm831x-gpio.o
28obj-$(CONFIG_GPIO_WM8350) += wm8350-gpiolib.o 29obj-$(CONFIG_GPIO_WM8350) += wm8350-gpiolib.o
29obj-$(CONFIG_GPIO_WM8994) += wm8994-gpio.o 30obj-$(CONFIG_GPIO_WM8994) += wm8994-gpio.o
30obj-$(CONFIG_GPIO_SCH) += sch_gpio.o \ No newline at end of file 31obj-$(CONFIG_GPIO_SCH) += sch_gpio.o
32obj-$(CONFIG_GPIO_RDC321X) += rdc321x-gpio.o
33obj-$(CONFIG_GPIO_JANZ_TTL) += janz-ttl.o
diff --git a/drivers/gpio/cs5535-gpio.c b/drivers/gpio/cs5535-gpio.c
index 0c3c498f2260..f73a1555e49d 100644
--- a/drivers/gpio/cs5535-gpio.c
+++ b/drivers/gpio/cs5535-gpio.c
@@ -197,7 +197,7 @@ static int chip_direction_output(struct gpio_chip *c, unsigned offset, int val)
197 return 0; 197 return 0;
198} 198}
199 199
200static char *cs5535_gpio_names[] = { 200static const char * const cs5535_gpio_names[] = {
201 "GPIO0", "GPIO1", "GPIO2", "GPIO3", 201 "GPIO0", "GPIO1", "GPIO2", "GPIO3",
202 "GPIO4", "GPIO5", "GPIO6", "GPIO7", 202 "GPIO4", "GPIO5", "GPIO6", "GPIO7",
203 "GPIO8", "GPIO9", "GPIO10", "GPIO11", 203 "GPIO8", "GPIO9", "GPIO10", "GPIO11",
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index cae1b8c5b08c..3ca36542e338 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -722,7 +722,7 @@ int gpio_export(unsigned gpio, bool direction_may_change)
722 unsigned long flags; 722 unsigned long flags;
723 struct gpio_desc *desc; 723 struct gpio_desc *desc;
724 int status = -EINVAL; 724 int status = -EINVAL;
725 char *ioname = NULL; 725 const char *ioname = NULL;
726 726
727 /* can't export until sysfs is available ... */ 727 /* can't export until sysfs is available ... */
728 if (!gpio_class.p) { 728 if (!gpio_class.p) {
@@ -753,7 +753,7 @@ int gpio_export(unsigned gpio, bool direction_may_change)
753 struct device *dev; 753 struct device *dev;
754 754
755 dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0), 755 dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0),
756 desc, ioname ? ioname : "gpio%d", gpio); 756 desc, ioname ? ioname : "gpio%u", gpio);
757 if (!IS_ERR(dev)) { 757 if (!IS_ERR(dev)) {
758 status = sysfs_create_group(&dev->kobj, 758 status = sysfs_create_group(&dev->kobj,
759 &gpio_attr_group); 759 &gpio_attr_group);
@@ -1106,7 +1106,7 @@ unlock:
1106fail: 1106fail:
1107 /* failures here can mean systems won't boot... */ 1107 /* failures here can mean systems won't boot... */
1108 if (status) 1108 if (status)
1109 pr_err("gpiochip_add: gpios %d..%d (%s) not registered\n", 1109 pr_err("gpiochip_add: gpios %d..%d (%s) failed to register\n",
1110 chip->base, chip->base + chip->ngpio - 1, 1110 chip->base, chip->base + chip->ngpio - 1,
1111 chip->label ? : "generic"); 1111 chip->label ? : "generic");
1112 return status; 1112 return status;
@@ -1447,6 +1447,49 @@ fail:
1447} 1447}
1448EXPORT_SYMBOL_GPL(gpio_direction_output); 1448EXPORT_SYMBOL_GPL(gpio_direction_output);
1449 1449
1450/**
1451 * gpio_set_debounce - sets @debounce time for a @gpio
1452 * @gpio: the gpio to set debounce time
1453 * @debounce: debounce time is microseconds
1454 */
1455int gpio_set_debounce(unsigned gpio, unsigned debounce)
1456{
1457 unsigned long flags;
1458 struct gpio_chip *chip;
1459 struct gpio_desc *desc = &gpio_desc[gpio];
1460 int status = -EINVAL;
1461
1462 spin_lock_irqsave(&gpio_lock, flags);
1463
1464 if (!gpio_is_valid(gpio))
1465 goto fail;
1466 chip = desc->chip;
1467 if (!chip || !chip->set || !chip->set_debounce)
1468 goto fail;
1469 gpio -= chip->base;
1470 if (gpio >= chip->ngpio)
1471 goto fail;
1472 status = gpio_ensure_requested(desc, gpio);
1473 if (status < 0)
1474 goto fail;
1475
1476 /* now we know the gpio is valid and chip won't vanish */
1477
1478 spin_unlock_irqrestore(&gpio_lock, flags);
1479
1480 might_sleep_if(extra_checks && chip->can_sleep);
1481
1482 return chip->set_debounce(chip, gpio, debounce);
1483
1484fail:
1485 spin_unlock_irqrestore(&gpio_lock, flags);
1486 if (status)
1487 pr_debug("%s: gpio-%d status %d\n",
1488 __func__, gpio, status);
1489
1490 return status;
1491}
1492EXPORT_SYMBOL_GPL(gpio_set_debounce);
1450 1493
1451/* I/O calls are only valid after configuration completed; the relevant 1494/* I/O calls are only valid after configuration completed; the relevant
1452 * "is this a valid GPIO" error checks should already have been done. 1495 * "is this a valid GPIO" error checks should already have been done.
diff --git a/drivers/gpio/it8761e_gpio.c b/drivers/gpio/it8761e_gpio.c
index 41a9388f2fde..48fc43c4bdd1 100644
--- a/drivers/gpio/it8761e_gpio.c
+++ b/drivers/gpio/it8761e_gpio.c
@@ -217,7 +217,10 @@ gpiochip_add_err:
217static void __exit it8761e_gpio_exit(void) 217static void __exit it8761e_gpio_exit(void)
218{ 218{
219 if (gpio_ba) { 219 if (gpio_ba) {
220 gpiochip_remove(&it8761e_gpio_chip); 220 int ret = gpiochip_remove(&it8761e_gpio_chip);
221
222 WARN(ret, "%s(): gpiochip_remove() failed, ret=%d\n",
223 __func__, ret);
221 224
222 release_region(gpio_ba, GPIO_IOSIZE); 225 release_region(gpio_ba, GPIO_IOSIZE);
223 gpio_ba = 0; 226 gpio_ba = 0;
diff --git a/drivers/gpio/janz-ttl.c b/drivers/gpio/janz-ttl.c
new file mode 100644
index 000000000000..813ac077e5d7
--- /dev/null
+++ b/drivers/gpio/janz-ttl.c
@@ -0,0 +1,258 @@
1/*
2 * Janz MODULbus VMOD-TTL GPIO Driver
3 *
4 * Copyright (c) 2010 Ira W. Snyder <iws@ovro.caltech.edu>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 */
11
12#include <linux/kernel.h>
13#include <linux/module.h>
14#include <linux/init.h>
15#include <linux/interrupt.h>
16#include <linux/delay.h>
17#include <linux/platform_device.h>
18#include <linux/io.h>
19#include <linux/gpio.h>
20#include <linux/slab.h>
21
22#include <linux/mfd/janz.h>
23
24#define DRV_NAME "janz-ttl"
25
26#define PORTA_DIRECTION 0x23
27#define PORTB_DIRECTION 0x2B
28#define PORTC_DIRECTION 0x06
29#define PORTA_IOCTL 0x24
30#define PORTB_IOCTL 0x2C
31#define PORTC_IOCTL 0x07
32
33#define MASTER_INT_CTL 0x00
34#define MASTER_CONF_CTL 0x01
35
36#define CONF_PAE (1 << 2)
37#define CONF_PBE (1 << 7)
38#define CONF_PCE (1 << 4)
39
40struct ttl_control_regs {
41 __be16 portc;
42 __be16 portb;
43 __be16 porta;
44 __be16 control;
45};
46
47struct ttl_module {
48 struct gpio_chip gpio;
49
50 /* base address of registers */
51 struct ttl_control_regs __iomem *regs;
52
53 u8 portc_shadow;
54 u8 portb_shadow;
55 u8 porta_shadow;
56
57 spinlock_t lock;
58};
59
60static int ttl_get_value(struct gpio_chip *gpio, unsigned offset)
61{
62 struct ttl_module *mod = dev_get_drvdata(gpio->dev);
63 u8 *shadow;
64 int ret;
65
66 if (offset < 8) {
67 shadow = &mod->porta_shadow;
68 } else if (offset < 16) {
69 shadow = &mod->portb_shadow;
70 offset -= 8;
71 } else {
72 shadow = &mod->portc_shadow;
73 offset -= 16;
74 }
75
76 spin_lock(&mod->lock);
77 ret = *shadow & (1 << offset);
78 spin_unlock(&mod->lock);
79 return ret;
80}
81
82static void ttl_set_value(struct gpio_chip *gpio, unsigned offset, int value)
83{
84 struct ttl_module *mod = dev_get_drvdata(gpio->dev);
85 void __iomem *port;
86 u8 *shadow;
87
88 if (offset < 8) {
89 port = &mod->regs->porta;
90 shadow = &mod->porta_shadow;
91 } else if (offset < 16) {
92 port = &mod->regs->portb;
93 shadow = &mod->portb_shadow;
94 offset -= 8;
95 } else {
96 port = &mod->regs->portc;
97 shadow = &mod->portc_shadow;
98 offset -= 16;
99 }
100
101 spin_lock(&mod->lock);
102 if (value)
103 *shadow |= (1 << offset);
104 else
105 *shadow &= ~(1 << offset);
106
107 iowrite16be(*shadow, port);
108 spin_unlock(&mod->lock);
109}
110
111static void __devinit ttl_write_reg(struct ttl_module *mod, u8 reg, u16 val)
112{
113 iowrite16be(reg, &mod->regs->control);
114 iowrite16be(val, &mod->regs->control);
115}
116
117static void __devinit ttl_setup_device(struct ttl_module *mod)
118{
119 /* reset the device to a known state */
120 iowrite16be(0x0000, &mod->regs->control);
121 iowrite16be(0x0001, &mod->regs->control);
122 iowrite16be(0x0000, &mod->regs->control);
123
124 /* put all ports in open-drain mode */
125 ttl_write_reg(mod, PORTA_IOCTL, 0x00ff);
126 ttl_write_reg(mod, PORTB_IOCTL, 0x00ff);
127 ttl_write_reg(mod, PORTC_IOCTL, 0x000f);
128
129 /* set all ports as outputs */
130 ttl_write_reg(mod, PORTA_DIRECTION, 0x0000);
131 ttl_write_reg(mod, PORTB_DIRECTION, 0x0000);
132 ttl_write_reg(mod, PORTC_DIRECTION, 0x0000);
133
134 /* set all ports to drive zeroes */
135 iowrite16be(0x0000, &mod->regs->porta);
136 iowrite16be(0x0000, &mod->regs->portb);
137 iowrite16be(0x0000, &mod->regs->portc);
138
139 /* enable all ports */
140 ttl_write_reg(mod, MASTER_CONF_CTL, CONF_PAE | CONF_PBE | CONF_PCE);
141}
142
143static int __devinit ttl_probe(struct platform_device *pdev)
144{
145 struct janz_platform_data *pdata;
146 struct device *dev = &pdev->dev;
147 struct ttl_module *mod;
148 struct gpio_chip *gpio;
149 struct resource *res;
150 int ret;
151
152 pdata = pdev->dev.platform_data;
153 if (!pdata) {
154 dev_err(dev, "no platform data\n");
155 ret = -ENXIO;
156 goto out_return;
157 }
158
159 mod = kzalloc(sizeof(*mod), GFP_KERNEL);
160 if (!mod) {
161 dev_err(dev, "unable to allocate private data\n");
162 ret = -ENOMEM;
163 goto out_return;
164 }
165
166 platform_set_drvdata(pdev, mod);
167 spin_lock_init(&mod->lock);
168
169 /* get access to the MODULbus registers for this module */
170 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
171 if (!res) {
172 dev_err(dev, "MODULbus registers not found\n");
173 ret = -ENODEV;
174 goto out_free_mod;
175 }
176
177 mod->regs = ioremap(res->start, resource_size(res));
178 if (!mod->regs) {
179 dev_err(dev, "MODULbus registers not ioremap\n");
180 ret = -ENOMEM;
181 goto out_free_mod;
182 }
183
184 ttl_setup_device(mod);
185
186 /* Initialize the GPIO data structures */
187 gpio = &mod->gpio;
188 gpio->dev = &pdev->dev;
189 gpio->label = pdev->name;
190 gpio->get = ttl_get_value;
191 gpio->set = ttl_set_value;
192 gpio->owner = THIS_MODULE;
193
194 /* request dynamic allocation */
195 gpio->base = -1;
196 gpio->ngpio = 20;
197
198 ret = gpiochip_add(gpio);
199 if (ret) {
200 dev_err(dev, "unable to add GPIO chip\n");
201 goto out_iounmap_regs;
202 }
203
204 dev_info(&pdev->dev, "module %d: registered GPIO device\n",
205 pdata->modno);
206 return 0;
207
208out_iounmap_regs:
209 iounmap(mod->regs);
210out_free_mod:
211 kfree(mod);
212out_return:
213 return ret;
214}
215
216static int __devexit ttl_remove(struct platform_device *pdev)
217{
218 struct ttl_module *mod = platform_get_drvdata(pdev);
219 struct device *dev = &pdev->dev;
220 int ret;
221
222 ret = gpiochip_remove(&mod->gpio);
223 if (ret) {
224 dev_err(dev, "unable to remove GPIO chip\n");
225 return ret;
226 }
227
228 iounmap(mod->regs);
229 kfree(mod);
230 return 0;
231}
232
233static struct platform_driver ttl_driver = {
234 .driver = {
235 .name = DRV_NAME,
236 .owner = THIS_MODULE,
237 },
238 .probe = ttl_probe,
239 .remove = __devexit_p(ttl_remove),
240};
241
242static int __init ttl_init(void)
243{
244 return platform_driver_register(&ttl_driver);
245}
246
247static void __exit ttl_exit(void)
248{
249 platform_driver_unregister(&ttl_driver);
250}
251
252MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>");
253MODULE_DESCRIPTION("Janz MODULbus VMOD-TTL Driver");
254MODULE_LICENSE("GPL");
255MODULE_ALIAS("platform:janz-ttl");
256
257module_init(ttl_init);
258module_exit(ttl_exit);
diff --git a/drivers/gpio/langwell_gpio.c b/drivers/gpio/langwell_gpio.c
index 00c3a14127af..8383a8d7f994 100644
--- a/drivers/gpio/langwell_gpio.c
+++ b/drivers/gpio/langwell_gpio.c
@@ -17,6 +17,7 @@
17 17
18/* Supports: 18/* Supports:
19 * Moorestown platform Langwell chip. 19 * Moorestown platform Langwell chip.
20 * Medfield platform Penwell chip.
20 */ 21 */
21 22
22#include <linux/module.h> 23#include <linux/module.h>
@@ -31,44 +32,65 @@
31#include <linux/gpio.h> 32#include <linux/gpio.h>
32#include <linux/slab.h> 33#include <linux/slab.h>
33 34
34struct lnw_gpio_register { 35/*
35 u32 GPLR[2]; 36 * Langwell chip has 64 pins and thus there are 2 32bit registers to control
36 u32 GPDR[2]; 37 * each feature, while Penwell chip has 96 pins for each block, and need 3 32bit
37 u32 GPSR[2]; 38 * registers to control them, so we only define the order here instead of a
38 u32 GPCR[2]; 39 * structure, to get a bit offset for a pin (use GPDR as an example):
39 u32 GRER[2]; 40 *
40 u32 GFER[2]; 41 * nreg = ngpio / 32;
41 u32 GEDR[2]; 42 * reg = offset / 32;
43 * bit = offset % 32;
44 * reg_addr = reg_base + GPDR * nreg * 4 + reg * 4;
45 *
46 * so the bit of reg_addr is to control pin offset's GPDR feature
47*/
48
49enum GPIO_REG {
50 GPLR = 0, /* pin level read-only */
51 GPDR, /* pin direction */
52 GPSR, /* pin set */
53 GPCR, /* pin clear */
54 GRER, /* rising edge detect */
55 GFER, /* falling edge detect */
56 GEDR, /* edge detect result */
42}; 57};
43 58
44struct lnw_gpio { 59struct lnw_gpio {
45 struct gpio_chip chip; 60 struct gpio_chip chip;
46 struct lnw_gpio_register *reg_base; 61 void *reg_base;
47 spinlock_t lock; 62 spinlock_t lock;
48 unsigned irq_base; 63 unsigned irq_base;
49}; 64};
50 65
51static int lnw_gpio_get(struct gpio_chip *chip, unsigned offset) 66static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset,
67 enum GPIO_REG reg_type)
52{ 68{
53 struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); 69 struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip);
70 unsigned nreg = chip->ngpio / 32;
54 u8 reg = offset / 32; 71 u8 reg = offset / 32;
55 void __iomem *gplr; 72 void __iomem *ptr;
73
74 ptr = (void __iomem *)(lnw->reg_base + reg_type * nreg * 4 + reg * 4);
75 return ptr;
76}
77
78static int lnw_gpio_get(struct gpio_chip *chip, unsigned offset)
79{
80 void __iomem *gplr = gpio_reg(chip, offset, GPLR);
56 81
57 gplr = (void __iomem *)(&lnw->reg_base->GPLR[reg]);
58 return readl(gplr) & BIT(offset % 32); 82 return readl(gplr) & BIT(offset % 32);
59} 83}
60 84
61static void lnw_gpio_set(struct gpio_chip *chip, unsigned offset, int value) 85static void lnw_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
62{ 86{
63 struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip);
64 u8 reg = offset / 32;
65 void __iomem *gpsr, *gpcr; 87 void __iomem *gpsr, *gpcr;
66 88
67 if (value) { 89 if (value) {
68 gpsr = (void __iomem *)(&lnw->reg_base->GPSR[reg]); 90 gpsr = gpio_reg(chip, offset, GPSR);
69 writel(BIT(offset % 32), gpsr); 91 writel(BIT(offset % 32), gpsr);
70 } else { 92 } else {
71 gpcr = (void __iomem *)(&lnw->reg_base->GPCR[reg]); 93 gpcr = gpio_reg(chip, offset, GPCR);
72 writel(BIT(offset % 32), gpcr); 94 writel(BIT(offset % 32), gpcr);
73 } 95 }
74} 96}
@@ -76,12 +98,10 @@ static void lnw_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
76static int lnw_gpio_direction_input(struct gpio_chip *chip, unsigned offset) 98static int lnw_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
77{ 99{
78 struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); 100 struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip);
79 u8 reg = offset / 32; 101 void __iomem *gpdr = gpio_reg(chip, offset, GPDR);
80 u32 value; 102 u32 value;
81 unsigned long flags; 103 unsigned long flags;
82 void __iomem *gpdr;
83 104
84 gpdr = (void __iomem *)(&lnw->reg_base->GPDR[reg]);
85 spin_lock_irqsave(&lnw->lock, flags); 105 spin_lock_irqsave(&lnw->lock, flags);
86 value = readl(gpdr); 106 value = readl(gpdr);
87 value &= ~BIT(offset % 32); 107 value &= ~BIT(offset % 32);
@@ -94,12 +114,10 @@ static int lnw_gpio_direction_output(struct gpio_chip *chip,
94 unsigned offset, int value) 114 unsigned offset, int value)
95{ 115{
96 struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); 116 struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip);
97 u8 reg = offset / 32; 117 void __iomem *gpdr = gpio_reg(chip, offset, GPDR);
98 unsigned long flags; 118 unsigned long flags;
99 void __iomem *gpdr;
100 119
101 lnw_gpio_set(chip, offset, value); 120 lnw_gpio_set(chip, offset, value);
102 gpdr = (void __iomem *)(&lnw->reg_base->GPDR[reg]);
103 spin_lock_irqsave(&lnw->lock, flags); 121 spin_lock_irqsave(&lnw->lock, flags);
104 value = readl(gpdr); 122 value = readl(gpdr);
105 value |= BIT(offset % 32);; 123 value |= BIT(offset % 32);;
@@ -118,11 +136,10 @@ static int lnw_irq_type(unsigned irq, unsigned type)
118{ 136{
119 struct lnw_gpio *lnw = get_irq_chip_data(irq); 137 struct lnw_gpio *lnw = get_irq_chip_data(irq);
120 u32 gpio = irq - lnw->irq_base; 138 u32 gpio = irq - lnw->irq_base;
121 u8 reg = gpio / 32;
122 unsigned long flags; 139 unsigned long flags;
123 u32 value; 140 u32 value;
124 void __iomem *grer = (void __iomem *)(&lnw->reg_base->GRER[reg]); 141 void __iomem *grer = gpio_reg(&lnw->chip, gpio, GRER);
125 void __iomem *gfer = (void __iomem *)(&lnw->reg_base->GFER[reg]); 142 void __iomem *gfer = gpio_reg(&lnw->chip, gpio, GFER);
126 143
127 if (gpio >= lnw->chip.ngpio) 144 if (gpio >= lnw->chip.ngpio)
128 return -EINVAL; 145 return -EINVAL;
@@ -158,8 +175,10 @@ static struct irq_chip lnw_irqchip = {
158 .set_type = lnw_irq_type, 175 .set_type = lnw_irq_type,
159}; 176};
160 177
161static struct pci_device_id lnw_gpio_ids[] = { 178static DEFINE_PCI_DEVICE_TABLE(lnw_gpio_ids) = { /* pin number */
162 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080f) }, 179 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080f), .driver_data = 64 },
180 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081f), .driver_data = 96 },
181 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081a), .driver_data = 96 },
163 { 0, } 182 { 0, }
164}; 183};
165MODULE_DEVICE_TABLE(pci, lnw_gpio_ids); 184MODULE_DEVICE_TABLE(pci, lnw_gpio_ids);
@@ -167,17 +186,17 @@ MODULE_DEVICE_TABLE(pci, lnw_gpio_ids);
167static void lnw_irq_handler(unsigned irq, struct irq_desc *desc) 186static void lnw_irq_handler(unsigned irq, struct irq_desc *desc)
168{ 187{
169 struct lnw_gpio *lnw = (struct lnw_gpio *)get_irq_data(irq); 188 struct lnw_gpio *lnw = (struct lnw_gpio *)get_irq_data(irq);
170 u32 reg, gpio; 189 u32 base, gpio;
171 void __iomem *gedr; 190 void __iomem *gedr;
172 u32 gedr_v; 191 u32 gedr_v;
173 192
174 /* check GPIO controller to check which pin triggered the interrupt */ 193 /* check GPIO controller to check which pin triggered the interrupt */
175 for (reg = 0; reg < lnw->chip.ngpio / 32; reg++) { 194 for (base = 0; base < lnw->chip.ngpio; base += 32) {
176 gedr = (void __iomem *)(&lnw->reg_base->GEDR[reg]); 195 gedr = gpio_reg(&lnw->chip, base, GEDR);
177 gedr_v = readl(gedr); 196 gedr_v = readl(gedr);
178 if (!gedr_v) 197 if (!gedr_v)
179 continue; 198 continue;
180 for (gpio = reg*32; gpio < reg*32+32; gpio++) 199 for (gpio = base; gpio < base + 32; gpio++)
181 if (gedr_v & BIT(gpio % 32)) { 200 if (gedr_v & BIT(gpio % 32)) {
182 pr_debug("pin %d triggered\n", gpio); 201 pr_debug("pin %d triggered\n", gpio);
183 generic_handle_irq(lnw->irq_base + gpio); 202 generic_handle_irq(lnw->irq_base + gpio);
@@ -245,7 +264,7 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev,
245 lnw->chip.set = lnw_gpio_set; 264 lnw->chip.set = lnw_gpio_set;
246 lnw->chip.to_irq = lnw_gpio_to_irq; 265 lnw->chip.to_irq = lnw_gpio_to_irq;
247 lnw->chip.base = gpio_base; 266 lnw->chip.base = gpio_base;
248 lnw->chip.ngpio = 64; 267 lnw->chip.ngpio = id->driver_data;
249 lnw->chip.can_sleep = 0; 268 lnw->chip.can_sleep = 0;
250 pci_set_drvdata(pdev, lnw); 269 pci_set_drvdata(pdev, lnw);
251 retval = gpiochip_add(&lnw->chip); 270 retval = gpiochip_add(&lnw->chip);
diff --git a/drivers/gpio/max732x.c b/drivers/gpio/max732x.c
index f7868243af89..9cad60f9e962 100644
--- a/drivers/gpio/max732x.c
+++ b/drivers/gpio/max732x.c
@@ -17,7 +17,8 @@
17#include <linux/slab.h> 17#include <linux/slab.h>
18#include <linux/string.h> 18#include <linux/string.h>
19#include <linux/gpio.h> 19#include <linux/gpio.h>
20 20#include <linux/interrupt.h>
21#include <linux/irq.h>
21#include <linux/i2c.h> 22#include <linux/i2c.h>
22#include <linux/i2c/max732x.h> 23#include <linux/i2c/max732x.h>
23 24
@@ -31,7 +32,8 @@
31 * - Open Drain I/O 32 * - Open Drain I/O
32 * 33 *
33 * designated by 'O', 'I' and 'P' individually according to MAXIM's 34 * designated by 'O', 'I' and 'P' individually according to MAXIM's
34 * datasheets. 35 * datasheets. 'I' and 'P' ports are interrupt capables, some with
36 * a dedicated interrupt mask.
35 * 37 *
36 * There are two groups of I/O ports, each group usually includes 38 * There are two groups of I/O ports, each group usually includes
37 * up to 8 I/O ports, and is accessed by a specific I2C address: 39 * up to 8 I/O ports, and is accessed by a specific I2C address:
@@ -44,7 +46,8 @@
44 * 46 *
45 * Within each group of ports, there are five known combinations of 47 * Within each group of ports, there are five known combinations of
46 * I/O ports: 4I4O, 4P4O, 8I, 8P, 8O, see the definitions below for 48 * I/O ports: 4I4O, 4P4O, 8I, 8P, 8O, see the definitions below for
47 * the detailed organization of these ports. 49 * the detailed organization of these ports. Only Goup A is interrupt
50 * capable.
48 * 51 *
49 * GPIO numbers start from 'gpio_base + 0' to 'gpio_base + 8/16', 52 * GPIO numbers start from 'gpio_base + 0' to 'gpio_base + 8/16',
50 * and GPIOs from GROUP_A are numbered before those from GROUP_B 53 * and GPIOs from GROUP_A are numbered before those from GROUP_B
@@ -68,16 +71,47 @@
68#define GROUP_A(x) ((x) & 0xffff) /* I2C Addr: 0b'110xxxx */ 71#define GROUP_A(x) ((x) & 0xffff) /* I2C Addr: 0b'110xxxx */
69#define GROUP_B(x) ((x) << 16) /* I2C Addr: 0b'101xxxx */ 72#define GROUP_B(x) ((x) << 16) /* I2C Addr: 0b'101xxxx */
70 73
74#define INT_NONE 0x0 /* No interrupt capability */
75#define INT_NO_MASK 0x1 /* Has interrupts, no mask */
76#define INT_INDEP_MASK 0x2 /* Has interrupts, independent mask */
77#define INT_MERGED_MASK 0x3 /* Has interrupts, merged mask */
78
79#define INT_CAPS(x) (((uint64_t)(x)) << 32)
80
81enum {
82 MAX7319,
83 MAX7320,
84 MAX7321,
85 MAX7322,
86 MAX7323,
87 MAX7324,
88 MAX7325,
89 MAX7326,
90 MAX7327,
91};
92
93static uint64_t max732x_features[] = {
94 [MAX7319] = GROUP_A(IO_8I) | INT_CAPS(INT_MERGED_MASK),
95 [MAX7320] = GROUP_B(IO_8O),
96 [MAX7321] = GROUP_A(IO_8P) | INT_CAPS(INT_NO_MASK),
97 [MAX7322] = GROUP_A(IO_4I4O) | INT_CAPS(INT_MERGED_MASK),
98 [MAX7323] = GROUP_A(IO_4P4O) | INT_CAPS(INT_INDEP_MASK),
99 [MAX7324] = GROUP_A(IO_8I) | GROUP_B(IO_8O) | INT_CAPS(INT_MERGED_MASK),
100 [MAX7325] = GROUP_A(IO_8P) | GROUP_B(IO_8O) | INT_CAPS(INT_NO_MASK),
101 [MAX7326] = GROUP_A(IO_4I4O) | GROUP_B(IO_8O) | INT_CAPS(INT_MERGED_MASK),
102 [MAX7327] = GROUP_A(IO_4P4O) | GROUP_B(IO_8O) | INT_CAPS(INT_NO_MASK),
103};
104
71static const struct i2c_device_id max732x_id[] = { 105static const struct i2c_device_id max732x_id[] = {
72 { "max7319", GROUP_A(IO_8I) }, 106 { "max7319", MAX7319 },
73 { "max7320", GROUP_B(IO_8O) }, 107 { "max7320", MAX7320 },
74 { "max7321", GROUP_A(IO_8P) }, 108 { "max7321", MAX7321 },
75 { "max7322", GROUP_A(IO_4I4O) }, 109 { "max7322", MAX7322 },
76 { "max7323", GROUP_A(IO_4P4O) }, 110 { "max7323", MAX7323 },
77 { "max7324", GROUP_A(IO_8I) | GROUP_B(IO_8O) }, 111 { "max7324", MAX7324 },
78 { "max7325", GROUP_A(IO_8P) | GROUP_B(IO_8O) }, 112 { "max7325", MAX7325 },
79 { "max7326", GROUP_A(IO_4I4O) | GROUP_B(IO_8O) }, 113 { "max7326", MAX7326 },
80 { "max7327", GROUP_A(IO_4P4O) | GROUP_B(IO_8O) }, 114 { "max7327", MAX7327 },
81 { }, 115 { },
82}; 116};
83MODULE_DEVICE_TABLE(i2c, max732x_id); 117MODULE_DEVICE_TABLE(i2c, max732x_id);
@@ -96,9 +130,19 @@ struct max732x_chip {
96 130
97 struct mutex lock; 131 struct mutex lock;
98 uint8_t reg_out[2]; 132 uint8_t reg_out[2];
133
134#ifdef CONFIG_GPIO_MAX732X_IRQ
135 struct mutex irq_lock;
136 int irq_base;
137 uint8_t irq_mask;
138 uint8_t irq_mask_cur;
139 uint8_t irq_trig_raise;
140 uint8_t irq_trig_fall;
141 uint8_t irq_features;
142#endif
99}; 143};
100 144
101static int max732x_write(struct max732x_chip *chip, int group_a, uint8_t val) 145static int max732x_writeb(struct max732x_chip *chip, int group_a, uint8_t val)
102{ 146{
103 struct i2c_client *client; 147 struct i2c_client *client;
104 int ret; 148 int ret;
@@ -113,7 +157,7 @@ static int max732x_write(struct max732x_chip *chip, int group_a, uint8_t val)
113 return 0; 157 return 0;
114} 158}
115 159
116static int max732x_read(struct max732x_chip *chip, int group_a, uint8_t *val) 160static int max732x_readb(struct max732x_chip *chip, int group_a, uint8_t *val)
117{ 161{
118 struct i2c_client *client; 162 struct i2c_client *client;
119 int ret; 163 int ret;
@@ -142,7 +186,7 @@ static int max732x_gpio_get_value(struct gpio_chip *gc, unsigned off)
142 186
143 chip = container_of(gc, struct max732x_chip, gpio_chip); 187 chip = container_of(gc, struct max732x_chip, gpio_chip);
144 188
145 ret = max732x_read(chip, is_group_a(chip, off), &reg_val); 189 ret = max732x_readb(chip, is_group_a(chip, off), &reg_val);
146 if (ret < 0) 190 if (ret < 0)
147 return 0; 191 return 0;
148 192
@@ -162,7 +206,7 @@ static void max732x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
162 reg_out = (off > 7) ? chip->reg_out[1] : chip->reg_out[0]; 206 reg_out = (off > 7) ? chip->reg_out[1] : chip->reg_out[0];
163 reg_out = (val) ? reg_out | mask : reg_out & ~mask; 207 reg_out = (val) ? reg_out | mask : reg_out & ~mask;
164 208
165 ret = max732x_write(chip, is_group_a(chip, off), reg_out); 209 ret = max732x_writeb(chip, is_group_a(chip, off), reg_out);
166 if (ret < 0) 210 if (ret < 0)
167 goto out; 211 goto out;
168 212
@@ -188,6 +232,13 @@ static int max732x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
188 return -EACCES; 232 return -EACCES;
189 } 233 }
190 234
235 /*
236 * Open-drain pins must be set to high impedance (which is
237 * equivalent to output-high) to be turned into an input.
238 */
239 if ((mask & chip->dir_output))
240 max732x_gpio_set_value(gc, off, 1);
241
191 return 0; 242 return 0;
192} 243}
193 244
@@ -209,12 +260,278 @@ static int max732x_gpio_direction_output(struct gpio_chip *gc,
209 return 0; 260 return 0;
210} 261}
211 262
263#ifdef CONFIG_GPIO_MAX732X_IRQ
264static int max732x_writew(struct max732x_chip *chip, uint16_t val)
265{
266 int ret;
267
268 val = cpu_to_le16(val);
269
270 ret = i2c_master_send(chip->client_group_a, (char *)&val, 2);
271 if (ret < 0) {
272 dev_err(&chip->client_group_a->dev, "failed writing\n");
273 return ret;
274 }
275
276 return 0;
277}
278
279static int max732x_readw(struct max732x_chip *chip, uint16_t *val)
280{
281 int ret;
282
283 ret = i2c_master_recv(chip->client_group_a, (char *)val, 2);
284 if (ret < 0) {
285 dev_err(&chip->client_group_a->dev, "failed reading\n");
286 return ret;
287 }
288
289 *val = le16_to_cpu(*val);
290 return 0;
291}
292
293static void max732x_irq_update_mask(struct max732x_chip *chip)
294{
295 uint16_t msg;
296
297 if (chip->irq_mask == chip->irq_mask_cur)
298 return;
299
300 chip->irq_mask = chip->irq_mask_cur;
301
302 if (chip->irq_features == INT_NO_MASK)
303 return;
304
305 mutex_lock(&chip->lock);
306
307 switch (chip->irq_features) {
308 case INT_INDEP_MASK:
309 msg = (chip->irq_mask << 8) | chip->reg_out[0];
310 max732x_writew(chip, msg);
311 break;
312
313 case INT_MERGED_MASK:
314 msg = chip->irq_mask | chip->reg_out[0];
315 max732x_writeb(chip, 1, (uint8_t)msg);
316 break;
317 }
318
319 mutex_unlock(&chip->lock);
320}
321
322static int max732x_gpio_to_irq(struct gpio_chip *gc, unsigned off)
323{
324 struct max732x_chip *chip;
325
326 chip = container_of(gc, struct max732x_chip, gpio_chip);
327 return chip->irq_base + off;
328}
329
330static void max732x_irq_mask(unsigned int irq)
331{
332 struct max732x_chip *chip = get_irq_chip_data(irq);
333
334 chip->irq_mask_cur &= ~(1 << (irq - chip->irq_base));
335}
336
337static void max732x_irq_unmask(unsigned int irq)
338{
339 struct max732x_chip *chip = get_irq_chip_data(irq);
340
341 chip->irq_mask_cur |= 1 << (irq - chip->irq_base);
342}
343
344static void max732x_irq_bus_lock(unsigned int irq)
345{
346 struct max732x_chip *chip = get_irq_chip_data(irq);
347
348 mutex_lock(&chip->irq_lock);
349 chip->irq_mask_cur = chip->irq_mask;
350}
351
352static void max732x_irq_bus_sync_unlock(unsigned int irq)
353{
354 struct max732x_chip *chip = get_irq_chip_data(irq);
355
356 max732x_irq_update_mask(chip);
357 mutex_unlock(&chip->irq_lock);
358}
359
360static int max732x_irq_set_type(unsigned int irq, unsigned int type)
361{
362 struct max732x_chip *chip = get_irq_chip_data(irq);
363 uint16_t off = irq - chip->irq_base;
364 uint16_t mask = 1 << off;
365
366 if (!(mask & chip->dir_input)) {
367 dev_dbg(&chip->client->dev, "%s port %d is output only\n",
368 chip->client->name, off);
369 return -EACCES;
370 }
371
372 if (!(type & IRQ_TYPE_EDGE_BOTH)) {
373 dev_err(&chip->client->dev, "irq %d: unsupported type %d\n",
374 irq, type);
375 return -EINVAL;
376 }
377
378 if (type & IRQ_TYPE_EDGE_FALLING)
379 chip->irq_trig_fall |= mask;
380 else
381 chip->irq_trig_fall &= ~mask;
382
383 if (type & IRQ_TYPE_EDGE_RISING)
384 chip->irq_trig_raise |= mask;
385 else
386 chip->irq_trig_raise &= ~mask;
387
388 return max732x_gpio_direction_input(&chip->gpio_chip, off);
389}
390
391static struct irq_chip max732x_irq_chip = {
392 .name = "max732x",
393 .mask = max732x_irq_mask,
394 .unmask = max732x_irq_unmask,
395 .bus_lock = max732x_irq_bus_lock,
396 .bus_sync_unlock = max732x_irq_bus_sync_unlock,
397 .set_type = max732x_irq_set_type,
398};
399
400static uint8_t max732x_irq_pending(struct max732x_chip *chip)
401{
402 uint8_t cur_stat;
403 uint8_t old_stat;
404 uint8_t trigger;
405 uint8_t pending;
406 uint16_t status;
407 int ret;
408
409 ret = max732x_readw(chip, &status);
410 if (ret)
411 return 0;
412
413 trigger = status >> 8;
414 trigger &= chip->irq_mask;
415
416 if (!trigger)
417 return 0;
418
419 cur_stat = status & 0xFF;
420 cur_stat &= chip->irq_mask;
421
422 old_stat = cur_stat ^ trigger;
423
424 pending = (old_stat & chip->irq_trig_fall) |
425 (cur_stat & chip->irq_trig_raise);
426 pending &= trigger;
427
428 return pending;
429}
430
431static irqreturn_t max732x_irq_handler(int irq, void *devid)
432{
433 struct max732x_chip *chip = devid;
434 uint8_t pending;
435 uint8_t level;
436
437 pending = max732x_irq_pending(chip);
438
439 if (!pending)
440 return IRQ_HANDLED;
441
442 do {
443 level = __ffs(pending);
444 handle_nested_irq(level + chip->irq_base);
445
446 pending &= ~(1 << level);
447 } while (pending);
448
449 return IRQ_HANDLED;
450}
451
452static int max732x_irq_setup(struct max732x_chip *chip,
453 const struct i2c_device_id *id)
454{
455 struct i2c_client *client = chip->client;
456 struct max732x_platform_data *pdata = client->dev.platform_data;
457 int has_irq = max732x_features[id->driver_data] >> 32;
458 int ret;
459
460 if (pdata->irq_base && has_irq != INT_NONE) {
461 int lvl;
462
463 chip->irq_base = pdata->irq_base;
464 chip->irq_features = has_irq;
465 mutex_init(&chip->irq_lock);
466
467 for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) {
468 int irq = lvl + chip->irq_base;
469
470 if (!(chip->dir_input & (1 << lvl)))
471 continue;
472
473 set_irq_chip_data(irq, chip);
474 set_irq_chip_and_handler(irq, &max732x_irq_chip,
475 handle_edge_irq);
476 set_irq_nested_thread(irq, 1);
477#ifdef CONFIG_ARM
478 set_irq_flags(irq, IRQF_VALID);
479#else
480 set_irq_noprobe(irq);
481#endif
482 }
483
484 ret = request_threaded_irq(client->irq,
485 NULL,
486 max732x_irq_handler,
487 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
488 dev_name(&client->dev), chip);
489 if (ret) {
490 dev_err(&client->dev, "failed to request irq %d\n",
491 client->irq);
492 goto out_failed;
493 }
494
495 chip->gpio_chip.to_irq = max732x_gpio_to_irq;
496 }
497
498 return 0;
499
500out_failed:
501 chip->irq_base = 0;
502 return ret;
503}
504
505static void max732x_irq_teardown(struct max732x_chip *chip)
506{
507 if (chip->irq_base)
508 free_irq(chip->client->irq, chip);
509}
510#else /* CONFIG_GPIO_MAX732X_IRQ */
511static int max732x_irq_setup(struct max732x_chip *chip,
512 const struct i2c_device_id *id)
513{
514 struct i2c_client *client = chip->client;
515 struct max732x_platform_data *pdata = client->dev.platform_data;
516 int has_irq = max732x_features[id->driver_data] >> 32;
517
518 if (pdata->irq_base && has_irq != INT_NONE)
519 dev_warn(&client->dev, "interrupt support not compiled in\n");
520
521 return 0;
522}
523
524static void max732x_irq_teardown(struct max732x_chip *chip)
525{
526}
527#endif
528
212static int __devinit max732x_setup_gpio(struct max732x_chip *chip, 529static int __devinit max732x_setup_gpio(struct max732x_chip *chip,
213 const struct i2c_device_id *id, 530 const struct i2c_device_id *id,
214 unsigned gpio_start) 531 unsigned gpio_start)
215{ 532{
216 struct gpio_chip *gc = &chip->gpio_chip; 533 struct gpio_chip *gc = &chip->gpio_chip;
217 uint32_t id_data = id->driver_data; 534 uint32_t id_data = (uint32_t)max732x_features[id->driver_data];
218 int i, port = 0; 535 int i, port = 0;
219 536
220 for (i = 0; i < 16; i++, id_data >>= 2) { 537 for (i = 0; i < 16; i++, id_data >>= 2) {
@@ -285,14 +602,14 @@ static int __devinit max732x_probe(struct i2c_client *client,
285 switch (client->addr & 0x70) { 602 switch (client->addr & 0x70) {
286 case 0x60: 603 case 0x60:
287 chip->client_group_a = client; 604 chip->client_group_a = client;
288 if (nr_port > 7) { 605 if (nr_port > 8) {
289 c = i2c_new_dummy(client->adapter, addr_b); 606 c = i2c_new_dummy(client->adapter, addr_b);
290 chip->client_group_b = chip->client_dummy = c; 607 chip->client_group_b = chip->client_dummy = c;
291 } 608 }
292 break; 609 break;
293 case 0x50: 610 case 0x50:
294 chip->client_group_b = client; 611 chip->client_group_b = client;
295 if (nr_port > 7) { 612 if (nr_port > 8) {
296 c = i2c_new_dummy(client->adapter, addr_a); 613 c = i2c_new_dummy(client->adapter, addr_a);
297 chip->client_group_a = chip->client_dummy = c; 614 chip->client_group_a = chip->client_dummy = c;
298 } 615 }
@@ -306,9 +623,13 @@ static int __devinit max732x_probe(struct i2c_client *client,
306 623
307 mutex_init(&chip->lock); 624 mutex_init(&chip->lock);
308 625
309 max732x_read(chip, is_group_a(chip, 0), &chip->reg_out[0]); 626 max732x_readb(chip, is_group_a(chip, 0), &chip->reg_out[0]);
310 if (nr_port > 7) 627 if (nr_port > 8)
311 max732x_read(chip, is_group_a(chip, 8), &chip->reg_out[1]); 628 max732x_readb(chip, is_group_a(chip, 8), &chip->reg_out[1]);
629
630 ret = max732x_irq_setup(chip, id);
631 if (ret)
632 goto out_failed;
312 633
313 ret = gpiochip_add(&chip->gpio_chip); 634 ret = gpiochip_add(&chip->gpio_chip);
314 if (ret) 635 if (ret)
@@ -325,6 +646,7 @@ static int __devinit max732x_probe(struct i2c_client *client,
325 return 0; 646 return 0;
326 647
327out_failed: 648out_failed:
649 max732x_irq_teardown(chip);
328 kfree(chip); 650 kfree(chip);
329 return ret; 651 return ret;
330} 652}
@@ -352,6 +674,8 @@ static int __devexit max732x_remove(struct i2c_client *client)
352 return ret; 674 return ret;
353 } 675 }
354 676
677 max732x_irq_teardown(chip);
678
355 /* unregister any dummy i2c_client */ 679 /* unregister any dummy i2c_client */
356 if (chip->client_dummy) 680 if (chip->client_dummy)
357 i2c_unregister_device(chip->client_dummy); 681 i2c_unregister_device(chip->client_dummy);
diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c
index f156ab3bb6ed..a2b12aa1f2b9 100644
--- a/drivers/gpio/pca953x.c
+++ b/drivers/gpio/pca953x.c
@@ -73,7 +73,7 @@ struct pca953x_chip {
73 struct i2c_client *client; 73 struct i2c_client *client;
74 struct pca953x_platform_data *dyn_pdata; 74 struct pca953x_platform_data *dyn_pdata;
75 struct gpio_chip gpio_chip; 75 struct gpio_chip gpio_chip;
76 char **names; 76 const char *const *names;
77}; 77};
78 78
79static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val) 79static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val)
diff --git a/drivers/gpio/pl061.c b/drivers/gpio/pl061.c
index 105701a1f05b..ee568c8fcbd0 100644
--- a/drivers/gpio/pl061.c
+++ b/drivers/gpio/pl061.c
@@ -164,7 +164,7 @@ static int pl061_irq_type(unsigned irq, unsigned trigger)
164 unsigned long flags; 164 unsigned long flags;
165 u8 gpiois, gpioibe, gpioiev; 165 u8 gpiois, gpioibe, gpioiev;
166 166
167 if (offset < 0 || offset > PL061_GPIO_NR) 167 if (offset < 0 || offset >= PL061_GPIO_NR)
168 return -EINVAL; 168 return -EINVAL;
169 169
170 spin_lock_irqsave(&chip->irq_lock, flags); 170 spin_lock_irqsave(&chip->irq_lock, flags);
diff --git a/drivers/gpio/rdc321x-gpio.c b/drivers/gpio/rdc321x-gpio.c
new file mode 100644
index 000000000000..2762698e0204
--- /dev/null
+++ b/drivers/gpio/rdc321x-gpio.c
@@ -0,0 +1,246 @@
1/*
2 * RDC321x GPIO driver
3 *
4 * Copyright (C) 2008, Volker Weiss <dev@tintuc.de>
5 * Copyright (C) 2007-2010 Florian Fainelli <florian@openwrt.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 */
22#include <linux/module.h>
23#include <linux/kernel.h>
24#include <linux/init.h>
25#include <linux/spinlock.h>
26#include <linux/platform_device.h>
27#include <linux/pci.h>
28#include <linux/gpio.h>
29#include <linux/mfd/rdc321x.h>
30#include <linux/slab.h>
31
32struct rdc321x_gpio {
33 spinlock_t lock;
34 struct pci_dev *sb_pdev;
35 u32 data_reg[2];
36 int reg1_ctrl_base;
37 int reg1_data_base;
38 int reg2_ctrl_base;
39 int reg2_data_base;
40 struct gpio_chip chip;
41};
42
43/* read GPIO pin */
44static int rdc_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
45{
46 struct rdc321x_gpio *gpch;
47 u32 value = 0;
48 int reg;
49
50 gpch = container_of(chip, struct rdc321x_gpio, chip);
51 reg = gpio < 32 ? gpch->reg1_data_base : gpch->reg2_data_base;
52
53 spin_lock(&gpch->lock);
54 pci_write_config_dword(gpch->sb_pdev, reg,
55 gpch->data_reg[gpio < 32 ? 0 : 1]);
56 pci_read_config_dword(gpch->sb_pdev, reg, &value);
57 spin_unlock(&gpch->lock);
58
59 return (1 << (gpio & 0x1f)) & value ? 1 : 0;
60}
61
62static void rdc_gpio_set_value_impl(struct gpio_chip *chip,
63 unsigned gpio, int value)
64{
65 struct rdc321x_gpio *gpch;
66 int reg = (gpio < 32) ? 0 : 1;
67
68 gpch = container_of(chip, struct rdc321x_gpio, chip);
69
70 if (value)
71 gpch->data_reg[reg] |= 1 << (gpio & 0x1f);
72 else
73 gpch->data_reg[reg] &= ~(1 << (gpio & 0x1f));
74
75 pci_write_config_dword(gpch->sb_pdev,
76 reg ? gpch->reg2_data_base : gpch->reg1_data_base,
77 gpch->data_reg[reg]);
78}
79
80/* set GPIO pin to value */
81static void rdc_gpio_set_value(struct gpio_chip *chip,
82 unsigned gpio, int value)
83{
84 struct rdc321x_gpio *gpch;
85
86 gpch = container_of(chip, struct rdc321x_gpio, chip);
87 spin_lock(&gpch->lock);
88 rdc_gpio_set_value_impl(chip, gpio, value);
89 spin_unlock(&gpch->lock);
90}
91
92static int rdc_gpio_config(struct gpio_chip *chip,
93 unsigned gpio, int value)
94{
95 struct rdc321x_gpio *gpch;
96 int err;
97 u32 reg;
98
99 gpch = container_of(chip, struct rdc321x_gpio, chip);
100
101 spin_lock(&gpch->lock);
102 err = pci_read_config_dword(gpch->sb_pdev, gpio < 32 ?
103 gpch->reg1_ctrl_base : gpch->reg2_ctrl_base, &reg);
104 if (err)
105 goto unlock;
106
107 reg |= 1 << (gpio & 0x1f);
108
109 err = pci_write_config_dword(gpch->sb_pdev, gpio < 32 ?
110 gpch->reg1_ctrl_base : gpch->reg2_ctrl_base, reg);
111 if (err)
112 goto unlock;
113
114 rdc_gpio_set_value_impl(chip, gpio, value);
115
116unlock:
117 spin_unlock(&gpch->lock);
118
119 return err;
120}
121
122/* configure GPIO pin as input */
123static int rdc_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
124{
125 return rdc_gpio_config(chip, gpio, 1);
126}
127
128/*
129 * Cache the initial value of both GPIO data registers
130 */
131static int __devinit rdc321x_gpio_probe(struct platform_device *pdev)
132{
133 int err;
134 struct resource *r;
135 struct rdc321x_gpio *rdc321x_gpio_dev;
136 struct rdc321x_gpio_pdata *pdata;
137
138 pdata = pdev->dev.platform_data;
139 if (!pdata) {
140 dev_err(&pdev->dev, "no platform data supplied\n");
141 return -ENODEV;
142 }
143
144 rdc321x_gpio_dev = kzalloc(sizeof(struct rdc321x_gpio), GFP_KERNEL);
145 if (!rdc321x_gpio_dev) {
146 dev_err(&pdev->dev, "failed to allocate private data\n");
147 return -ENOMEM;
148 }
149
150 r = platform_get_resource_byname(pdev, IORESOURCE_IO, "gpio-reg1");
151 if (!r) {
152 dev_err(&pdev->dev, "failed to get gpio-reg1 resource\n");
153 err = -ENODEV;
154 goto out_free;
155 }
156
157 spin_lock_init(&rdc321x_gpio_dev->lock);
158 rdc321x_gpio_dev->sb_pdev = pdata->sb_pdev;
159 rdc321x_gpio_dev->reg1_ctrl_base = r->start;
160 rdc321x_gpio_dev->reg1_data_base = r->start + 0x4;
161
162 r = platform_get_resource_byname(pdev, IORESOURCE_IO, "gpio-reg2");
163 if (!r) {
164 dev_err(&pdev->dev, "failed to get gpio-reg2 resource\n");
165 err = -ENODEV;
166 goto out_free;
167 }
168
169 rdc321x_gpio_dev->reg2_ctrl_base = r->start;
170 rdc321x_gpio_dev->reg2_data_base = r->start + 0x4;
171
172 rdc321x_gpio_dev->chip.label = "rdc321x-gpio";
173 rdc321x_gpio_dev->chip.direction_input = rdc_gpio_direction_input;
174 rdc321x_gpio_dev->chip.direction_output = rdc_gpio_config;
175 rdc321x_gpio_dev->chip.get = rdc_gpio_get_value;
176 rdc321x_gpio_dev->chip.set = rdc_gpio_set_value;
177 rdc321x_gpio_dev->chip.base = 0;
178 rdc321x_gpio_dev->chip.ngpio = pdata->max_gpios;
179
180 platform_set_drvdata(pdev, rdc321x_gpio_dev);
181
182 /* This might not be, what others (BIOS, bootloader, etc.)
183 wrote to these registers before, but it's a good guess. Still
184 better than just using 0xffffffff. */
185 err = pci_read_config_dword(rdc321x_gpio_dev->sb_pdev,
186 rdc321x_gpio_dev->reg1_data_base,
187 &rdc321x_gpio_dev->data_reg[0]);
188 if (err)
189 goto out_drvdata;
190
191 err = pci_read_config_dword(rdc321x_gpio_dev->sb_pdev,
192 rdc321x_gpio_dev->reg2_data_base,
193 &rdc321x_gpio_dev->data_reg[1]);
194 if (err)
195 goto out_drvdata;
196
197 dev_info(&pdev->dev, "registering %d GPIOs\n",
198 rdc321x_gpio_dev->chip.ngpio);
199 return gpiochip_add(&rdc321x_gpio_dev->chip);
200
201out_drvdata:
202 platform_set_drvdata(pdev, NULL);
203out_free:
204 kfree(rdc321x_gpio_dev);
205 return err;
206}
207
208static int __devexit rdc321x_gpio_remove(struct platform_device *pdev)
209{
210 int ret;
211 struct rdc321x_gpio *rdc321x_gpio_dev = platform_get_drvdata(pdev);
212
213 ret = gpiochip_remove(&rdc321x_gpio_dev->chip);
214 if (ret)
215 dev_err(&pdev->dev, "failed to unregister chip\n");
216
217 kfree(rdc321x_gpio_dev);
218 platform_set_drvdata(pdev, NULL);
219
220 return ret;
221}
222
223static struct platform_driver rdc321x_gpio_driver = {
224 .driver.name = "rdc321x-gpio",
225 .driver.owner = THIS_MODULE,
226 .probe = rdc321x_gpio_probe,
227 .remove = __devexit_p(rdc321x_gpio_remove),
228};
229
230static int __init rdc321x_gpio_init(void)
231{
232 return platform_driver_register(&rdc321x_gpio_driver);
233}
234
235static void __exit rdc321x_gpio_exit(void)
236{
237 platform_driver_unregister(&rdc321x_gpio_driver);
238}
239
240module_init(rdc321x_gpio_init);
241module_exit(rdc321x_gpio_exit);
242
243MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
244MODULE_DESCRIPTION("RDC321x GPIO driver");
245MODULE_LICENSE("GPL");
246MODULE_ALIAS("platform:rdc321x-gpio");
diff --git a/drivers/gpio/tc35892-gpio.c b/drivers/gpio/tc35892-gpio.c
new file mode 100644
index 000000000000..1be6288780de
--- /dev/null
+++ b/drivers/gpio/tc35892-gpio.c
@@ -0,0 +1,381 @@
1/*
2 * Copyright (C) ST-Ericsson SA 2010
3 *
4 * License Terms: GNU General Public License, version 2
5 * Author: Hanumath Prasad <hanumath.prasad@stericsson.com> for ST-Ericsson
6 * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
7 */
8
9#include <linux/module.h>
10#include <linux/init.h>
11#include <linux/platform_device.h>
12#include <linux/slab.h>
13#include <linux/gpio.h>
14#include <linux/irq.h>
15#include <linux/interrupt.h>
16#include <linux/mfd/tc35892.h>
17
18/*
19 * These registers are modified under the irq bus lock and cached to avoid
20 * unnecessary writes in bus_sync_unlock.
21 */
22enum { REG_IBE, REG_IEV, REG_IS, REG_IE };
23
24#define CACHE_NR_REGS 4
25#define CACHE_NR_BANKS 3
26
27struct tc35892_gpio {
28 struct gpio_chip chip;
29 struct tc35892 *tc35892;
30 struct device *dev;
31 struct mutex irq_lock;
32
33 int irq_base;
34
35 /* Caches of interrupt control registers for bus_lock */
36 u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS];
37 u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS];
38};
39
40static inline struct tc35892_gpio *to_tc35892_gpio(struct gpio_chip *chip)
41{
42 return container_of(chip, struct tc35892_gpio, chip);
43}
44
45static int tc35892_gpio_get(struct gpio_chip *chip, unsigned offset)
46{
47 struct tc35892_gpio *tc35892_gpio = to_tc35892_gpio(chip);
48 struct tc35892 *tc35892 = tc35892_gpio->tc35892;
49 u8 reg = TC35892_GPIODATA0 + (offset / 8) * 2;
50 u8 mask = 1 << (offset % 8);
51 int ret;
52
53 ret = tc35892_reg_read(tc35892, reg);
54 if (ret < 0)
55 return ret;
56
57 return ret & mask;
58}
59
60static void tc35892_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
61{
62 struct tc35892_gpio *tc35892_gpio = to_tc35892_gpio(chip);
63 struct tc35892 *tc35892 = tc35892_gpio->tc35892;
64 u8 reg = TC35892_GPIODATA0 + (offset / 8) * 2;
65 unsigned pos = offset % 8;
66 u8 data[] = {!!val << pos, 1 << pos};
67
68 tc35892_block_write(tc35892, reg, ARRAY_SIZE(data), data);
69}
70
71static int tc35892_gpio_direction_output(struct gpio_chip *chip,
72 unsigned offset, int val)
73{
74 struct tc35892_gpio *tc35892_gpio = to_tc35892_gpio(chip);
75 struct tc35892 *tc35892 = tc35892_gpio->tc35892;
76 u8 reg = TC35892_GPIODIR0 + offset / 8;
77 unsigned pos = offset % 8;
78
79 tc35892_gpio_set(chip, offset, val);
80
81 return tc35892_set_bits(tc35892, reg, 1 << pos, 1 << pos);
82}
83
84static int tc35892_gpio_direction_input(struct gpio_chip *chip,
85 unsigned offset)
86{
87 struct tc35892_gpio *tc35892_gpio = to_tc35892_gpio(chip);
88 struct tc35892 *tc35892 = tc35892_gpio->tc35892;
89 u8 reg = TC35892_GPIODIR0 + offset / 8;
90 unsigned pos = offset % 8;
91
92 return tc35892_set_bits(tc35892, reg, 1 << pos, 0);
93}
94
95static int tc35892_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
96{
97 struct tc35892_gpio *tc35892_gpio = to_tc35892_gpio(chip);
98
99 return tc35892_gpio->irq_base + offset;
100}
101
102static struct gpio_chip template_chip = {
103 .label = "tc35892",
104 .owner = THIS_MODULE,
105 .direction_input = tc35892_gpio_direction_input,
106 .get = tc35892_gpio_get,
107 .direction_output = tc35892_gpio_direction_output,
108 .set = tc35892_gpio_set,
109 .to_irq = tc35892_gpio_to_irq,
110 .can_sleep = 1,
111};
112
113static int tc35892_gpio_irq_set_type(unsigned int irq, unsigned int type)
114{
115 struct tc35892_gpio *tc35892_gpio = get_irq_chip_data(irq);
116 int offset = irq - tc35892_gpio->irq_base;
117 int regoffset = offset / 8;
118 int mask = 1 << (offset % 8);
119
120 if (type == IRQ_TYPE_EDGE_BOTH) {
121 tc35892_gpio->regs[REG_IBE][regoffset] |= mask;
122 return 0;
123 }
124
125 tc35892_gpio->regs[REG_IBE][regoffset] &= ~mask;
126
127 if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_LEVEL_HIGH)
128 tc35892_gpio->regs[REG_IS][regoffset] |= mask;
129 else
130 tc35892_gpio->regs[REG_IS][regoffset] &= ~mask;
131
132 if (type == IRQ_TYPE_EDGE_RISING || type == IRQ_TYPE_LEVEL_HIGH)
133 tc35892_gpio->regs[REG_IEV][regoffset] |= mask;
134 else
135 tc35892_gpio->regs[REG_IEV][regoffset] &= ~mask;
136
137 return 0;
138}
139
140static void tc35892_gpio_irq_lock(unsigned int irq)
141{
142 struct tc35892_gpio *tc35892_gpio = get_irq_chip_data(irq);
143
144 mutex_lock(&tc35892_gpio->irq_lock);
145}
146
147static void tc35892_gpio_irq_sync_unlock(unsigned int irq)
148{
149 struct tc35892_gpio *tc35892_gpio = get_irq_chip_data(irq);
150 struct tc35892 *tc35892 = tc35892_gpio->tc35892;
151 static const u8 regmap[] = {
152 [REG_IBE] = TC35892_GPIOIBE0,
153 [REG_IEV] = TC35892_GPIOIEV0,
154 [REG_IS] = TC35892_GPIOIS0,
155 [REG_IE] = TC35892_GPIOIE0,
156 };
157 int i, j;
158
159 for (i = 0; i < CACHE_NR_REGS; i++) {
160 for (j = 0; j < CACHE_NR_BANKS; j++) {
161 u8 old = tc35892_gpio->oldregs[i][j];
162 u8 new = tc35892_gpio->regs[i][j];
163
164 if (new == old)
165 continue;
166
167 tc35892_gpio->oldregs[i][j] = new;
168 tc35892_reg_write(tc35892, regmap[i] + j * 8, new);
169 }
170 }
171
172 mutex_unlock(&tc35892_gpio->irq_lock);
173}
174
175static void tc35892_gpio_irq_mask(unsigned int irq)
176{
177 struct tc35892_gpio *tc35892_gpio = get_irq_chip_data(irq);
178 int offset = irq - tc35892_gpio->irq_base;
179 int regoffset = offset / 8;
180 int mask = 1 << (offset % 8);
181
182 tc35892_gpio->regs[REG_IE][regoffset] &= ~mask;
183}
184
185static void tc35892_gpio_irq_unmask(unsigned int irq)
186{
187 struct tc35892_gpio *tc35892_gpio = get_irq_chip_data(irq);
188 int offset = irq - tc35892_gpio->irq_base;
189 int regoffset = offset / 8;
190 int mask = 1 << (offset % 8);
191
192 tc35892_gpio->regs[REG_IE][regoffset] |= mask;
193}
194
195static struct irq_chip tc35892_gpio_irq_chip = {
196 .name = "tc35892-gpio",
197 .bus_lock = tc35892_gpio_irq_lock,
198 .bus_sync_unlock = tc35892_gpio_irq_sync_unlock,
199 .mask = tc35892_gpio_irq_mask,
200 .unmask = tc35892_gpio_irq_unmask,
201 .set_type = tc35892_gpio_irq_set_type,
202};
203
204static irqreturn_t tc35892_gpio_irq(int irq, void *dev)
205{
206 struct tc35892_gpio *tc35892_gpio = dev;
207 struct tc35892 *tc35892 = tc35892_gpio->tc35892;
208 u8 status[CACHE_NR_BANKS];
209 int ret;
210 int i;
211
212 ret = tc35892_block_read(tc35892, TC35892_GPIOMIS0,
213 ARRAY_SIZE(status), status);
214 if (ret < 0)
215 return IRQ_NONE;
216
217 for (i = 0; i < ARRAY_SIZE(status); i++) {
218 unsigned int stat = status[i];
219 if (!stat)
220 continue;
221
222 while (stat) {
223 int bit = __ffs(stat);
224 int line = i * 8 + bit;
225
226 handle_nested_irq(tc35892_gpio->irq_base + line);
227 stat &= ~(1 << bit);
228 }
229
230 tc35892_reg_write(tc35892, TC35892_GPIOIC0 + i, status[i]);
231 }
232
233 return IRQ_HANDLED;
234}
235
236static int tc35892_gpio_irq_init(struct tc35892_gpio *tc35892_gpio)
237{
238 int base = tc35892_gpio->irq_base;
239 int irq;
240
241 for (irq = base; irq < base + tc35892_gpio->chip.ngpio; irq++) {
242 set_irq_chip_data(irq, tc35892_gpio);
243 set_irq_chip_and_handler(irq, &tc35892_gpio_irq_chip,
244 handle_simple_irq);
245 set_irq_nested_thread(irq, 1);
246#ifdef CONFIG_ARM
247 set_irq_flags(irq, IRQF_VALID);
248#else
249 set_irq_noprobe(irq);
250#endif
251 }
252
253 return 0;
254}
255
256static void tc35892_gpio_irq_remove(struct tc35892_gpio *tc35892_gpio)
257{
258 int base = tc35892_gpio->irq_base;
259 int irq;
260
261 for (irq = base; irq < base + tc35892_gpio->chip.ngpio; irq++) {
262#ifdef CONFIG_ARM
263 set_irq_flags(irq, 0);
264#endif
265 set_irq_chip_and_handler(irq, NULL, NULL);
266 set_irq_chip_data(irq, NULL);
267 }
268}
269
270static int __devinit tc35892_gpio_probe(struct platform_device *pdev)
271{
272 struct tc35892 *tc35892 = dev_get_drvdata(pdev->dev.parent);
273 struct tc35892_gpio_platform_data *pdata;
274 struct tc35892_gpio *tc35892_gpio;
275 int ret;
276 int irq;
277
278 pdata = tc35892->pdata->gpio;
279 if (!pdata)
280 return -ENODEV;
281
282 irq = platform_get_irq(pdev, 0);
283 if (irq < 0)
284 return irq;
285
286 tc35892_gpio = kzalloc(sizeof(struct tc35892_gpio), GFP_KERNEL);
287 if (!tc35892_gpio)
288 return -ENOMEM;
289
290 mutex_init(&tc35892_gpio->irq_lock);
291
292 tc35892_gpio->dev = &pdev->dev;
293 tc35892_gpio->tc35892 = tc35892;
294
295 tc35892_gpio->chip = template_chip;
296 tc35892_gpio->chip.ngpio = tc35892->num_gpio;
297 tc35892_gpio->chip.dev = &pdev->dev;
298 tc35892_gpio->chip.base = pdata->gpio_base;
299
300 tc35892_gpio->irq_base = tc35892->irq_base + TC35892_INT_GPIO(0);
301
302 /* Bring the GPIO module out of reset */
303 ret = tc35892_set_bits(tc35892, TC35892_RSTCTRL,
304 TC35892_RSTCTRL_GPIRST, 0);
305 if (ret < 0)
306 goto out_free;
307
308 ret = tc35892_gpio_irq_init(tc35892_gpio);
309 if (ret)
310 goto out_free;
311
312 ret = request_threaded_irq(irq, NULL, tc35892_gpio_irq, IRQF_ONESHOT,
313 "tc35892-gpio", tc35892_gpio);
314 if (ret) {
315 dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
316 goto out_removeirq;
317 }
318
319 ret = gpiochip_add(&tc35892_gpio->chip);
320 if (ret) {
321 dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret);
322 goto out_freeirq;
323 }
324
325 platform_set_drvdata(pdev, tc35892_gpio);
326
327 return 0;
328
329out_freeirq:
330 free_irq(irq, tc35892_gpio);
331out_removeirq:
332 tc35892_gpio_irq_remove(tc35892_gpio);
333out_free:
334 kfree(tc35892_gpio);
335 return ret;
336}
337
338static int __devexit tc35892_gpio_remove(struct platform_device *pdev)
339{
340 struct tc35892_gpio *tc35892_gpio = platform_get_drvdata(pdev);
341 int irq = platform_get_irq(pdev, 0);
342 int ret;
343
344 ret = gpiochip_remove(&tc35892_gpio->chip);
345 if (ret < 0) {
346 dev_err(tc35892_gpio->dev,
347 "unable to remove gpiochip: %d\n", ret);
348 return ret;
349 }
350
351 free_irq(irq, tc35892_gpio);
352 tc35892_gpio_irq_remove(tc35892_gpio);
353
354 platform_set_drvdata(pdev, NULL);
355 kfree(tc35892_gpio);
356
357 return 0;
358}
359
360static struct platform_driver tc35892_gpio_driver = {
361 .driver.name = "tc35892-gpio",
362 .driver.owner = THIS_MODULE,
363 .probe = tc35892_gpio_probe,
364 .remove = __devexit_p(tc35892_gpio_remove),
365};
366
367static int __init tc35892_gpio_init(void)
368{
369 return platform_driver_register(&tc35892_gpio_driver);
370}
371subsys_initcall(tc35892_gpio_init);
372
373static void __exit tc35892_gpio_exit(void)
374{
375 platform_driver_unregister(&tc35892_gpio_driver);
376}
377module_exit(tc35892_gpio_exit);
378
379MODULE_LICENSE("GPL v2");
380MODULE_DESCRIPTION("TC35892 GPIO driver");
381MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent");
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 994d23beeb1d..57cea01c4ffb 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1840,8 +1840,10 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
1840 1840
1841 ret = copy_from_user(clips, clips_ptr, 1841 ret = copy_from_user(clips, clips_ptr,
1842 num_clips * sizeof(*clips)); 1842 num_clips * sizeof(*clips));
1843 if (ret) 1843 if (ret) {
1844 ret = -EFAULT;
1844 goto out_err2; 1845 goto out_err2;
1846 }
1845 } 1847 }
1846 1848
1847 if (fb->funcs->dirty) { 1849 if (fb->funcs->dirty) {
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 764401951041..9b2a54117c91 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -860,19 +860,24 @@ static void output_poll_execute(struct slow_work *work)
860 } 860 }
861} 861}
862 862
863void drm_kms_helper_poll_init(struct drm_device *dev) 863void drm_kms_helper_poll_disable(struct drm_device *dev)
864{
865 if (!dev->mode_config.poll_enabled)
866 return;
867 delayed_slow_work_cancel(&dev->mode_config.output_poll_slow_work);
868}
869EXPORT_SYMBOL(drm_kms_helper_poll_disable);
870
871void drm_kms_helper_poll_enable(struct drm_device *dev)
864{ 872{
865 struct drm_connector *connector;
866 bool poll = false; 873 bool poll = false;
874 struct drm_connector *connector;
867 int ret; 875 int ret;
868 876
869 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 877 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
870 if (connector->polled) 878 if (connector->polled)
871 poll = true; 879 poll = true;
872 } 880 }
873 slow_work_register_user(THIS_MODULE);
874 delayed_slow_work_init(&dev->mode_config.output_poll_slow_work,
875 &output_poll_ops);
876 881
877 if (poll) { 882 if (poll) {
878 ret = delayed_slow_work_enqueue(&dev->mode_config.output_poll_slow_work, DRM_OUTPUT_POLL_PERIOD); 883 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)
880 DRM_ERROR("delayed enqueue failed %d\n", ret); 885 DRM_ERROR("delayed enqueue failed %d\n", ret);
881 } 886 }
882} 887}
888EXPORT_SYMBOL(drm_kms_helper_poll_enable);
889
890void drm_kms_helper_poll_init(struct drm_device *dev)
891{
892 slow_work_register_user(THIS_MODULE);
893 delayed_slow_work_init(&dev->mode_config.output_poll_slow_work,
894 &output_poll_ops);
895 dev->mode_config.poll_enabled = true;
896
897 drm_kms_helper_poll_enable(dev);
898}
883EXPORT_SYMBOL(drm_kms_helper_poll_init); 899EXPORT_SYMBOL(drm_kms_helper_poll_init);
884 900
885void drm_kms_helper_poll_fini(struct drm_device *dev) 901void drm_kms_helper_poll_fini(struct drm_device *dev)
886{ 902{
887 delayed_slow_work_cancel(&dev->mode_config.output_poll_slow_work); 903 drm_kms_helper_poll_disable(dev);
888 slow_work_unregister_user(THIS_MODULE); 904 slow_work_unregister_user(THIS_MODULE);
889} 905}
890EXPORT_SYMBOL(drm_kms_helper_poll_fini); 906EXPORT_SYMBOL(drm_kms_helper_poll_fini);
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index f569ae88ab38..c1981861bbbd 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -147,7 +147,10 @@ drm_edid_block_valid(u8 *raw_edid)
147 csum += raw_edid[i]; 147 csum += raw_edid[i];
148 if (csum) { 148 if (csum) {
149 DRM_ERROR("EDID checksum is invalid, remainder is %d\n", csum); 149 DRM_ERROR("EDID checksum is invalid, remainder is %d\n", csum);
150 goto bad; 150
151 /* allow CEA to slide through, switches mangle this */
152 if (raw_edid[0] != 0x02)
153 goto bad;
151 } 154 }
152 155
153 /* per-block-type checks */ 156 /* per-block-type checks */
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index b3779d243aef..08c4c926e65f 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -264,7 +264,7 @@ bool drm_fb_helper_force_kernel_mode(void)
264int drm_fb_helper_panic(struct notifier_block *n, unsigned long ununsed, 264int drm_fb_helper_panic(struct notifier_block *n, unsigned long ununsed,
265 void *panic_str) 265 void *panic_str)
266{ 266{
267 DRM_ERROR("panic occurred, switching back to text console\n"); 267 printk(KERN_ERR "panic occurred, switching back to text console\n");
268 return drm_fb_helper_force_kernel_mode(); 268 return drm_fb_helper_force_kernel_mode();
269 return 0; 269 return 0;
270} 270}
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 95639017bdbe..da78f2c0d909 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -22,6 +22,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \
22 intel_fb.o \ 22 intel_fb.o \
23 intel_tv.o \ 23 intel_tv.o \
24 intel_dvo.o \ 24 intel_dvo.o \
25 intel_ringbuffer.o \
25 intel_overlay.o \ 26 intel_overlay.o \
26 dvo_ch7xxx.o \ 27 dvo_ch7xxx.o \
27 dvo_ch7017.o \ 28 dvo_ch7017.o \
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 322070c0c631..52510ad8b25d 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -77,7 +77,7 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data)
77 case ACTIVE_LIST: 77 case ACTIVE_LIST:
78 seq_printf(m, "Active:\n"); 78 seq_printf(m, "Active:\n");
79 lock = &dev_priv->mm.active_list_lock; 79 lock = &dev_priv->mm.active_list_lock;
80 head = &dev_priv->mm.active_list; 80 head = &dev_priv->render_ring.active_list;
81 break; 81 break;
82 case INACTIVE_LIST: 82 case INACTIVE_LIST:
83 seq_printf(m, "Inactive:\n"); 83 seq_printf(m, "Inactive:\n");
@@ -129,7 +129,8 @@ static int i915_gem_request_info(struct seq_file *m, void *data)
129 struct drm_i915_gem_request *gem_request; 129 struct drm_i915_gem_request *gem_request;
130 130
131 seq_printf(m, "Request:\n"); 131 seq_printf(m, "Request:\n");
132 list_for_each_entry(gem_request, &dev_priv->mm.request_list, list) { 132 list_for_each_entry(gem_request, &dev_priv->render_ring.request_list,
133 list) {
133 seq_printf(m, " %d @ %d\n", 134 seq_printf(m, " %d @ %d\n",
134 gem_request->seqno, 135 gem_request->seqno,
135 (int) (jiffies - gem_request->emitted_jiffies)); 136 (int) (jiffies - gem_request->emitted_jiffies));
@@ -143,9 +144,9 @@ static int i915_gem_seqno_info(struct seq_file *m, void *data)
143 struct drm_device *dev = node->minor->dev; 144 struct drm_device *dev = node->minor->dev;
144 drm_i915_private_t *dev_priv = dev->dev_private; 145 drm_i915_private_t *dev_priv = dev->dev_private;
145 146
146 if (dev_priv->hw_status_page != NULL) { 147 if (dev_priv->render_ring.status_page.page_addr != NULL) {
147 seq_printf(m, "Current sequence: %d\n", 148 seq_printf(m, "Current sequence: %d\n",
148 i915_get_gem_seqno(dev)); 149 i915_get_gem_seqno(dev, &dev_priv->render_ring));
149 } else { 150 } else {
150 seq_printf(m, "Current sequence: hws uninitialized\n"); 151 seq_printf(m, "Current sequence: hws uninitialized\n");
151 } 152 }
@@ -195,9 +196,9 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
195 } 196 }
196 seq_printf(m, "Interrupts received: %d\n", 197 seq_printf(m, "Interrupts received: %d\n",
197 atomic_read(&dev_priv->irq_received)); 198 atomic_read(&dev_priv->irq_received));
198 if (dev_priv->hw_status_page != NULL) { 199 if (dev_priv->render_ring.status_page.page_addr != NULL) {
199 seq_printf(m, "Current sequence: %d\n", 200 seq_printf(m, "Current sequence: %d\n",
200 i915_get_gem_seqno(dev)); 201 i915_get_gem_seqno(dev, &dev_priv->render_ring));
201 } else { 202 } else {
202 seq_printf(m, "Current sequence: hws uninitialized\n"); 203 seq_printf(m, "Current sequence: hws uninitialized\n");
203 } 204 }
@@ -251,7 +252,7 @@ static int i915_hws_info(struct seq_file *m, void *data)
251 int i; 252 int i;
252 volatile u32 *hws; 253 volatile u32 *hws;
253 254
254 hws = (volatile u32 *)dev_priv->hw_status_page; 255 hws = (volatile u32 *)dev_priv->render_ring.status_page.page_addr;
255 if (hws == NULL) 256 if (hws == NULL)
256 return 0; 257 return 0;
257 258
@@ -287,7 +288,8 @@ static int i915_batchbuffer_info(struct seq_file *m, void *data)
287 288
288 spin_lock(&dev_priv->mm.active_list_lock); 289 spin_lock(&dev_priv->mm.active_list_lock);
289 290
290 list_for_each_entry(obj_priv, &dev_priv->mm.active_list, list) { 291 list_for_each_entry(obj_priv, &dev_priv->render_ring.active_list,
292 list) {
291 obj = &obj_priv->base; 293 obj = &obj_priv->base;
292 if (obj->read_domains & I915_GEM_DOMAIN_COMMAND) { 294 if (obj->read_domains & I915_GEM_DOMAIN_COMMAND) {
293 ret = i915_gem_object_get_pages(obj, 0); 295 ret = i915_gem_object_get_pages(obj, 0);
@@ -317,14 +319,14 @@ static int i915_ringbuffer_data(struct seq_file *m, void *data)
317 u8 *virt; 319 u8 *virt;
318 uint32_t *ptr, off; 320 uint32_t *ptr, off;
319 321
320 if (!dev_priv->ring.ring_obj) { 322 if (!dev_priv->render_ring.gem_object) {
321 seq_printf(m, "No ringbuffer setup\n"); 323 seq_printf(m, "No ringbuffer setup\n");
322 return 0; 324 return 0;
323 } 325 }
324 326
325 virt = dev_priv->ring.virtual_start; 327 virt = dev_priv->render_ring.virtual_start;
326 328
327 for (off = 0; off < dev_priv->ring.Size; off += 4) { 329 for (off = 0; off < dev_priv->render_ring.size; off += 4) {
328 ptr = (uint32_t *)(virt + off); 330 ptr = (uint32_t *)(virt + off);
329 seq_printf(m, "%08x : %08x\n", off, *ptr); 331 seq_printf(m, "%08x : %08x\n", off, *ptr);
330 } 332 }
@@ -344,7 +346,7 @@ static int i915_ringbuffer_info(struct seq_file *m, void *data)
344 346
345 seq_printf(m, "RingHead : %08x\n", head); 347 seq_printf(m, "RingHead : %08x\n", head);
346 seq_printf(m, "RingTail : %08x\n", tail); 348 seq_printf(m, "RingTail : %08x\n", tail);
347 seq_printf(m, "RingSize : %08lx\n", dev_priv->ring.Size); 349 seq_printf(m, "RingSize : %08lx\n", dev_priv->render_ring.size);
348 seq_printf(m, "Acthd : %08x\n", I915_READ(IS_I965G(dev) ? ACTHD_I965 : ACTHD)); 350 seq_printf(m, "Acthd : %08x\n", I915_READ(IS_I965G(dev) ? ACTHD_I965 : ACTHD));
349 351
350 return 0; 352 return 0;
@@ -489,11 +491,14 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
489 struct drm_device *dev = node->minor->dev; 491 struct drm_device *dev = node->minor->dev;
490 drm_i915_private_t *dev_priv = dev->dev_private; 492 drm_i915_private_t *dev_priv = dev->dev_private;
491 u16 rgvswctl = I915_READ16(MEMSWCTL); 493 u16 rgvswctl = I915_READ16(MEMSWCTL);
494 u16 rgvstat = I915_READ16(MEMSTAT_ILK);
492 495
493 seq_printf(m, "Last command: 0x%01x\n", (rgvswctl >> 13) & 0x3); 496 seq_printf(m, "Requested P-state: %d\n", (rgvswctl >> 8) & 0xf);
494 seq_printf(m, "Command status: %d\n", (rgvswctl >> 12) & 1); 497 seq_printf(m, "Requested VID: %d\n", rgvswctl & 0x3f);
495 seq_printf(m, "P%d DELAY 0x%02x\n", (rgvswctl >> 8) & 0xf, 498 seq_printf(m, "Current VID: %d\n", (rgvstat & MEMSTAT_VID_MASK) >>
496 rgvswctl & 0x3f); 499 MEMSTAT_VID_SHIFT);
500 seq_printf(m, "Current P-state: %d\n",
501 (rgvstat & MEMSTAT_PSTATE_MASK) >> MEMSTAT_PSTATE_SHIFT);
497 502
498 return 0; 503 return 0;
499} 504}
@@ -508,7 +513,8 @@ static int i915_delayfreq_table(struct seq_file *m, void *unused)
508 513
509 for (i = 0; i < 16; i++) { 514 for (i = 0; i < 16; i++) {
510 delayfreq = I915_READ(PXVFREQ_BASE + i * 4); 515 delayfreq = I915_READ(PXVFREQ_BASE + i * 4);
511 seq_printf(m, "P%02dVIDFREQ: 0x%08x\n", i, delayfreq); 516 seq_printf(m, "P%02dVIDFREQ: 0x%08x (VID: %d)\n", i, delayfreq,
517 (delayfreq & PXVFREQ_PX_MASK) >> PXVFREQ_PX_SHIFT);
512 } 518 }
513 519
514 return 0; 520 return 0;
@@ -541,6 +547,8 @@ static int i915_drpc_info(struct seq_file *m, void *unused)
541 struct drm_device *dev = node->minor->dev; 547 struct drm_device *dev = node->minor->dev;
542 drm_i915_private_t *dev_priv = dev->dev_private; 548 drm_i915_private_t *dev_priv = dev->dev_private;
543 u32 rgvmodectl = I915_READ(MEMMODECTL); 549 u32 rgvmodectl = I915_READ(MEMMODECTL);
550 u32 rstdbyctl = I915_READ(MCHBAR_RENDER_STANDBY);
551 u16 crstandvid = I915_READ16(CRSTANDVID);
544 552
545 seq_printf(m, "HD boost: %s\n", (rgvmodectl & MEMMODE_BOOST_EN) ? 553 seq_printf(m, "HD boost: %s\n", (rgvmodectl & MEMMODE_BOOST_EN) ?
546 "yes" : "no"); 554 "yes" : "no");
@@ -555,9 +563,13 @@ static int i915_drpc_info(struct seq_file *m, void *unused)
555 rgvmodectl & MEMMODE_RCLK_GATE ? "yes" : "no"); 563 rgvmodectl & MEMMODE_RCLK_GATE ? "yes" : "no");
556 seq_printf(m, "Starting frequency: P%d\n", 564 seq_printf(m, "Starting frequency: P%d\n",
557 (rgvmodectl & MEMMODE_FSTART_MASK) >> MEMMODE_FSTART_SHIFT); 565 (rgvmodectl & MEMMODE_FSTART_MASK) >> MEMMODE_FSTART_SHIFT);
558 seq_printf(m, "Max frequency: P%d\n", 566 seq_printf(m, "Max P-state: P%d\n",
559 (rgvmodectl & MEMMODE_FMAX_MASK) >> MEMMODE_FMAX_SHIFT); 567 (rgvmodectl & MEMMODE_FMAX_MASK) >> MEMMODE_FMAX_SHIFT);
560 seq_printf(m, "Min frequency: P%d\n", (rgvmodectl & MEMMODE_FMIN_MASK)); 568 seq_printf(m, "Min P-state: P%d\n", (rgvmodectl & MEMMODE_FMIN_MASK));
569 seq_printf(m, "RS1 VID: %d\n", (crstandvid & 0x3f));
570 seq_printf(m, "RS2 VID: %d\n", ((crstandvid >> 8) & 0x3f));
571 seq_printf(m, "Render standby enabled: %s\n",
572 (rstdbyctl & RCX_SW_EXIT) ? "no" : "yes");
561 573
562 return 0; 574 return 0;
563} 575}
@@ -621,6 +633,36 @@ static int i915_sr_status(struct seq_file *m, void *unused)
621 return 0; 633 return 0;
622} 634}
623 635
636static int i915_emon_status(struct seq_file *m, void *unused)
637{
638 struct drm_info_node *node = (struct drm_info_node *) m->private;
639 struct drm_device *dev = node->minor->dev;
640 drm_i915_private_t *dev_priv = dev->dev_private;
641 unsigned long temp, chipset, gfx;
642
643 temp = i915_mch_val(dev_priv);
644 chipset = i915_chipset_val(dev_priv);
645 gfx = i915_gfx_val(dev_priv);
646
647 seq_printf(m, "GMCH temp: %ld\n", temp);
648 seq_printf(m, "Chipset power: %ld\n", chipset);
649 seq_printf(m, "GFX power: %ld\n", gfx);
650 seq_printf(m, "Total power: %ld\n", chipset + gfx);
651
652 return 0;
653}
654
655static int i915_gfxec(struct seq_file *m, void *unused)
656{
657 struct drm_info_node *node = (struct drm_info_node *) m->private;
658 struct drm_device *dev = node->minor->dev;
659 drm_i915_private_t *dev_priv = dev->dev_private;
660
661 seq_printf(m, "GFXEC: %ld\n", (unsigned long)I915_READ(0x112f4));
662
663 return 0;
664}
665
624static int 666static int
625i915_wedged_open(struct inode *inode, 667i915_wedged_open(struct inode *inode,
626 struct file *filp) 668 struct file *filp)
@@ -743,6 +785,8 @@ static struct drm_info_list i915_debugfs_list[] = {
743 {"i915_delayfreq_table", i915_delayfreq_table, 0}, 785 {"i915_delayfreq_table", i915_delayfreq_table, 0},
744 {"i915_inttoext_table", i915_inttoext_table, 0}, 786 {"i915_inttoext_table", i915_inttoext_table, 0},
745 {"i915_drpc_info", i915_drpc_info, 0}, 787 {"i915_drpc_info", i915_drpc_info, 0},
788 {"i915_emon_status", i915_emon_status, 0},
789 {"i915_gfxec", i915_gfxec, 0},
746 {"i915_fbc_status", i915_fbc_status, 0}, 790 {"i915_fbc_status", i915_fbc_status, 0},
747 {"i915_sr_status", i915_sr_status, 0}, 791 {"i915_sr_status", i915_sr_status, 0},
748}; 792};
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 2a6b5de5ae5d..59a2bf8592ec 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -40,84 +40,6 @@
40#include <linux/vga_switcheroo.h> 40#include <linux/vga_switcheroo.h>
41#include <linux/slab.h> 41#include <linux/slab.h>
42 42
43/* Really want an OS-independent resettable timer. Would like to have
44 * this loop run for (eg) 3 sec, but have the timer reset every time
45 * the head pointer changes, so that EBUSY only happens if the ring
46 * actually stalls for (eg) 3 seconds.
47 */
48int i915_wait_ring(struct drm_device * dev, int n, const char *caller)
49{
50 drm_i915_private_t *dev_priv = dev->dev_private;
51 drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
52 u32 acthd_reg = IS_I965G(dev) ? ACTHD_I965 : ACTHD;
53 u32 last_acthd = I915_READ(acthd_reg);
54 u32 acthd;
55 u32 last_head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
56 int i;
57
58 trace_i915_ring_wait_begin (dev);
59
60 for (i = 0; i < 100000; i++) {
61 ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
62 acthd = I915_READ(acthd_reg);
63 ring->space = ring->head - (ring->tail + 8);
64 if (ring->space < 0)
65 ring->space += ring->Size;
66 if (ring->space >= n) {
67 trace_i915_ring_wait_end (dev);
68 return 0;
69 }
70
71 if (dev->primary->master) {
72 struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
73 if (master_priv->sarea_priv)
74 master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
75 }
76
77
78 if (ring->head != last_head)
79 i = 0;
80 if (acthd != last_acthd)
81 i = 0;
82
83 last_head = ring->head;
84 last_acthd = acthd;
85 msleep_interruptible(10);
86
87 }
88
89 trace_i915_ring_wait_end (dev);
90 return -EBUSY;
91}
92
93/* As a ringbuffer is only allowed to wrap between instructions, fill
94 * the tail with NOOPs.
95 */
96int i915_wrap_ring(struct drm_device *dev)
97{
98 drm_i915_private_t *dev_priv = dev->dev_private;
99 volatile unsigned int *virt;
100 int rem;
101
102 rem = dev_priv->ring.Size - dev_priv->ring.tail;
103 if (dev_priv->ring.space < rem) {
104 int ret = i915_wait_ring(dev, rem, __func__);
105 if (ret)
106 return ret;
107 }
108 dev_priv->ring.space -= rem;
109
110 virt = (unsigned int *)
111 (dev_priv->ring.virtual_start + dev_priv->ring.tail);
112 rem /= 4;
113 while (rem--)
114 *virt++ = MI_NOOP;
115
116 dev_priv->ring.tail = 0;
117
118 return 0;
119}
120
121/** 43/**
122 * Sets up the hardware status page for devices that need a physical address 44 * Sets up the hardware status page for devices that need a physical address
123 * in the register. 45 * in the register.
@@ -133,10 +55,11 @@ static int i915_init_phys_hws(struct drm_device *dev)
133 DRM_ERROR("Can not allocate hardware status page\n"); 55 DRM_ERROR("Can not allocate hardware status page\n");
134 return -ENOMEM; 56 return -ENOMEM;
135 } 57 }
136 dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr; 58 dev_priv->render_ring.status_page.page_addr
59 = dev_priv->status_page_dmah->vaddr;
137 dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr; 60 dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
138 61
139 memset(dev_priv->hw_status_page, 0, PAGE_SIZE); 62 memset(dev_priv->render_ring.status_page.page_addr, 0, PAGE_SIZE);
140 63
141 if (IS_I965G(dev)) 64 if (IS_I965G(dev))
142 dev_priv->dma_status_page |= (dev_priv->dma_status_page >> 28) & 65 dev_priv->dma_status_page |= (dev_priv->dma_status_page >> 28) &
@@ -159,8 +82,8 @@ static void i915_free_hws(struct drm_device *dev)
159 dev_priv->status_page_dmah = NULL; 82 dev_priv->status_page_dmah = NULL;
160 } 83 }
161 84
162 if (dev_priv->status_gfx_addr) { 85 if (dev_priv->render_ring.status_page.gfx_addr) {
163 dev_priv->status_gfx_addr = 0; 86 dev_priv->render_ring.status_page.gfx_addr = 0;
164 drm_core_ioremapfree(&dev_priv->hws_map, dev); 87 drm_core_ioremapfree(&dev_priv->hws_map, dev);
165 } 88 }
166 89
@@ -172,7 +95,7 @@ void i915_kernel_lost_context(struct drm_device * dev)
172{ 95{
173 drm_i915_private_t *dev_priv = dev->dev_private; 96 drm_i915_private_t *dev_priv = dev->dev_private;
174 struct drm_i915_master_private *master_priv; 97 struct drm_i915_master_private *master_priv;
175 drm_i915_ring_buffer_t *ring = &(dev_priv->ring); 98 struct intel_ring_buffer *ring = &dev_priv->render_ring;
176 99
177 /* 100 /*
178 * We should never lose context on the ring with modesetting 101 * We should never lose context on the ring with modesetting
@@ -185,7 +108,7 @@ void i915_kernel_lost_context(struct drm_device * dev)
185 ring->tail = I915_READ(PRB0_TAIL) & TAIL_ADDR; 108 ring->tail = I915_READ(PRB0_TAIL) & TAIL_ADDR;
186 ring->space = ring->head - (ring->tail + 8); 109 ring->space = ring->head - (ring->tail + 8);
187 if (ring->space < 0) 110 if (ring->space < 0)
188 ring->space += ring->Size; 111 ring->space += ring->size;
189 112
190 if (!dev->primary->master) 113 if (!dev->primary->master)
191 return; 114 return;
@@ -205,12 +128,9 @@ static int i915_dma_cleanup(struct drm_device * dev)
205 if (dev->irq_enabled) 128 if (dev->irq_enabled)
206 drm_irq_uninstall(dev); 129 drm_irq_uninstall(dev);
207 130
208 if (dev_priv->ring.virtual_start) { 131 intel_cleanup_ring_buffer(dev, &dev_priv->render_ring);
209 drm_core_ioremapfree(&dev_priv->ring.map, dev); 132 if (HAS_BSD(dev))
210 dev_priv->ring.virtual_start = NULL; 133 intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring);
211 dev_priv->ring.map.handle = NULL;
212 dev_priv->ring.map.size = 0;
213 }
214 134
215 /* Clear the HWS virtual address at teardown */ 135 /* Clear the HWS virtual address at teardown */
216 if (I915_NEED_GFX_HWS(dev)) 136 if (I915_NEED_GFX_HWS(dev))
@@ -233,24 +153,24 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
233 } 153 }
234 154
235 if (init->ring_size != 0) { 155 if (init->ring_size != 0) {
236 if (dev_priv->ring.ring_obj != NULL) { 156 if (dev_priv->render_ring.gem_object != NULL) {
237 i915_dma_cleanup(dev); 157 i915_dma_cleanup(dev);
238 DRM_ERROR("Client tried to initialize ringbuffer in " 158 DRM_ERROR("Client tried to initialize ringbuffer in "
239 "GEM mode\n"); 159 "GEM mode\n");
240 return -EINVAL; 160 return -EINVAL;
241 } 161 }
242 162
243 dev_priv->ring.Size = init->ring_size; 163 dev_priv->render_ring.size = init->ring_size;
244 164
245 dev_priv->ring.map.offset = init->ring_start; 165 dev_priv->render_ring.map.offset = init->ring_start;
246 dev_priv->ring.map.size = init->ring_size; 166 dev_priv->render_ring.map.size = init->ring_size;
247 dev_priv->ring.map.type = 0; 167 dev_priv->render_ring.map.type = 0;
248 dev_priv->ring.map.flags = 0; 168 dev_priv->render_ring.map.flags = 0;
249 dev_priv->ring.map.mtrr = 0; 169 dev_priv->render_ring.map.mtrr = 0;
250 170
251 drm_core_ioremap_wc(&dev_priv->ring.map, dev); 171 drm_core_ioremap_wc(&dev_priv->render_ring.map, dev);
252 172
253 if (dev_priv->ring.map.handle == NULL) { 173 if (dev_priv->render_ring.map.handle == NULL) {
254 i915_dma_cleanup(dev); 174 i915_dma_cleanup(dev);
255 DRM_ERROR("can not ioremap virtual address for" 175 DRM_ERROR("can not ioremap virtual address for"
256 " ring buffer\n"); 176 " ring buffer\n");
@@ -258,7 +178,7 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
258 } 178 }
259 } 179 }
260 180
261 dev_priv->ring.virtual_start = dev_priv->ring.map.handle; 181 dev_priv->render_ring.virtual_start = dev_priv->render_ring.map.handle;
262 182
263 dev_priv->cpp = init->cpp; 183 dev_priv->cpp = init->cpp;
264 dev_priv->back_offset = init->back_offset; 184 dev_priv->back_offset = init->back_offset;
@@ -278,26 +198,29 @@ static int i915_dma_resume(struct drm_device * dev)
278{ 198{
279 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 199 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
280 200
201 struct intel_ring_buffer *ring;
281 DRM_DEBUG_DRIVER("%s\n", __func__); 202 DRM_DEBUG_DRIVER("%s\n", __func__);
282 203
283 if (dev_priv->ring.map.handle == NULL) { 204 ring = &dev_priv->render_ring;
205
206 if (ring->map.handle == NULL) {
284 DRM_ERROR("can not ioremap virtual address for" 207 DRM_ERROR("can not ioremap virtual address for"
285 " ring buffer\n"); 208 " ring buffer\n");
286 return -ENOMEM; 209 return -ENOMEM;
287 } 210 }
288 211
289 /* Program Hardware Status Page */ 212 /* Program Hardware Status Page */
290 if (!dev_priv->hw_status_page) { 213 if (!ring->status_page.page_addr) {
291 DRM_ERROR("Can not find hardware status page\n"); 214 DRM_ERROR("Can not find hardware status page\n");
292 return -EINVAL; 215 return -EINVAL;
293 } 216 }
294 DRM_DEBUG_DRIVER("hw status page @ %p\n", 217 DRM_DEBUG_DRIVER("hw status page @ %p\n",
295 dev_priv->hw_status_page); 218 ring->status_page.page_addr);
296 219 if (ring->status_page.gfx_addr != 0)
297 if (dev_priv->status_gfx_addr != 0) 220 ring->setup_status_page(dev, ring);
298 I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
299 else 221 else
300 I915_WRITE(HWS_PGA, dev_priv->dma_status_page); 222 I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
223
301 DRM_DEBUG_DRIVER("Enabled hardware status page\n"); 224 DRM_DEBUG_DRIVER("Enabled hardware status page\n");
302 225
303 return 0; 226 return 0;
@@ -407,9 +330,8 @@ static int i915_emit_cmds(struct drm_device * dev, int *buffer, int dwords)
407{ 330{
408 drm_i915_private_t *dev_priv = dev->dev_private; 331 drm_i915_private_t *dev_priv = dev->dev_private;
409 int i; 332 int i;
410 RING_LOCALS;
411 333
412 if ((dwords+1) * sizeof(int) >= dev_priv->ring.Size - 8) 334 if ((dwords+1) * sizeof(int) >= dev_priv->render_ring.size - 8)
413 return -EINVAL; 335 return -EINVAL;
414 336
415 BEGIN_LP_RING((dwords+1)&~1); 337 BEGIN_LP_RING((dwords+1)&~1);
@@ -442,9 +364,7 @@ i915_emit_box(struct drm_device *dev,
442 struct drm_clip_rect *boxes, 364 struct drm_clip_rect *boxes,
443 int i, int DR1, int DR4) 365 int i, int DR1, int DR4)
444{ 366{
445 drm_i915_private_t *dev_priv = dev->dev_private;
446 struct drm_clip_rect box = boxes[i]; 367 struct drm_clip_rect box = boxes[i];
447 RING_LOCALS;
448 368
449 if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) { 369 if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) {
450 DRM_ERROR("Bad box %d,%d..%d,%d\n", 370 DRM_ERROR("Bad box %d,%d..%d,%d\n",
@@ -481,7 +401,6 @@ static void i915_emit_breadcrumb(struct drm_device *dev)
481{ 401{
482 drm_i915_private_t *dev_priv = dev->dev_private; 402 drm_i915_private_t *dev_priv = dev->dev_private;
483 struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; 403 struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
484 RING_LOCALS;
485 404
486 dev_priv->counter++; 405 dev_priv->counter++;
487 if (dev_priv->counter > 0x7FFFFFFFUL) 406 if (dev_priv->counter > 0x7FFFFFFFUL)
@@ -535,10 +454,8 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev,
535 drm_i915_batchbuffer_t * batch, 454 drm_i915_batchbuffer_t * batch,
536 struct drm_clip_rect *cliprects) 455 struct drm_clip_rect *cliprects)
537{ 456{
538 drm_i915_private_t *dev_priv = dev->dev_private;
539 int nbox = batch->num_cliprects; 457 int nbox = batch->num_cliprects;
540 int i = 0, count; 458 int i = 0, count;
541 RING_LOCALS;
542 459
543 if ((batch->start | batch->used) & 0x7) { 460 if ((batch->start | batch->used) & 0x7) {
544 DRM_ERROR("alignment"); 461 DRM_ERROR("alignment");
@@ -587,7 +504,6 @@ static int i915_dispatch_flip(struct drm_device * dev)
587 drm_i915_private_t *dev_priv = dev->dev_private; 504 drm_i915_private_t *dev_priv = dev->dev_private;
588 struct drm_i915_master_private *master_priv = 505 struct drm_i915_master_private *master_priv =
589 dev->primary->master->driver_priv; 506 dev->primary->master->driver_priv;
590 RING_LOCALS;
591 507
592 if (!master_priv->sarea_priv) 508 if (!master_priv->sarea_priv)
593 return -EINVAL; 509 return -EINVAL;
@@ -640,7 +556,8 @@ static int i915_quiescent(struct drm_device * dev)
640 drm_i915_private_t *dev_priv = dev->dev_private; 556 drm_i915_private_t *dev_priv = dev->dev_private;
641 557
642 i915_kernel_lost_context(dev); 558 i915_kernel_lost_context(dev);
643 return i915_wait_ring(dev, dev_priv->ring.Size - 8, __func__); 559 return intel_wait_ring_buffer(dev, &dev_priv->render_ring,
560 dev_priv->render_ring.size - 8);
644} 561}
645 562
646static int i915_flush_ioctl(struct drm_device *dev, void *data, 563static int i915_flush_ioctl(struct drm_device *dev, void *data,
@@ -827,6 +744,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
827 /* depends on GEM */ 744 /* depends on GEM */
828 value = dev_priv->has_gem; 745 value = dev_priv->has_gem;
829 break; 746 break;
747 case I915_PARAM_HAS_BSD:
748 value = HAS_BSD(dev);
749 break;
830 default: 750 default:
831 DRM_DEBUG_DRIVER("Unknown parameter %d\n", 751 DRM_DEBUG_DRIVER("Unknown parameter %d\n",
832 param->param); 752 param->param);
@@ -882,6 +802,7 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
882{ 802{
883 drm_i915_private_t *dev_priv = dev->dev_private; 803 drm_i915_private_t *dev_priv = dev->dev_private;
884 drm_i915_hws_addr_t *hws = data; 804 drm_i915_hws_addr_t *hws = data;
805 struct intel_ring_buffer *ring = &dev_priv->render_ring;
885 806
886 if (!I915_NEED_GFX_HWS(dev)) 807 if (!I915_NEED_GFX_HWS(dev))
887 return -EINVAL; 808 return -EINVAL;
@@ -898,7 +819,7 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
898 819
899 DRM_DEBUG_DRIVER("set status page addr 0x%08x\n", (u32)hws->addr); 820 DRM_DEBUG_DRIVER("set status page addr 0x%08x\n", (u32)hws->addr);
900 821
901 dev_priv->status_gfx_addr = hws->addr & (0x1ffff<<12); 822 ring->status_page.gfx_addr = hws->addr & (0x1ffff<<12);
902 823
903 dev_priv->hws_map.offset = dev->agp->base + hws->addr; 824 dev_priv->hws_map.offset = dev->agp->base + hws->addr;
904 dev_priv->hws_map.size = 4*1024; 825 dev_priv->hws_map.size = 4*1024;
@@ -909,19 +830,19 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
909 drm_core_ioremap_wc(&dev_priv->hws_map, dev); 830 drm_core_ioremap_wc(&dev_priv->hws_map, dev);
910 if (dev_priv->hws_map.handle == NULL) { 831 if (dev_priv->hws_map.handle == NULL) {
911 i915_dma_cleanup(dev); 832 i915_dma_cleanup(dev);
912 dev_priv->status_gfx_addr = 0; 833 ring->status_page.gfx_addr = 0;
913 DRM_ERROR("can not ioremap virtual address for" 834 DRM_ERROR("can not ioremap virtual address for"
914 " G33 hw status page\n"); 835 " G33 hw status page\n");
915 return -ENOMEM; 836 return -ENOMEM;
916 } 837 }
917 dev_priv->hw_status_page = dev_priv->hws_map.handle; 838 ring->status_page.page_addr = dev_priv->hws_map.handle;
839 memset(ring->status_page.page_addr, 0, PAGE_SIZE);
840 I915_WRITE(HWS_PGA, ring->status_page.gfx_addr);
918 841
919 memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
920 I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
921 DRM_DEBUG_DRIVER("load hws HWS_PGA with gfx mem 0x%x\n", 842 DRM_DEBUG_DRIVER("load hws HWS_PGA with gfx mem 0x%x\n",
922 dev_priv->status_gfx_addr); 843 ring->status_page.gfx_addr);
923 DRM_DEBUG_DRIVER("load hws at %p\n", 844 DRM_DEBUG_DRIVER("load hws at %p\n",
924 dev_priv->hw_status_page); 845 ring->status_page.page_addr);
925 return 0; 846 return 0;
926} 847}
927 848
@@ -1399,12 +1320,14 @@ static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_
1399 struct drm_device *dev = pci_get_drvdata(pdev); 1320 struct drm_device *dev = pci_get_drvdata(pdev);
1400 pm_message_t pmm = { .event = PM_EVENT_SUSPEND }; 1321 pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
1401 if (state == VGA_SWITCHEROO_ON) { 1322 if (state == VGA_SWITCHEROO_ON) {
1402 printk(KERN_INFO "i915: switched off\n"); 1323 printk(KERN_INFO "i915: switched on\n");
1403 /* i915 resume handler doesn't set to D0 */ 1324 /* i915 resume handler doesn't set to D0 */
1404 pci_set_power_state(dev->pdev, PCI_D0); 1325 pci_set_power_state(dev->pdev, PCI_D0);
1405 i915_resume(dev); 1326 i915_resume(dev);
1327 drm_kms_helper_poll_enable(dev);
1406 } else { 1328 } else {
1407 printk(KERN_ERR "i915: switched off\n"); 1329 printk(KERN_ERR "i915: switched off\n");
1330 drm_kms_helper_poll_disable(dev);
1408 i915_suspend(dev, pmm); 1331 i915_suspend(dev, pmm);
1409 } 1332 }
1410} 1333}
@@ -1479,19 +1402,19 @@ static int i915_load_modeset_init(struct drm_device *dev,
1479 /* if we have > 1 VGA cards, then disable the radeon VGA resources */ 1402 /* if we have > 1 VGA cards, then disable the radeon VGA resources */
1480 ret = vga_client_register(dev->pdev, dev, NULL, i915_vga_set_decode); 1403 ret = vga_client_register(dev->pdev, dev, NULL, i915_vga_set_decode);
1481 if (ret) 1404 if (ret)
1482 goto destroy_ringbuffer; 1405 goto cleanup_ringbuffer;
1483 1406
1484 ret = vga_switcheroo_register_client(dev->pdev, 1407 ret = vga_switcheroo_register_client(dev->pdev,
1485 i915_switcheroo_set_state, 1408 i915_switcheroo_set_state,
1486 i915_switcheroo_can_switch); 1409 i915_switcheroo_can_switch);
1487 if (ret) 1410 if (ret)
1488 goto destroy_ringbuffer; 1411 goto cleanup_vga_client;
1489 1412
1490 intel_modeset_init(dev); 1413 intel_modeset_init(dev);
1491 1414
1492 ret = drm_irq_install(dev); 1415 ret = drm_irq_install(dev);
1493 if (ret) 1416 if (ret)
1494 goto destroy_ringbuffer; 1417 goto cleanup_vga_switcheroo;
1495 1418
1496 /* Always safe in the mode setting case. */ 1419 /* Always safe in the mode setting case. */
1497 /* FIXME: do pre/post-mode set stuff in core KMS code */ 1420 /* FIXME: do pre/post-mode set stuff in core KMS code */
@@ -1503,11 +1426,20 @@ static int i915_load_modeset_init(struct drm_device *dev,
1503 1426
1504 I915_WRITE(INSTPM, (1 << 5) | (1 << 21)); 1427 I915_WRITE(INSTPM, (1 << 5) | (1 << 21));
1505 1428
1506 intel_fbdev_init(dev); 1429 ret = intel_fbdev_init(dev);
1430 if (ret)
1431 goto cleanup_irq;
1432
1507 drm_kms_helper_poll_init(dev); 1433 drm_kms_helper_poll_init(dev);
1508 return 0; 1434 return 0;
1509 1435
1510destroy_ringbuffer: 1436cleanup_irq:
1437 drm_irq_uninstall(dev);
1438cleanup_vga_switcheroo:
1439 vga_switcheroo_unregister_client(dev->pdev);
1440cleanup_vga_client:
1441 vga_client_register(dev->pdev, NULL, NULL, NULL);
1442cleanup_ringbuffer:
1511 mutex_lock(&dev->struct_mutex); 1443 mutex_lock(&dev->struct_mutex);
1512 i915_gem_cleanup_ringbuffer(dev); 1444 i915_gem_cleanup_ringbuffer(dev);
1513 mutex_unlock(&dev->struct_mutex); 1445 mutex_unlock(&dev->struct_mutex);
@@ -1539,14 +1471,11 @@ void i915_master_destroy(struct drm_device *dev, struct drm_master *master)
1539 master->driver_priv = NULL; 1471 master->driver_priv = NULL;
1540} 1472}
1541 1473
1542static void i915_get_mem_freq(struct drm_device *dev) 1474static void i915_pineview_get_mem_freq(struct drm_device *dev)
1543{ 1475{
1544 drm_i915_private_t *dev_priv = dev->dev_private; 1476 drm_i915_private_t *dev_priv = dev->dev_private;
1545 u32 tmp; 1477 u32 tmp;
1546 1478
1547 if (!IS_PINEVIEW(dev))
1548 return;
1549
1550 tmp = I915_READ(CLKCFG); 1479 tmp = I915_READ(CLKCFG);
1551 1480
1552 switch (tmp & CLKCFG_FSB_MASK) { 1481 switch (tmp & CLKCFG_FSB_MASK) {
@@ -1575,7 +1504,524 @@ static void i915_get_mem_freq(struct drm_device *dev)
1575 dev_priv->mem_freq = 800; 1504 dev_priv->mem_freq = 800;
1576 break; 1505 break;
1577 } 1506 }
1507
1508 /* detect pineview DDR3 setting */
1509 tmp = I915_READ(CSHRDDR3CTL);
1510 dev_priv->is_ddr3 = (tmp & CSHRDDR3CTL_DDR3) ? 1 : 0;
1511}
1512
1513static void i915_ironlake_get_mem_freq(struct drm_device *dev)
1514{
1515 drm_i915_private_t *dev_priv = dev->dev_private;
1516 u16 ddrpll, csipll;
1517
1518 ddrpll = I915_READ16(DDRMPLL1);
1519 csipll = I915_READ16(CSIPLL0);
1520
1521 switch (ddrpll & 0xff) {
1522 case 0xc:
1523 dev_priv->mem_freq = 800;
1524 break;
1525 case 0x10:
1526 dev_priv->mem_freq = 1066;
1527 break;
1528 case 0x14:
1529 dev_priv->mem_freq = 1333;
1530 break;
1531 case 0x18:
1532 dev_priv->mem_freq = 1600;
1533 break;
1534 default:
1535 DRM_DEBUG_DRIVER("unknown memory frequency 0x%02x\n",
1536 ddrpll & 0xff);
1537 dev_priv->mem_freq = 0;
1538 break;
1539 }
1540
1541 dev_priv->r_t = dev_priv->mem_freq;
1542
1543 switch (csipll & 0x3ff) {
1544 case 0x00c:
1545 dev_priv->fsb_freq = 3200;
1546 break;
1547 case 0x00e:
1548 dev_priv->fsb_freq = 3733;
1549 break;
1550 case 0x010:
1551 dev_priv->fsb_freq = 4266;
1552 break;
1553 case 0x012:
1554 dev_priv->fsb_freq = 4800;
1555 break;
1556 case 0x014:
1557 dev_priv->fsb_freq = 5333;
1558 break;
1559 case 0x016:
1560 dev_priv->fsb_freq = 5866;
1561 break;
1562 case 0x018:
1563 dev_priv->fsb_freq = 6400;
1564 break;
1565 default:
1566 DRM_DEBUG_DRIVER("unknown fsb frequency 0x%04x\n",
1567 csipll & 0x3ff);
1568 dev_priv->fsb_freq = 0;
1569 break;
1570 }
1571
1572 if (dev_priv->fsb_freq == 3200) {
1573 dev_priv->c_m = 0;
1574 } else if (dev_priv->fsb_freq > 3200 && dev_priv->fsb_freq <= 4800) {
1575 dev_priv->c_m = 1;
1576 } else {
1577 dev_priv->c_m = 2;
1578 }
1579}
1580
1581struct v_table {
1582 u8 vid;
1583 unsigned long vd; /* in .1 mil */
1584 unsigned long vm; /* in .1 mil */
1585 u8 pvid;
1586};
1587
1588static struct v_table v_table[] = {
1589 { 0, 16125, 15000, 0x7f, },
1590 { 1, 16000, 14875, 0x7e, },
1591 { 2, 15875, 14750, 0x7d, },
1592 { 3, 15750, 14625, 0x7c, },
1593 { 4, 15625, 14500, 0x7b, },
1594 { 5, 15500, 14375, 0x7a, },
1595 { 6, 15375, 14250, 0x79, },
1596 { 7, 15250, 14125, 0x78, },
1597 { 8, 15125, 14000, 0x77, },
1598 { 9, 15000, 13875, 0x76, },
1599 { 10, 14875, 13750, 0x75, },
1600 { 11, 14750, 13625, 0x74, },
1601 { 12, 14625, 13500, 0x73, },
1602 { 13, 14500, 13375, 0x72, },
1603 { 14, 14375, 13250, 0x71, },
1604 { 15, 14250, 13125, 0x70, },
1605 { 16, 14125, 13000, 0x6f, },
1606 { 17, 14000, 12875, 0x6e, },
1607 { 18, 13875, 12750, 0x6d, },
1608 { 19, 13750, 12625, 0x6c, },
1609 { 20, 13625, 12500, 0x6b, },
1610 { 21, 13500, 12375, 0x6a, },
1611 { 22, 13375, 12250, 0x69, },
1612 { 23, 13250, 12125, 0x68, },
1613 { 24, 13125, 12000, 0x67, },
1614 { 25, 13000, 11875, 0x66, },
1615 { 26, 12875, 11750, 0x65, },
1616 { 27, 12750, 11625, 0x64, },
1617 { 28, 12625, 11500, 0x63, },
1618 { 29, 12500, 11375, 0x62, },
1619 { 30, 12375, 11250, 0x61, },
1620 { 31, 12250, 11125, 0x60, },
1621 { 32, 12125, 11000, 0x5f, },
1622 { 33, 12000, 10875, 0x5e, },
1623 { 34, 11875, 10750, 0x5d, },
1624 { 35, 11750, 10625, 0x5c, },
1625 { 36, 11625, 10500, 0x5b, },
1626 { 37, 11500, 10375, 0x5a, },
1627 { 38, 11375, 10250, 0x59, },
1628 { 39, 11250, 10125, 0x58, },
1629 { 40, 11125, 10000, 0x57, },
1630 { 41, 11000, 9875, 0x56, },
1631 { 42, 10875, 9750, 0x55, },
1632 { 43, 10750, 9625, 0x54, },
1633 { 44, 10625, 9500, 0x53, },
1634 { 45, 10500, 9375, 0x52, },
1635 { 46, 10375, 9250, 0x51, },
1636 { 47, 10250, 9125, 0x50, },
1637 { 48, 10125, 9000, 0x4f, },
1638 { 49, 10000, 8875, 0x4e, },
1639 { 50, 9875, 8750, 0x4d, },
1640 { 51, 9750, 8625, 0x4c, },
1641 { 52, 9625, 8500, 0x4b, },
1642 { 53, 9500, 8375, 0x4a, },
1643 { 54, 9375, 8250, 0x49, },
1644 { 55, 9250, 8125, 0x48, },
1645 { 56, 9125, 8000, 0x47, },
1646 { 57, 9000, 7875, 0x46, },
1647 { 58, 8875, 7750, 0x45, },
1648 { 59, 8750, 7625, 0x44, },
1649 { 60, 8625, 7500, 0x43, },
1650 { 61, 8500, 7375, 0x42, },
1651 { 62, 8375, 7250, 0x41, },
1652 { 63, 8250, 7125, 0x40, },
1653 { 64, 8125, 7000, 0x3f, },
1654 { 65, 8000, 6875, 0x3e, },
1655 { 66, 7875, 6750, 0x3d, },
1656 { 67, 7750, 6625, 0x3c, },
1657 { 68, 7625, 6500, 0x3b, },
1658 { 69, 7500, 6375, 0x3a, },
1659 { 70, 7375, 6250, 0x39, },
1660 { 71, 7250, 6125, 0x38, },
1661 { 72, 7125, 6000, 0x37, },
1662 { 73, 7000, 5875, 0x36, },
1663 { 74, 6875, 5750, 0x35, },
1664 { 75, 6750, 5625, 0x34, },
1665 { 76, 6625, 5500, 0x33, },
1666 { 77, 6500, 5375, 0x32, },
1667 { 78, 6375, 5250, 0x31, },
1668 { 79, 6250, 5125, 0x30, },
1669 { 80, 6125, 5000, 0x2f, },
1670 { 81, 6000, 4875, 0x2e, },
1671 { 82, 5875, 4750, 0x2d, },
1672 { 83, 5750, 4625, 0x2c, },
1673 { 84, 5625, 4500, 0x2b, },
1674 { 85, 5500, 4375, 0x2a, },
1675 { 86, 5375, 4250, 0x29, },
1676 { 87, 5250, 4125, 0x28, },
1677 { 88, 5125, 4000, 0x27, },
1678 { 89, 5000, 3875, 0x26, },
1679 { 90, 4875, 3750, 0x25, },
1680 { 91, 4750, 3625, 0x24, },
1681 { 92, 4625, 3500, 0x23, },
1682 { 93, 4500, 3375, 0x22, },
1683 { 94, 4375, 3250, 0x21, },
1684 { 95, 4250, 3125, 0x20, },
1685 { 96, 4125, 3000, 0x1f, },
1686 { 97, 4125, 3000, 0x1e, },
1687 { 98, 4125, 3000, 0x1d, },
1688 { 99, 4125, 3000, 0x1c, },
1689 { 100, 4125, 3000, 0x1b, },
1690 { 101, 4125, 3000, 0x1a, },
1691 { 102, 4125, 3000, 0x19, },
1692 { 103, 4125, 3000, 0x18, },
1693 { 104, 4125, 3000, 0x17, },
1694 { 105, 4125, 3000, 0x16, },
1695 { 106, 4125, 3000, 0x15, },
1696 { 107, 4125, 3000, 0x14, },
1697 { 108, 4125, 3000, 0x13, },
1698 { 109, 4125, 3000, 0x12, },
1699 { 110, 4125, 3000, 0x11, },
1700 { 111, 4125, 3000, 0x10, },
1701 { 112, 4125, 3000, 0x0f, },
1702 { 113, 4125, 3000, 0x0e, },
1703 { 114, 4125, 3000, 0x0d, },
1704 { 115, 4125, 3000, 0x0c, },
1705 { 116, 4125, 3000, 0x0b, },
1706 { 117, 4125, 3000, 0x0a, },
1707 { 118, 4125, 3000, 0x09, },
1708 { 119, 4125, 3000, 0x08, },
1709 { 120, 1125, 0, 0x07, },
1710 { 121, 1000, 0, 0x06, },
1711 { 122, 875, 0, 0x05, },
1712 { 123, 750, 0, 0x04, },
1713 { 124, 625, 0, 0x03, },
1714 { 125, 500, 0, 0x02, },
1715 { 126, 375, 0, 0x01, },
1716 { 127, 0, 0, 0x00, },
1717};
1718
1719struct cparams {
1720 int i;
1721 int t;
1722 int m;
1723 int c;
1724};
1725
1726static struct cparams cparams[] = {
1727 { 1, 1333, 301, 28664 },
1728 { 1, 1066, 294, 24460 },
1729 { 1, 800, 294, 25192 },
1730 { 0, 1333, 276, 27605 },
1731 { 0, 1066, 276, 27605 },
1732 { 0, 800, 231, 23784 },
1733};
1734
1735unsigned long i915_chipset_val(struct drm_i915_private *dev_priv)
1736{
1737 u64 total_count, diff, ret;
1738 u32 count1, count2, count3, m = 0, c = 0;
1739 unsigned long now = jiffies_to_msecs(jiffies), diff1;
1740 int i;
1741
1742 diff1 = now - dev_priv->last_time1;
1743
1744 count1 = I915_READ(DMIEC);
1745 count2 = I915_READ(DDREC);
1746 count3 = I915_READ(CSIEC);
1747
1748 total_count = count1 + count2 + count3;
1749
1750 /* FIXME: handle per-counter overflow */
1751 if (total_count < dev_priv->last_count1) {
1752 diff = ~0UL - dev_priv->last_count1;
1753 diff += total_count;
1754 } else {
1755 diff = total_count - dev_priv->last_count1;
1756 }
1757
1758 for (i = 0; i < ARRAY_SIZE(cparams); i++) {
1759 if (cparams[i].i == dev_priv->c_m &&
1760 cparams[i].t == dev_priv->r_t) {
1761 m = cparams[i].m;
1762 c = cparams[i].c;
1763 break;
1764 }
1765 }
1766
1767 div_u64(diff, diff1);
1768 ret = ((m * diff) + c);
1769 div_u64(ret, 10);
1770
1771 dev_priv->last_count1 = total_count;
1772 dev_priv->last_time1 = now;
1773
1774 return ret;
1775}
1776
1777unsigned long i915_mch_val(struct drm_i915_private *dev_priv)
1778{
1779 unsigned long m, x, b;
1780 u32 tsfs;
1781
1782 tsfs = I915_READ(TSFS);
1783
1784 m = ((tsfs & TSFS_SLOPE_MASK) >> TSFS_SLOPE_SHIFT);
1785 x = I915_READ8(TR1);
1786
1787 b = tsfs & TSFS_INTR_MASK;
1788
1789 return ((m * x) / 127) - b;
1790}
1791
1792static unsigned long pvid_to_extvid(struct drm_i915_private *dev_priv, u8 pxvid)
1793{
1794 unsigned long val = 0;
1795 int i;
1796
1797 for (i = 0; i < ARRAY_SIZE(v_table); i++) {
1798 if (v_table[i].pvid == pxvid) {
1799 if (IS_MOBILE(dev_priv->dev))
1800 val = v_table[i].vm;
1801 else
1802 val = v_table[i].vd;
1803 }
1804 }
1805
1806 return val;
1807}
1808
1809void i915_update_gfx_val(struct drm_i915_private *dev_priv)
1810{
1811 struct timespec now, diff1;
1812 u64 diff;
1813 unsigned long diffms;
1814 u32 count;
1815
1816 getrawmonotonic(&now);
1817 diff1 = timespec_sub(now, dev_priv->last_time2);
1818
1819 /* Don't divide by 0 */
1820 diffms = diff1.tv_sec * 1000 + diff1.tv_nsec / 1000000;
1821 if (!diffms)
1822 return;
1823
1824 count = I915_READ(GFXEC);
1825
1826 if (count < dev_priv->last_count2) {
1827 diff = ~0UL - dev_priv->last_count2;
1828 diff += count;
1829 } else {
1830 diff = count - dev_priv->last_count2;
1831 }
1832
1833 dev_priv->last_count2 = count;
1834 dev_priv->last_time2 = now;
1835
1836 /* More magic constants... */
1837 diff = diff * 1181;
1838 div_u64(diff, diffms * 10);
1839 dev_priv->gfx_power = diff;
1840}
1841
1842unsigned long i915_gfx_val(struct drm_i915_private *dev_priv)
1843{
1844 unsigned long t, corr, state1, corr2, state2;
1845 u32 pxvid, ext_v;
1846
1847 pxvid = I915_READ(PXVFREQ_BASE + (dev_priv->cur_delay * 4));
1848 pxvid = (pxvid >> 24) & 0x7f;
1849 ext_v = pvid_to_extvid(dev_priv, pxvid);
1850
1851 state1 = ext_v;
1852
1853 t = i915_mch_val(dev_priv);
1854
1855 /* Revel in the empirically derived constants */
1856
1857 /* Correction factor in 1/100000 units */
1858 if (t > 80)
1859 corr = ((t * 2349) + 135940);
1860 else if (t >= 50)
1861 corr = ((t * 964) + 29317);
1862 else /* < 50 */
1863 corr = ((t * 301) + 1004);
1864
1865 corr = corr * ((150142 * state1) / 10000 - 78642);
1866 corr /= 100000;
1867 corr2 = (corr * dev_priv->corr);
1868
1869 state2 = (corr2 * state1) / 10000;
1870 state2 /= 100; /* convert to mW */
1871
1872 i915_update_gfx_val(dev_priv);
1873
1874 return dev_priv->gfx_power + state2;
1875}
1876
1877/* Global for IPS driver to get at the current i915 device */
1878static struct drm_i915_private *i915_mch_dev;
1879/*
1880 * Lock protecting IPS related data structures
1881 * - i915_mch_dev
1882 * - dev_priv->max_delay
1883 * - dev_priv->min_delay
1884 * - dev_priv->fmax
1885 * - dev_priv->gpu_busy
1886 */
1887DEFINE_SPINLOCK(mchdev_lock);
1888
1889/**
1890 * i915_read_mch_val - return value for IPS use
1891 *
1892 * Calculate and return a value for the IPS driver to use when deciding whether
1893 * we have thermal and power headroom to increase CPU or GPU power budget.
1894 */
1895unsigned long i915_read_mch_val(void)
1896{
1897 struct drm_i915_private *dev_priv;
1898 unsigned long chipset_val, graphics_val, ret = 0;
1899
1900 spin_lock(&mchdev_lock);
1901 if (!i915_mch_dev)
1902 goto out_unlock;
1903 dev_priv = i915_mch_dev;
1904
1905 chipset_val = i915_chipset_val(dev_priv);
1906 graphics_val = i915_gfx_val(dev_priv);
1907
1908 ret = chipset_val + graphics_val;
1909
1910out_unlock:
1911 spin_unlock(&mchdev_lock);
1912
1913 return ret;
1914}
1915EXPORT_SYMBOL_GPL(i915_read_mch_val);
1916
1917/**
1918 * i915_gpu_raise - raise GPU frequency limit
1919 *
1920 * Raise the limit; IPS indicates we have thermal headroom.
1921 */
1922bool i915_gpu_raise(void)
1923{
1924 struct drm_i915_private *dev_priv;
1925 bool ret = true;
1926
1927 spin_lock(&mchdev_lock);
1928 if (!i915_mch_dev) {
1929 ret = false;
1930 goto out_unlock;
1931 }
1932 dev_priv = i915_mch_dev;
1933
1934 if (dev_priv->max_delay > dev_priv->fmax)
1935 dev_priv->max_delay--;
1936
1937out_unlock:
1938 spin_unlock(&mchdev_lock);
1939
1940 return ret;
1941}
1942EXPORT_SYMBOL_GPL(i915_gpu_raise);
1943
1944/**
1945 * i915_gpu_lower - lower GPU frequency limit
1946 *
1947 * IPS indicates we're close to a thermal limit, so throttle back the GPU
1948 * frequency maximum.
1949 */
1950bool i915_gpu_lower(void)
1951{
1952 struct drm_i915_private *dev_priv;
1953 bool ret = true;
1954
1955 spin_lock(&mchdev_lock);
1956 if (!i915_mch_dev) {
1957 ret = false;
1958 goto out_unlock;
1959 }
1960 dev_priv = i915_mch_dev;
1961
1962 if (dev_priv->max_delay < dev_priv->min_delay)
1963 dev_priv->max_delay++;
1964
1965out_unlock:
1966 spin_unlock(&mchdev_lock);
1967
1968 return ret;
1578} 1969}
1970EXPORT_SYMBOL_GPL(i915_gpu_lower);
1971
1972/**
1973 * i915_gpu_busy - indicate GPU business to IPS
1974 *
1975 * Tell the IPS driver whether or not the GPU is busy.
1976 */
1977bool i915_gpu_busy(void)
1978{
1979 struct drm_i915_private *dev_priv;
1980 bool ret = false;
1981
1982 spin_lock(&mchdev_lock);
1983 if (!i915_mch_dev)
1984 goto out_unlock;
1985 dev_priv = i915_mch_dev;
1986
1987 ret = dev_priv->busy;
1988
1989out_unlock:
1990 spin_unlock(&mchdev_lock);
1991
1992 return ret;
1993}
1994EXPORT_SYMBOL_GPL(i915_gpu_busy);
1995
1996/**
1997 * i915_gpu_turbo_disable - disable graphics turbo
1998 *
1999 * Disable graphics turbo by resetting the max frequency and setting the
2000 * current frequency to the default.
2001 */
2002bool i915_gpu_turbo_disable(void)
2003{
2004 struct drm_i915_private *dev_priv;
2005 bool ret = true;
2006
2007 spin_lock(&mchdev_lock);
2008 if (!i915_mch_dev) {
2009 ret = false;
2010 goto out_unlock;
2011 }
2012 dev_priv = i915_mch_dev;
2013
2014 dev_priv->max_delay = dev_priv->fstart;
2015
2016 if (!ironlake_set_drps(dev_priv->dev, dev_priv->fstart))
2017 ret = false;
2018
2019out_unlock:
2020 spin_unlock(&mchdev_lock);
2021
2022 return ret;
2023}
2024EXPORT_SYMBOL_GPL(i915_gpu_turbo_disable);
1579 2025
1580/** 2026/**
1581 * i915_driver_load - setup chip and create an initial config 2027 * i915_driver_load - setup chip and create an initial config
@@ -1594,7 +2040,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
1594 resource_size_t base, size; 2040 resource_size_t base, size;
1595 int ret = 0, mmio_bar; 2041 int ret = 0, mmio_bar;
1596 uint32_t agp_size, prealloc_size, prealloc_start; 2042 uint32_t agp_size, prealloc_size, prealloc_start;
1597
1598 /* i915 has 4 more counters */ 2043 /* i915 has 4 more counters */
1599 dev->counters += 4; 2044 dev->counters += 4;
1600 dev->types[6] = _DRM_STAT_IRQ; 2045 dev->types[6] = _DRM_STAT_IRQ;
@@ -1672,6 +2117,13 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
1672 dev_priv->has_gem = 0; 2117 dev_priv->has_gem = 0;
1673 } 2118 }
1674 2119
2120 if (dev_priv->has_gem == 0 &&
2121 drm_core_check_feature(dev, DRIVER_MODESET)) {
2122 DRM_ERROR("kernel modesetting requires GEM, disabling driver.\n");
2123 ret = -ENODEV;
2124 goto out_iomapfree;
2125 }
2126
1675 dev->driver->get_vblank_counter = i915_get_vblank_counter; 2127 dev->driver->get_vblank_counter = i915_get_vblank_counter;
1676 dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ 2128 dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
1677 if (IS_G4X(dev) || IS_IRONLAKE(dev) || IS_GEN6(dev)) { 2129 if (IS_G4X(dev) || IS_IRONLAKE(dev) || IS_GEN6(dev)) {
@@ -1691,7 +2143,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
1691 goto out_workqueue_free; 2143 goto out_workqueue_free;
1692 } 2144 }
1693 2145
1694 i915_get_mem_freq(dev); 2146 if (IS_PINEVIEW(dev))
2147 i915_pineview_get_mem_freq(dev);
2148 else if (IS_IRONLAKE(dev))
2149 i915_ironlake_get_mem_freq(dev);
1695 2150
1696 /* On the 945G/GM, the chipset reports the MSI capability on the 2151 /* On the 945G/GM, the chipset reports the MSI capability on the
1697 * integrated graphics even though the support isn't actually there 2152 * integrated graphics even though the support isn't actually there
@@ -1709,7 +2164,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
1709 2164
1710 spin_lock_init(&dev_priv->user_irq_lock); 2165 spin_lock_init(&dev_priv->user_irq_lock);
1711 spin_lock_init(&dev_priv->error_lock); 2166 spin_lock_init(&dev_priv->error_lock);
1712 dev_priv->user_irq_refcount = 0;
1713 dev_priv->trace_irq_seqno = 0; 2167 dev_priv->trace_irq_seqno = 0;
1714 2168
1715 ret = drm_vblank_init(dev, I915_NUM_PIPE); 2169 ret = drm_vblank_init(dev, I915_NUM_PIPE);
@@ -1738,6 +2192,12 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
1738 2192
1739 setup_timer(&dev_priv->hangcheck_timer, i915_hangcheck_elapsed, 2193 setup_timer(&dev_priv->hangcheck_timer, i915_hangcheck_elapsed,
1740 (unsigned long) dev); 2194 (unsigned long) dev);
2195
2196 spin_lock(&mchdev_lock);
2197 i915_mch_dev = dev_priv;
2198 dev_priv->mchdev_lock = &mchdev_lock;
2199 spin_unlock(&mchdev_lock);
2200
1741 return 0; 2201 return 0;
1742 2202
1743out_workqueue_free: 2203out_workqueue_free:
@@ -1759,6 +2219,10 @@ int i915_driver_unload(struct drm_device *dev)
1759 2219
1760 i915_destroy_error_state(dev); 2220 i915_destroy_error_state(dev);
1761 2221
2222 spin_lock(&mchdev_lock);
2223 i915_mch_dev = NULL;
2224 spin_unlock(&mchdev_lock);
2225
1762 destroy_workqueue(dev_priv->wq); 2226 destroy_workqueue(dev_priv->wq);
1763 del_timer_sync(&dev_priv->hangcheck_timer); 2227 del_timer_sync(&dev_priv->hangcheck_timer);
1764 2228
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 5c51e45ab68d..423dc90c1e20 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -60,95 +60,95 @@ extern int intel_agp_enabled;
60 .subdevice = PCI_ANY_ID, \ 60 .subdevice = PCI_ANY_ID, \
61 .driver_data = (unsigned long) info } 61 .driver_data = (unsigned long) info }
62 62
63const static struct intel_device_info intel_i830_info = { 63static const struct intel_device_info intel_i830_info = {
64 .is_i8xx = 1, .is_mobile = 1, .cursor_needs_physical = 1, 64 .is_i8xx = 1, .is_mobile = 1, .cursor_needs_physical = 1,
65}; 65};
66 66
67const static struct intel_device_info intel_845g_info = { 67static const struct intel_device_info intel_845g_info = {
68 .is_i8xx = 1, 68 .is_i8xx = 1,
69}; 69};
70 70
71const static struct intel_device_info intel_i85x_info = { 71static const struct intel_device_info intel_i85x_info = {
72 .is_i8xx = 1, .is_i85x = 1, .is_mobile = 1, 72 .is_i8xx = 1, .is_i85x = 1, .is_mobile = 1,
73 .cursor_needs_physical = 1, 73 .cursor_needs_physical = 1,
74}; 74};
75 75
76const static struct intel_device_info intel_i865g_info = { 76static const struct intel_device_info intel_i865g_info = {
77 .is_i8xx = 1, 77 .is_i8xx = 1,
78}; 78};
79 79
80const static struct intel_device_info intel_i915g_info = { 80static const struct intel_device_info intel_i915g_info = {
81 .is_i915g = 1, .is_i9xx = 1, .cursor_needs_physical = 1, 81 .is_i915g = 1, .is_i9xx = 1, .cursor_needs_physical = 1,
82}; 82};
83const static struct intel_device_info intel_i915gm_info = { 83static const struct intel_device_info intel_i915gm_info = {
84 .is_i9xx = 1, .is_mobile = 1, 84 .is_i9xx = 1, .is_mobile = 1,
85 .cursor_needs_physical = 1, 85 .cursor_needs_physical = 1,
86}; 86};
87const static struct intel_device_info intel_i945g_info = { 87static const struct intel_device_info intel_i945g_info = {
88 .is_i9xx = 1, .has_hotplug = 1, .cursor_needs_physical = 1, 88 .is_i9xx = 1, .has_hotplug = 1, .cursor_needs_physical = 1,
89}; 89};
90const static struct intel_device_info intel_i945gm_info = { 90static const struct intel_device_info intel_i945gm_info = {
91 .is_i945gm = 1, .is_i9xx = 1, .is_mobile = 1, 91 .is_i945gm = 1, .is_i9xx = 1, .is_mobile = 1,
92 .has_hotplug = 1, .cursor_needs_physical = 1, 92 .has_hotplug = 1, .cursor_needs_physical = 1,
93}; 93};
94 94
95const static struct intel_device_info intel_i965g_info = { 95static const struct intel_device_info intel_i965g_info = {
96 .is_i965g = 1, .is_i9xx = 1, .has_hotplug = 1, 96 .is_i965g = 1, .is_i9xx = 1, .has_hotplug = 1,
97}; 97};
98 98
99const static struct intel_device_info intel_i965gm_info = { 99static const struct intel_device_info intel_i965gm_info = {
100 .is_i965g = 1, .is_mobile = 1, .is_i965gm = 1, .is_i9xx = 1, 100 .is_i965g = 1, .is_mobile = 1, .is_i965gm = 1, .is_i9xx = 1,
101 .is_mobile = 1, .has_fbc = 1, .has_rc6 = 1, 101 .is_mobile = 1, .has_fbc = 1, .has_rc6 = 1,
102 .has_hotplug = 1, 102 .has_hotplug = 1,
103}; 103};
104 104
105const static struct intel_device_info intel_g33_info = { 105static const struct intel_device_info intel_g33_info = {
106 .is_g33 = 1, .is_i9xx = 1, .need_gfx_hws = 1, 106 .is_g33 = 1, .is_i9xx = 1, .need_gfx_hws = 1,
107 .has_hotplug = 1, 107 .has_hotplug = 1,
108}; 108};
109 109
110const static struct intel_device_info intel_g45_info = { 110static const struct intel_device_info intel_g45_info = {
111 .is_i965g = 1, .is_g4x = 1, .is_i9xx = 1, .need_gfx_hws = 1, 111 .is_i965g = 1, .is_g4x = 1, .is_i9xx = 1, .need_gfx_hws = 1,
112 .has_pipe_cxsr = 1, 112 .has_pipe_cxsr = 1,
113 .has_hotplug = 1, 113 .has_hotplug = 1,
114}; 114};
115 115
116const static struct intel_device_info intel_gm45_info = { 116static const struct intel_device_info intel_gm45_info = {
117 .is_i965g = 1, .is_mobile = 1, .is_g4x = 1, .is_i9xx = 1, 117 .is_i965g = 1, .is_mobile = 1, .is_g4x = 1, .is_i9xx = 1,
118 .is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1, 118 .is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1,
119 .has_pipe_cxsr = 1, 119 .has_pipe_cxsr = 1,
120 .has_hotplug = 1, 120 .has_hotplug = 1,
121}; 121};
122 122
123const static struct intel_device_info intel_pineview_info = { 123static const struct intel_device_info intel_pineview_info = {
124 .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .is_i9xx = 1, 124 .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .is_i9xx = 1,
125 .need_gfx_hws = 1, 125 .need_gfx_hws = 1,
126 .has_hotplug = 1, 126 .has_hotplug = 1,
127}; 127};
128 128
129const static struct intel_device_info intel_ironlake_d_info = { 129static const struct intel_device_info intel_ironlake_d_info = {
130 .is_ironlake = 1, .is_i965g = 1, .is_i9xx = 1, .need_gfx_hws = 1, 130 .is_ironlake = 1, .is_i965g = 1, .is_i9xx = 1, .need_gfx_hws = 1,
131 .has_pipe_cxsr = 1, 131 .has_pipe_cxsr = 1,
132 .has_hotplug = 1, 132 .has_hotplug = 1,
133}; 133};
134 134
135const static struct intel_device_info intel_ironlake_m_info = { 135static const struct intel_device_info intel_ironlake_m_info = {
136 .is_ironlake = 1, .is_mobile = 1, .is_i965g = 1, .is_i9xx = 1, 136 .is_ironlake = 1, .is_mobile = 1, .is_i965g = 1, .is_i9xx = 1,
137 .need_gfx_hws = 1, .has_rc6 = 1, 137 .need_gfx_hws = 1, .has_rc6 = 1,
138 .has_hotplug = 1, 138 .has_hotplug = 1,
139}; 139};
140 140
141const static struct intel_device_info intel_sandybridge_d_info = { 141static const struct intel_device_info intel_sandybridge_d_info = {
142 .is_i965g = 1, .is_i9xx = 1, .need_gfx_hws = 1, 142 .is_i965g = 1, .is_i9xx = 1, .need_gfx_hws = 1,
143 .has_hotplug = 1, .is_gen6 = 1, 143 .has_hotplug = 1, .is_gen6 = 1,
144}; 144};
145 145
146const static struct intel_device_info intel_sandybridge_m_info = { 146static const struct intel_device_info intel_sandybridge_m_info = {
147 .is_i965g = 1, .is_mobile = 1, .is_i9xx = 1, .need_gfx_hws = 1, 147 .is_i965g = 1, .is_mobile = 1, .is_i9xx = 1, .need_gfx_hws = 1,
148 .has_hotplug = 1, .is_gen6 = 1, 148 .has_hotplug = 1, .is_gen6 = 1,
149}; 149};
150 150
151const static struct pci_device_id pciidlist[] = { 151static const struct pci_device_id pciidlist[] = {
152 INTEL_VGA_DEVICE(0x3577, &intel_i830_info), 152 INTEL_VGA_DEVICE(0x3577, &intel_i830_info),
153 INTEL_VGA_DEVICE(0x2562, &intel_845g_info), 153 INTEL_VGA_DEVICE(0x2562, &intel_845g_info),
154 INTEL_VGA_DEVICE(0x3582, &intel_i85x_info), 154 INTEL_VGA_DEVICE(0x3582, &intel_i85x_info),
@@ -340,7 +340,7 @@ int i965_reset(struct drm_device *dev, u8 flags)
340 /* 340 /*
341 * Clear request list 341 * Clear request list
342 */ 342 */
343 i915_gem_retire_requests(dev); 343 i915_gem_retire_requests(dev, &dev_priv->render_ring);
344 344
345 if (need_display) 345 if (need_display)
346 i915_save_display(dev); 346 i915_save_display(dev);
@@ -370,6 +370,7 @@ int i965_reset(struct drm_device *dev, u8 flags)
370 } 370 }
371 } else { 371 } else {
372 DRM_ERROR("Error occurred. Don't know how to reset this chip.\n"); 372 DRM_ERROR("Error occurred. Don't know how to reset this chip.\n");
373 mutex_unlock(&dev->struct_mutex);
373 return -ENODEV; 374 return -ENODEV;
374 } 375 }
375 376
@@ -388,33 +389,10 @@ int i965_reset(struct drm_device *dev, u8 flags)
388 * switched away). 389 * switched away).
389 */ 390 */
390 if (drm_core_check_feature(dev, DRIVER_MODESET) || 391 if (drm_core_check_feature(dev, DRIVER_MODESET) ||
391 !dev_priv->mm.suspended) { 392 !dev_priv->mm.suspended) {
392 drm_i915_ring_buffer_t *ring = &dev_priv->ring; 393 struct intel_ring_buffer *ring = &dev_priv->render_ring;
393 struct drm_gem_object *obj = ring->ring_obj;
394 struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
395 dev_priv->mm.suspended = 0; 394 dev_priv->mm.suspended = 0;
396 395 ring->init(dev, ring);
397 /* Stop the ring if it's running. */
398 I915_WRITE(PRB0_CTL, 0);
399 I915_WRITE(PRB0_TAIL, 0);
400 I915_WRITE(PRB0_HEAD, 0);
401
402 /* Initialize the ring. */
403 I915_WRITE(PRB0_START, obj_priv->gtt_offset);
404 I915_WRITE(PRB0_CTL,
405 ((obj->size - 4096) & RING_NR_PAGES) |
406 RING_NO_REPORT |
407 RING_VALID);
408 if (!drm_core_check_feature(dev, DRIVER_MODESET))
409 i915_kernel_lost_context(dev);
410 else {
411 ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
412 ring->tail = I915_READ(PRB0_TAIL) & TAIL_ADDR;
413 ring->space = ring->head - (ring->tail + 8);
414 if (ring->space < 0)
415 ring->space += ring->Size;
416 }
417
418 mutex_unlock(&dev->struct_mutex); 396 mutex_unlock(&dev->struct_mutex);
419 drm_irq_uninstall(dev); 397 drm_irq_uninstall(dev);
420 drm_irq_install(dev); 398 drm_irq_install(dev);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 7f797ef1ab39..276583159847 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -32,6 +32,7 @@
32 32
33#include "i915_reg.h" 33#include "i915_reg.h"
34#include "intel_bios.h" 34#include "intel_bios.h"
35#include "intel_ringbuffer.h"
35#include <linux/io-mapping.h> 36#include <linux/io-mapping.h>
36 37
37/* General customization: 38/* General customization:
@@ -55,6 +56,8 @@ enum plane {
55 56
56#define I915_NUM_PIPE 2 57#define I915_NUM_PIPE 2
57 58
59#define I915_GEM_GPU_DOMAINS (~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT))
60
58/* Interface history: 61/* Interface history:
59 * 62 *
60 * 1.1: Original. 63 * 1.1: Original.
@@ -89,16 +92,6 @@ struct drm_i915_gem_phys_object {
89 struct drm_gem_object *cur_obj; 92 struct drm_gem_object *cur_obj;
90}; 93};
91 94
92typedef struct _drm_i915_ring_buffer {
93 unsigned long Size;
94 u8 *virtual_start;
95 int head;
96 int tail;
97 int space;
98 drm_local_map_t map;
99 struct drm_gem_object *ring_obj;
100} drm_i915_ring_buffer_t;
101
102struct mem_block { 95struct mem_block {
103 struct mem_block *next; 96 struct mem_block *next;
104 struct mem_block *prev; 97 struct mem_block *prev;
@@ -241,17 +234,15 @@ typedef struct drm_i915_private {
241 void __iomem *regs; 234 void __iomem *regs;
242 235
243 struct pci_dev *bridge_dev; 236 struct pci_dev *bridge_dev;
244 drm_i915_ring_buffer_t ring; 237 struct intel_ring_buffer render_ring;
238 struct intel_ring_buffer bsd_ring;
245 239
246 drm_dma_handle_t *status_page_dmah; 240 drm_dma_handle_t *status_page_dmah;
247 void *hw_status_page;
248 void *seqno_page; 241 void *seqno_page;
249 dma_addr_t dma_status_page; 242 dma_addr_t dma_status_page;
250 uint32_t counter; 243 uint32_t counter;
251 unsigned int status_gfx_addr;
252 unsigned int seqno_gfx_addr; 244 unsigned int seqno_gfx_addr;
253 drm_local_map_t hws_map; 245 drm_local_map_t hws_map;
254 struct drm_gem_object *hws_obj;
255 struct drm_gem_object *seqno_obj; 246 struct drm_gem_object *seqno_obj;
256 struct drm_gem_object *pwrctx; 247 struct drm_gem_object *pwrctx;
257 248
@@ -267,8 +258,6 @@ typedef struct drm_i915_private {
267 atomic_t irq_received; 258 atomic_t irq_received;
268 /** Protects user_irq_refcount and irq_mask_reg */ 259 /** Protects user_irq_refcount and irq_mask_reg */
269 spinlock_t user_irq_lock; 260 spinlock_t user_irq_lock;
270 /** Refcount for i915_user_irq_get() versus i915_user_irq_put(). */
271 int user_irq_refcount;
272 u32 trace_irq_seqno; 261 u32 trace_irq_seqno;
273 /** Cached value of IMR to avoid reads in updating the bitfield */ 262 /** Cached value of IMR to avoid reads in updating the bitfield */
274 u32 irq_mask_reg; 263 u32 irq_mask_reg;
@@ -289,6 +278,7 @@ typedef struct drm_i915_private {
289 struct mem_block *agp_heap; 278 struct mem_block *agp_heap;
290 unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds; 279 unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds;
291 int vblank_pipe; 280 int vblank_pipe;
281 int num_pipe;
292 282
293 /* For hangcheck timer */ 283 /* For hangcheck timer */
294#define DRM_I915_HANGCHECK_PERIOD 75 /* in jiffies */ 284#define DRM_I915_HANGCHECK_PERIOD 75 /* in jiffies */
@@ -334,7 +324,7 @@ typedef struct drm_i915_private {
334 int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */ 324 int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */
335 int num_fence_regs; /* 8 on pre-965, 16 otherwise */ 325 int num_fence_regs; /* 8 on pre-965, 16 otherwise */
336 326
337 unsigned int fsb_freq, mem_freq; 327 unsigned int fsb_freq, mem_freq, is_ddr3;
338 328
339 spinlock_t error_lock; 329 spinlock_t error_lock;
340 struct drm_i915_error_state *first_error; 330 struct drm_i915_error_state *first_error;
@@ -514,18 +504,7 @@ typedef struct drm_i915_private {
514 */ 504 */
515 struct list_head shrink_list; 505 struct list_head shrink_list;
516 506
517 /**
518 * List of objects currently involved in rendering from the
519 * ringbuffer.
520 *
521 * Includes buffers having the contents of their GPU caches
522 * flushed, not necessarily primitives. last_rendering_seqno
523 * represents when the rendering involved will be completed.
524 *
525 * A reference is held on the buffer while on this list.
526 */
527 spinlock_t active_list_lock; 507 spinlock_t active_list_lock;
528 struct list_head active_list;
529 508
530 /** 509 /**
531 * List of objects which are not in the ringbuffer but which 510 * List of objects which are not in the ringbuffer but which
@@ -563,12 +542,6 @@ typedef struct drm_i915_private {
563 struct list_head fence_list; 542 struct list_head fence_list;
564 543
565 /** 544 /**
566 * List of breadcrumbs associated with GPU requests currently
567 * outstanding.
568 */
569 struct list_head request_list;
570
571 /**
572 * We leave the user IRQ off as much as possible, 545 * We leave the user IRQ off as much as possible,
573 * but this means that requests will finish and never 546 * but this means that requests will finish and never
574 * be retired once the system goes idle. Set a timer to 547 * be retired once the system goes idle. Set a timer to
@@ -644,6 +617,18 @@ typedef struct drm_i915_private {
644 u8 cur_delay; 617 u8 cur_delay;
645 u8 min_delay; 618 u8 min_delay;
646 u8 max_delay; 619 u8 max_delay;
620 u8 fmax;
621 u8 fstart;
622
623 u64 last_count1;
624 unsigned long last_time1;
625 u64 last_count2;
626 struct timespec last_time2;
627 unsigned long gfx_power;
628 int c_m;
629 int r_t;
630 u8 corr;
631 spinlock_t *mchdev_lock;
647 632
648 enum no_fbc_reason no_fbc_reason; 633 enum no_fbc_reason no_fbc_reason;
649 634
@@ -671,19 +656,64 @@ struct drm_i915_gem_object {
671 * (has pending rendering), and is not set if it's on inactive (ready 656 * (has pending rendering), and is not set if it's on inactive (ready
672 * to be unbound). 657 * to be unbound).
673 */ 658 */
674 int active; 659 unsigned int active : 1;
675 660
676 /** 661 /**
677 * This is set if the object has been written to since last bound 662 * This is set if the object has been written to since last bound
678 * to the GTT 663 * to the GTT
679 */ 664 */
680 int dirty; 665 unsigned int dirty : 1;
666
667 /**
668 * Fence register bits (if any) for this object. Will be set
669 * as needed when mapped into the GTT.
670 * Protected by dev->struct_mutex.
671 *
672 * Size: 4 bits for 16 fences + sign (for FENCE_REG_NONE)
673 */
674 int fence_reg : 5;
675
676 /**
677 * Used for checking the object doesn't appear more than once
678 * in an execbuffer object list.
679 */
680 unsigned int in_execbuffer : 1;
681
682 /**
683 * Advice: are the backing pages purgeable?
684 */
685 unsigned int madv : 2;
686
687 /**
688 * Refcount for the pages array. With the current locking scheme, there
689 * are at most two concurrent users: Binding a bo to the gtt and
690 * pwrite/pread using physical addresses. So two bits for a maximum
691 * of two users are enough.
692 */
693 unsigned int pages_refcount : 2;
694#define DRM_I915_GEM_OBJECT_MAX_PAGES_REFCOUNT 0x3
695
696 /**
697 * Current tiling mode for the object.
698 */
699 unsigned int tiling_mode : 2;
700
701 /** How many users have pinned this object in GTT space. The following
702 * users can each hold at most one reference: pwrite/pread, pin_ioctl
703 * (via user_pin_count), execbuffer (objects are not allowed multiple
704 * times for the same batchbuffer), and the framebuffer code. When
705 * switching/pageflipping, the framebuffer code has at most two buffers
706 * pinned per crtc.
707 *
708 * In the worst case this is 1 + 1 + 1 + 2*2 = 7. That would fit into 3
709 * bits with absolutely no headroom. So use 4 bits. */
710 int pin_count : 4;
711#define DRM_I915_GEM_OBJECT_MAX_PIN_COUNT 0xf
681 712
682 /** AGP memory structure for our GTT binding. */ 713 /** AGP memory structure for our GTT binding. */
683 DRM_AGP_MEM *agp_mem; 714 DRM_AGP_MEM *agp_mem;
684 715
685 struct page **pages; 716 struct page **pages;
686 int pages_refcount;
687 717
688 /** 718 /**
689 * Current offset of the object in GTT space. 719 * Current offset of the object in GTT space.
@@ -692,26 +722,18 @@ struct drm_i915_gem_object {
692 */ 722 */
693 uint32_t gtt_offset; 723 uint32_t gtt_offset;
694 724
725 /* Which ring is refering to is this object */
726 struct intel_ring_buffer *ring;
727
695 /** 728 /**
696 * Fake offset for use by mmap(2) 729 * Fake offset for use by mmap(2)
697 */ 730 */
698 uint64_t mmap_offset; 731 uint64_t mmap_offset;
699 732
700 /**
701 * Fence register bits (if any) for this object. Will be set
702 * as needed when mapped into the GTT.
703 * Protected by dev->struct_mutex.
704 */
705 int fence_reg;
706
707 /** How many users have pinned this object in GTT space */
708 int pin_count;
709
710 /** Breadcrumb of last rendering to the buffer. */ 733 /** Breadcrumb of last rendering to the buffer. */
711 uint32_t last_rendering_seqno; 734 uint32_t last_rendering_seqno;
712 735
713 /** Current tiling mode for the object. */ 736 /** Current tiling stride for the object, if it's tiled. */
714 uint32_t tiling_mode;
715 uint32_t stride; 737 uint32_t stride;
716 738
717 /** Record of address bit 17 of each page at last unbind. */ 739 /** Record of address bit 17 of each page at last unbind. */
@@ -734,17 +756,6 @@ struct drm_i915_gem_object {
734 struct drm_i915_gem_phys_object *phys_obj; 756 struct drm_i915_gem_phys_object *phys_obj;
735 757
736 /** 758 /**
737 * Used for checking the object doesn't appear more than once
738 * in an execbuffer object list.
739 */
740 int in_execbuffer;
741
742 /**
743 * Advice: are the backing pages purgeable?
744 */
745 int madv;
746
747 /**
748 * Number of crtcs where this object is currently the fb, but 759 * Number of crtcs where this object is currently the fb, but
749 * will be page flipped away on the next vblank. When it 760 * will be page flipped away on the next vblank. When it
750 * reaches 0, dev_priv->pending_flip_queue will be woken up. 761 * reaches 0, dev_priv->pending_flip_queue will be woken up.
@@ -765,6 +776,9 @@ struct drm_i915_gem_object {
765 * an emission time with seqnos for tracking how far ahead of the GPU we are. 776 * an emission time with seqnos for tracking how far ahead of the GPU we are.
766 */ 777 */
767struct drm_i915_gem_request { 778struct drm_i915_gem_request {
779 /** On Which ring this request was generated */
780 struct intel_ring_buffer *ring;
781
768 /** GEM sequence number associated with this request. */ 782 /** GEM sequence number associated with this request. */
769 uint32_t seqno; 783 uint32_t seqno;
770 784
@@ -821,6 +835,11 @@ extern int i915_emit_box(struct drm_device *dev,
821 struct drm_clip_rect *boxes, 835 struct drm_clip_rect *boxes,
822 int i, int DR1, int DR4); 836 int i, int DR1, int DR4);
823extern int i965_reset(struct drm_device *dev, u8 flags); 837extern int i965_reset(struct drm_device *dev, u8 flags);
838extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv);
839extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv);
840extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv);
841extern void i915_update_gfx_val(struct drm_i915_private *dev_priv);
842
824 843
825/* i915_irq.c */ 844/* i915_irq.c */
826void i915_hangcheck_elapsed(unsigned long data); 845void i915_hangcheck_elapsed(unsigned long data);
@@ -829,9 +848,7 @@ extern int i915_irq_emit(struct drm_device *dev, void *data,
829 struct drm_file *file_priv); 848 struct drm_file *file_priv);
830extern int i915_irq_wait(struct drm_device *dev, void *data, 849extern int i915_irq_wait(struct drm_device *dev, void *data,
831 struct drm_file *file_priv); 850 struct drm_file *file_priv);
832void i915_user_irq_get(struct drm_device *dev);
833void i915_trace_irq_get(struct drm_device *dev, u32 seqno); 851void i915_trace_irq_get(struct drm_device *dev, u32 seqno);
834void i915_user_irq_put(struct drm_device *dev);
835extern void i915_enable_interrupt (struct drm_device *dev); 852extern void i915_enable_interrupt (struct drm_device *dev);
836 853
837extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS); 854extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
@@ -849,6 +866,11 @@ extern u32 gm45_get_vblank_counter(struct drm_device *dev, int crtc);
849extern int i915_vblank_swap(struct drm_device *dev, void *data, 866extern int i915_vblank_swap(struct drm_device *dev, void *data,
850 struct drm_file *file_priv); 867 struct drm_file *file_priv);
851extern void i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask); 868extern void i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask);
869extern void i915_disable_irq(drm_i915_private_t *dev_priv, u32 mask);
870extern void ironlake_enable_graphics_irq(drm_i915_private_t *dev_priv,
871 u32 mask);
872extern void ironlake_disable_graphics_irq(drm_i915_private_t *dev_priv,
873 u32 mask);
852 874
853void 875void
854i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask); 876i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
@@ -922,11 +944,13 @@ void i915_gem_object_unpin(struct drm_gem_object *obj);
922int i915_gem_object_unbind(struct drm_gem_object *obj); 944int i915_gem_object_unbind(struct drm_gem_object *obj);
923void i915_gem_release_mmap(struct drm_gem_object *obj); 945void i915_gem_release_mmap(struct drm_gem_object *obj);
924void i915_gem_lastclose(struct drm_device *dev); 946void i915_gem_lastclose(struct drm_device *dev);
925uint32_t i915_get_gem_seqno(struct drm_device *dev); 947uint32_t i915_get_gem_seqno(struct drm_device *dev,
948 struct intel_ring_buffer *ring);
926bool i915_seqno_passed(uint32_t seq1, uint32_t seq2); 949bool i915_seqno_passed(uint32_t seq1, uint32_t seq2);
927int i915_gem_object_get_fence_reg(struct drm_gem_object *obj); 950int i915_gem_object_get_fence_reg(struct drm_gem_object *obj);
928int i915_gem_object_put_fence_reg(struct drm_gem_object *obj); 951int i915_gem_object_put_fence_reg(struct drm_gem_object *obj);
929void i915_gem_retire_requests(struct drm_device *dev); 952void i915_gem_retire_requests(struct drm_device *dev,
953 struct intel_ring_buffer *ring);
930void i915_gem_retire_work_handler(struct work_struct *work); 954void i915_gem_retire_work_handler(struct work_struct *work);
931void i915_gem_clflush_object(struct drm_gem_object *obj); 955void i915_gem_clflush_object(struct drm_gem_object *obj);
932int i915_gem_object_set_domain(struct drm_gem_object *obj, 956int i915_gem_object_set_domain(struct drm_gem_object *obj,
@@ -937,9 +961,13 @@ void i915_gem_cleanup_ringbuffer(struct drm_device *dev);
937int i915_gem_do_init(struct drm_device *dev, unsigned long start, 961int i915_gem_do_init(struct drm_device *dev, unsigned long start,
938 unsigned long end); 962 unsigned long end);
939int i915_gem_idle(struct drm_device *dev); 963int i915_gem_idle(struct drm_device *dev);
940uint32_t i915_add_request(struct drm_device *dev, struct drm_file *file_priv, 964uint32_t i915_add_request(struct drm_device *dev,
941 uint32_t flush_domains); 965 struct drm_file *file_priv,
942int i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible); 966 uint32_t flush_domains,
967 struct intel_ring_buffer *ring);
968int i915_do_wait_request(struct drm_device *dev,
969 uint32_t seqno, int interruptible,
970 struct intel_ring_buffer *ring);
943int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); 971int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
944int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, 972int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj,
945 int write); 973 int write);
@@ -1015,7 +1043,7 @@ extern void g4x_disable_fbc(struct drm_device *dev);
1015extern void intel_disable_fbc(struct drm_device *dev); 1043extern void intel_disable_fbc(struct drm_device *dev);
1016extern void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval); 1044extern void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval);
1017extern bool intel_fbc_enabled(struct drm_device *dev); 1045extern bool intel_fbc_enabled(struct drm_device *dev);
1018 1046extern bool ironlake_set_drps(struct drm_device *dev, u8 val);
1019extern void intel_detect_pch (struct drm_device *dev); 1047extern void intel_detect_pch (struct drm_device *dev);
1020extern int intel_trans_dp_port_sel (struct drm_crtc *crtc); 1048extern int intel_trans_dp_port_sel (struct drm_crtc *crtc);
1021 1049
@@ -1026,7 +1054,8 @@ extern int intel_trans_dp_port_sel (struct drm_crtc *crtc);
1026 * has access to the ring. 1054 * has access to the ring.
1027 */ 1055 */
1028#define RING_LOCK_TEST_WITH_RETURN(dev, file_priv) do { \ 1056#define RING_LOCK_TEST_WITH_RETURN(dev, file_priv) do { \
1029 if (((drm_i915_private_t *)dev->dev_private)->ring.ring_obj == NULL) \ 1057 if (((drm_i915_private_t *)dev->dev_private)->render_ring.gem_object \
1058 == NULL) \
1030 LOCK_TEST_WITH_RETURN(dev, file_priv); \ 1059 LOCK_TEST_WITH_RETURN(dev, file_priv); \
1031} while (0) 1060} while (0)
1032 1061
@@ -1039,35 +1068,31 @@ extern int intel_trans_dp_port_sel (struct drm_crtc *crtc);
1039#define I915_WRITE64(reg, val) writeq(val, dev_priv->regs + (reg)) 1068#define I915_WRITE64(reg, val) writeq(val, dev_priv->regs + (reg))
1040#define I915_READ64(reg) readq(dev_priv->regs + (reg)) 1069#define I915_READ64(reg) readq(dev_priv->regs + (reg))
1041#define POSTING_READ(reg) (void)I915_READ(reg) 1070#define POSTING_READ(reg) (void)I915_READ(reg)
1071#define POSTING_READ16(reg) (void)I915_READ16(reg)
1042 1072
1043#define I915_VERBOSE 0 1073#define I915_VERBOSE 0
1044 1074
1045#define RING_LOCALS volatile unsigned int *ring_virt__; 1075#define BEGIN_LP_RING(n) do { \
1046 1076 drm_i915_private_t *dev_priv = dev->dev_private; \
1047#define BEGIN_LP_RING(n) do { \ 1077 if (I915_VERBOSE) \
1048 int bytes__ = 4*(n); \ 1078 DRM_DEBUG(" BEGIN_LP_RING %x\n", (int)(n)); \
1049 if (I915_VERBOSE) DRM_DEBUG("BEGIN_LP_RING(%d)\n", (n)); \ 1079 intel_ring_begin(dev, &dev_priv->render_ring, 4*(n)); \
1050 /* a wrap must occur between instructions so pad beforehand */ \
1051 if (unlikely (dev_priv->ring.tail + bytes__ > dev_priv->ring.Size)) \
1052 i915_wrap_ring(dev); \
1053 if (unlikely (dev_priv->ring.space < bytes__)) \
1054 i915_wait_ring(dev, bytes__, __func__); \
1055 ring_virt__ = (unsigned int *) \
1056 (dev_priv->ring.virtual_start + dev_priv->ring.tail); \
1057 dev_priv->ring.tail += bytes__; \
1058 dev_priv->ring.tail &= dev_priv->ring.Size - 1; \
1059 dev_priv->ring.space -= bytes__; \
1060} while (0) 1080} while (0)
1061 1081
1062#define OUT_RING(n) do { \ 1082
1063 if (I915_VERBOSE) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \ 1083#define OUT_RING(x) do { \
1064 *ring_virt__++ = (n); \ 1084 drm_i915_private_t *dev_priv = dev->dev_private; \
1085 if (I915_VERBOSE) \
1086 DRM_DEBUG(" OUT_RING %x\n", (int)(x)); \
1087 intel_ring_emit(dev, &dev_priv->render_ring, x); \
1065} while (0) 1088} while (0)
1066 1089
1067#define ADVANCE_LP_RING() do { \ 1090#define ADVANCE_LP_RING() do { \
1091 drm_i915_private_t *dev_priv = dev->dev_private; \
1068 if (I915_VERBOSE) \ 1092 if (I915_VERBOSE) \
1069 DRM_DEBUG("ADVANCE_LP_RING %x\n", dev_priv->ring.tail); \ 1093 DRM_DEBUG("ADVANCE_LP_RING %x\n", \
1070 I915_WRITE(PRB0_TAIL, dev_priv->ring.tail); \ 1094 dev_priv->render_ring.tail); \
1095 intel_ring_advance(dev, &dev_priv->render_ring); \
1071} while(0) 1096} while(0)
1072 1097
1073/** 1098/**
@@ -1085,14 +1110,12 @@ extern int intel_trans_dp_port_sel (struct drm_crtc *crtc);
1085 * 1110 *
1086 * The area from dword 0x20 to 0x3ff is available for driver usage. 1111 * The area from dword 0x20 to 0x3ff is available for driver usage.
1087 */ 1112 */
1088#define READ_HWSP(dev_priv, reg) (((volatile u32*)(dev_priv->hw_status_page))[reg]) 1113#define READ_HWSP(dev_priv, reg) (((volatile u32 *)\
1114 (dev_priv->render_ring.status_page.page_addr))[reg])
1089#define READ_BREADCRUMB(dev_priv) READ_HWSP(dev_priv, I915_BREADCRUMB_INDEX) 1115#define READ_BREADCRUMB(dev_priv) READ_HWSP(dev_priv, I915_BREADCRUMB_INDEX)
1090#define I915_GEM_HWS_INDEX 0x20 1116#define I915_GEM_HWS_INDEX 0x20
1091#define I915_BREADCRUMB_INDEX 0x21 1117#define I915_BREADCRUMB_INDEX 0x21
1092 1118
1093extern int i915_wrap_ring(struct drm_device * dev);
1094extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
1095
1096#define INTEL_INFO(dev) (((struct drm_i915_private *) (dev)->dev_private)->info) 1119#define INTEL_INFO(dev) (((struct drm_i915_private *) (dev)->dev_private)->info)
1097 1120
1098#define IS_I830(dev) ((dev)->pci_device == 0x3577) 1121#define IS_I830(dev) ((dev)->pci_device == 0x3577)
@@ -1138,6 +1161,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
1138 (dev)->pci_device == 0x2A42 || \ 1161 (dev)->pci_device == 0x2A42 || \
1139 (dev)->pci_device == 0x2E42) 1162 (dev)->pci_device == 0x2E42)
1140 1163
1164#define HAS_BSD(dev) (IS_IRONLAKE(dev) || IS_G4X(dev))
1141#define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws) 1165#define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws)
1142 1166
1143/* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte 1167/* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 112699f71fa4..9ded3dae6c87 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -35,8 +35,6 @@
35#include <linux/swap.h> 35#include <linux/swap.h>
36#include <linux/pci.h> 36#include <linux/pci.h>
37 37
38#define I915_GEM_GPU_DOMAINS (~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT))
39
40static void i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj); 38static void i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj);
41static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj); 39static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj);
42static void i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj); 40static 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)
169 obj_priv->tiling_mode != I915_TILING_NONE; 167 obj_priv->tiling_mode != I915_TILING_NONE;
170} 168}
171 169
172static inline int 170static inline void
173slow_shmem_copy(struct page *dst_page, 171slow_shmem_copy(struct page *dst_page,
174 int dst_offset, 172 int dst_offset,
175 struct page *src_page, 173 struct page *src_page,
@@ -178,25 +176,16 @@ slow_shmem_copy(struct page *dst_page,
178{ 176{
179 char *dst_vaddr, *src_vaddr; 177 char *dst_vaddr, *src_vaddr;
180 178
181 dst_vaddr = kmap_atomic(dst_page, KM_USER0); 179 dst_vaddr = kmap(dst_page);
182 if (dst_vaddr == NULL) 180 src_vaddr = kmap(src_page);
183 return -ENOMEM;
184
185 src_vaddr = kmap_atomic(src_page, KM_USER1);
186 if (src_vaddr == NULL) {
187 kunmap_atomic(dst_vaddr, KM_USER0);
188 return -ENOMEM;
189 }
190 181
191 memcpy(dst_vaddr + dst_offset, src_vaddr + src_offset, length); 182 memcpy(dst_vaddr + dst_offset, src_vaddr + src_offset, length);
192 183
193 kunmap_atomic(src_vaddr, KM_USER1); 184 kunmap(src_page);
194 kunmap_atomic(dst_vaddr, KM_USER0); 185 kunmap(dst_page);
195
196 return 0;
197} 186}
198 187
199static inline int 188static inline void
200slow_shmem_bit17_copy(struct page *gpu_page, 189slow_shmem_bit17_copy(struct page *gpu_page,
201 int gpu_offset, 190 int gpu_offset,
202 struct page *cpu_page, 191 struct page *cpu_page,
@@ -216,15 +205,8 @@ slow_shmem_bit17_copy(struct page *gpu_page,
216 cpu_page, cpu_offset, length); 205 cpu_page, cpu_offset, length);
217 } 206 }
218 207
219 gpu_vaddr = kmap_atomic(gpu_page, KM_USER0); 208 gpu_vaddr = kmap(gpu_page);
220 if (gpu_vaddr == NULL) 209 cpu_vaddr = kmap(cpu_page);
221 return -ENOMEM;
222
223 cpu_vaddr = kmap_atomic(cpu_page, KM_USER1);
224 if (cpu_vaddr == NULL) {
225 kunmap_atomic(gpu_vaddr, KM_USER0);
226 return -ENOMEM;
227 }
228 210
229 /* Copy the data, XORing A6 with A17 (1). The user already knows he's 211 /* Copy the data, XORing A6 with A17 (1). The user already knows he's
230 * XORing with the other bits (A9 for Y, A9 and A10 for X) 212 * 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,
248 length -= this_length; 230 length -= this_length;
249 } 231 }
250 232
251 kunmap_atomic(cpu_vaddr, KM_USER1); 233 kunmap(cpu_page);
252 kunmap_atomic(gpu_vaddr, KM_USER0); 234 kunmap(gpu_page);
253
254 return 0;
255} 235}
256 236
257/** 237/**
@@ -427,21 +407,19 @@ i915_gem_shmem_pread_slow(struct drm_device *dev, struct drm_gem_object *obj,
427 page_length = PAGE_SIZE - data_page_offset; 407 page_length = PAGE_SIZE - data_page_offset;
428 408
429 if (do_bit17_swizzling) { 409 if (do_bit17_swizzling) {
430 ret = slow_shmem_bit17_copy(obj_priv->pages[shmem_page_index], 410 slow_shmem_bit17_copy(obj_priv->pages[shmem_page_index],
431 shmem_page_offset,
432 user_pages[data_page_index],
433 data_page_offset,
434 page_length,
435 1);
436 } else {
437 ret = slow_shmem_copy(user_pages[data_page_index],
438 data_page_offset,
439 obj_priv->pages[shmem_page_index],
440 shmem_page_offset, 411 shmem_page_offset,
441 page_length); 412 user_pages[data_page_index],
413 data_page_offset,
414 page_length,
415 1);
416 } else {
417 slow_shmem_copy(user_pages[data_page_index],
418 data_page_offset,
419 obj_priv->pages[shmem_page_index],
420 shmem_page_offset,
421 page_length);
442 } 422 }
443 if (ret)
444 goto fail_put_pages;
445 423
446 remain -= page_length; 424 remain -= page_length;
447 data_ptr += page_length; 425 data_ptr += page_length;
@@ -531,25 +509,24 @@ fast_user_write(struct io_mapping *mapping,
531 * page faults 509 * page faults
532 */ 510 */
533 511
534static inline int 512static inline void
535slow_kernel_write(struct io_mapping *mapping, 513slow_kernel_write(struct io_mapping *mapping,
536 loff_t gtt_base, int gtt_offset, 514 loff_t gtt_base, int gtt_offset,
537 struct page *user_page, int user_offset, 515 struct page *user_page, int user_offset,
538 int length) 516 int length)
539{ 517{
540 char *src_vaddr, *dst_vaddr; 518 char __iomem *dst_vaddr;
541 unsigned long unwritten; 519 char *src_vaddr;
542 520
543 dst_vaddr = io_mapping_map_atomic_wc(mapping, gtt_base); 521 dst_vaddr = io_mapping_map_wc(mapping, gtt_base);
544 src_vaddr = kmap_atomic(user_page, KM_USER1); 522 src_vaddr = kmap(user_page);
545 unwritten = __copy_from_user_inatomic_nocache(dst_vaddr + gtt_offset, 523
546 src_vaddr + user_offset, 524 memcpy_toio(dst_vaddr + gtt_offset,
547 length); 525 src_vaddr + user_offset,
548 kunmap_atomic(src_vaddr, KM_USER1); 526 length);
549 io_mapping_unmap_atomic(dst_vaddr); 527
550 if (unwritten) 528 kunmap(user_page);
551 return -EFAULT; 529 io_mapping_unmap(dst_vaddr);
552 return 0;
553} 530}
554 531
555static inline int 532static inline int
@@ -722,18 +699,11 @@ i915_gem_gtt_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj,
722 if ((data_page_offset + page_length) > PAGE_SIZE) 699 if ((data_page_offset + page_length) > PAGE_SIZE)
723 page_length = PAGE_SIZE - data_page_offset; 700 page_length = PAGE_SIZE - data_page_offset;
724 701
725 ret = slow_kernel_write(dev_priv->mm.gtt_mapping, 702 slow_kernel_write(dev_priv->mm.gtt_mapping,
726 gtt_page_base, gtt_page_offset, 703 gtt_page_base, gtt_page_offset,
727 user_pages[data_page_index], 704 user_pages[data_page_index],
728 data_page_offset, 705 data_page_offset,
729 page_length); 706 page_length);
730
731 /* If we get a fault while copying data, then (presumably) our
732 * source page isn't available. Return the error and we'll
733 * retry in the slow path.
734 */
735 if (ret)
736 goto out_unpin_object;
737 707
738 remain -= page_length; 708 remain -= page_length;
739 offset += page_length; 709 offset += page_length;
@@ -902,21 +872,19 @@ i915_gem_shmem_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj,
902 page_length = PAGE_SIZE - data_page_offset; 872 page_length = PAGE_SIZE - data_page_offset;
903 873
904 if (do_bit17_swizzling) { 874 if (do_bit17_swizzling) {
905 ret = slow_shmem_bit17_copy(obj_priv->pages[shmem_page_index], 875 slow_shmem_bit17_copy(obj_priv->pages[shmem_page_index],
906 shmem_page_offset,
907 user_pages[data_page_index],
908 data_page_offset,
909 page_length,
910 0);
911 } else {
912 ret = slow_shmem_copy(obj_priv->pages[shmem_page_index],
913 shmem_page_offset, 876 shmem_page_offset,
914 user_pages[data_page_index], 877 user_pages[data_page_index],
915 data_page_offset, 878 data_page_offset,
916 page_length); 879 page_length,
880 0);
881 } else {
882 slow_shmem_copy(obj_priv->pages[shmem_page_index],
883 shmem_page_offset,
884 user_pages[data_page_index],
885 data_page_offset,
886 page_length);
917 } 887 }
918 if (ret)
919 goto fail_put_pages;
920 888
921 remain -= page_length; 889 remain -= page_length;
922 data_ptr += page_length; 890 data_ptr += page_length;
@@ -973,7 +941,8 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
973 if (obj_priv->phys_obj) 941 if (obj_priv->phys_obj)
974 ret = i915_gem_phys_pwrite(dev, obj, args, file_priv); 942 ret = i915_gem_phys_pwrite(dev, obj, args, file_priv);
975 else if (obj_priv->tiling_mode == I915_TILING_NONE && 943 else if (obj_priv->tiling_mode == I915_TILING_NONE &&
976 dev->gtt_total != 0) { 944 dev->gtt_total != 0 &&
945 obj->write_domain != I915_GEM_DOMAIN_CPU) {
977 ret = i915_gem_gtt_pwrite_fast(dev, obj, args, file_priv); 946 ret = i915_gem_gtt_pwrite_fast(dev, obj, args, file_priv);
978 if (ret == -EFAULT) { 947 if (ret == -EFAULT) {
979 ret = i915_gem_gtt_pwrite_slow(dev, obj, args, 948 ret = i915_gem_gtt_pwrite_slow(dev, obj, args,
@@ -1484,11 +1453,14 @@ i915_gem_object_put_pages(struct drm_gem_object *obj)
1484} 1453}
1485 1454
1486static void 1455static void
1487i915_gem_object_move_to_active(struct drm_gem_object *obj, uint32_t seqno) 1456i915_gem_object_move_to_active(struct drm_gem_object *obj, uint32_t seqno,
1457 struct intel_ring_buffer *ring)
1488{ 1458{
1489 struct drm_device *dev = obj->dev; 1459 struct drm_device *dev = obj->dev;
1490 drm_i915_private_t *dev_priv = dev->dev_private; 1460 drm_i915_private_t *dev_priv = dev->dev_private;
1491 struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); 1461 struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
1462 BUG_ON(ring == NULL);
1463 obj_priv->ring = ring;
1492 1464
1493 /* Add a reference if we're newly entering the active list. */ 1465 /* Add a reference if we're newly entering the active list. */
1494 if (!obj_priv->active) { 1466 if (!obj_priv->active) {
@@ -1497,8 +1469,7 @@ i915_gem_object_move_to_active(struct drm_gem_object *obj, uint32_t seqno)
1497 } 1469 }
1498 /* Move from whatever list we were on to the tail of execution. */ 1470 /* Move from whatever list we were on to the tail of execution. */
1499 spin_lock(&dev_priv->mm.active_list_lock); 1471 spin_lock(&dev_priv->mm.active_list_lock);
1500 list_move_tail(&obj_priv->list, 1472 list_move_tail(&obj_priv->list, &ring->active_list);
1501 &dev_priv->mm.active_list);
1502 spin_unlock(&dev_priv->mm.active_list_lock); 1473 spin_unlock(&dev_priv->mm.active_list_lock);
1503 obj_priv->last_rendering_seqno = seqno; 1474 obj_priv->last_rendering_seqno = seqno;
1504} 1475}
@@ -1551,6 +1522,7 @@ i915_gem_object_move_to_inactive(struct drm_gem_object *obj)
1551 BUG_ON(!list_empty(&obj_priv->gpu_write_list)); 1522 BUG_ON(!list_empty(&obj_priv->gpu_write_list));
1552 1523
1553 obj_priv->last_rendering_seqno = 0; 1524 obj_priv->last_rendering_seqno = 0;
1525 obj_priv->ring = NULL;
1554 if (obj_priv->active) { 1526 if (obj_priv->active) {
1555 obj_priv->active = 0; 1527 obj_priv->active = 0;
1556 drm_gem_object_unreference(obj); 1528 drm_gem_object_unreference(obj);
@@ -1560,7 +1532,8 @@ i915_gem_object_move_to_inactive(struct drm_gem_object *obj)
1560 1532
1561static void 1533static void
1562i915_gem_process_flushing_list(struct drm_device *dev, 1534i915_gem_process_flushing_list(struct drm_device *dev,
1563 uint32_t flush_domains, uint32_t seqno) 1535 uint32_t flush_domains, uint32_t seqno,
1536 struct intel_ring_buffer *ring)
1564{ 1537{
1565 drm_i915_private_t *dev_priv = dev->dev_private; 1538 drm_i915_private_t *dev_priv = dev->dev_private;
1566 struct drm_i915_gem_object *obj_priv, *next; 1539 struct drm_i915_gem_object *obj_priv, *next;
@@ -1571,12 +1544,13 @@ i915_gem_process_flushing_list(struct drm_device *dev,
1571 struct drm_gem_object *obj = &obj_priv->base; 1544 struct drm_gem_object *obj = &obj_priv->base;
1572 1545
1573 if ((obj->write_domain & flush_domains) == 1546 if ((obj->write_domain & flush_domains) ==
1574 obj->write_domain) { 1547 obj->write_domain &&
1548 obj_priv->ring->ring_flag == ring->ring_flag) {
1575 uint32_t old_write_domain = obj->write_domain; 1549 uint32_t old_write_domain = obj->write_domain;
1576 1550
1577 obj->write_domain = 0; 1551 obj->write_domain = 0;
1578 list_del_init(&obj_priv->gpu_write_list); 1552 list_del_init(&obj_priv->gpu_write_list);
1579 i915_gem_object_move_to_active(obj, seqno); 1553 i915_gem_object_move_to_active(obj, seqno, ring);
1580 1554
1581 /* update the fence lru list */ 1555 /* update the fence lru list */
1582 if (obj_priv->fence_reg != I915_FENCE_REG_NONE) { 1556 if (obj_priv->fence_reg != I915_FENCE_REG_NONE) {
@@ -1593,31 +1567,15 @@ i915_gem_process_flushing_list(struct drm_device *dev,
1593 } 1567 }
1594} 1568}
1595 1569
1596#define PIPE_CONTROL_FLUSH(addr) \
1597 OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE | \
1598 PIPE_CONTROL_DEPTH_STALL); \
1599 OUT_RING(addr | PIPE_CONTROL_GLOBAL_GTT); \
1600 OUT_RING(0); \
1601 OUT_RING(0); \
1602
1603/**
1604 * Creates a new sequence number, emitting a write of it to the status page
1605 * plus an interrupt, which will trigger i915_user_interrupt_handler.
1606 *
1607 * Must be called with struct_lock held.
1608 *
1609 * Returned sequence numbers are nonzero on success.
1610 */
1611uint32_t 1570uint32_t
1612i915_add_request(struct drm_device *dev, struct drm_file *file_priv, 1571i915_add_request(struct drm_device *dev, struct drm_file *file_priv,
1613 uint32_t flush_domains) 1572 uint32_t flush_domains, struct intel_ring_buffer *ring)
1614{ 1573{
1615 drm_i915_private_t *dev_priv = dev->dev_private; 1574 drm_i915_private_t *dev_priv = dev->dev_private;
1616 struct drm_i915_file_private *i915_file_priv = NULL; 1575 struct drm_i915_file_private *i915_file_priv = NULL;
1617 struct drm_i915_gem_request *request; 1576 struct drm_i915_gem_request *request;
1618 uint32_t seqno; 1577 uint32_t seqno;
1619 int was_empty; 1578 int was_empty;
1620 RING_LOCALS;
1621 1579
1622 if (file_priv != NULL) 1580 if (file_priv != NULL)
1623 i915_file_priv = file_priv->driver_priv; 1581 i915_file_priv = file_priv->driver_priv;
@@ -1626,62 +1584,14 @@ i915_add_request(struct drm_device *dev, struct drm_file *file_priv,
1626 if (request == NULL) 1584 if (request == NULL)
1627 return 0; 1585 return 0;
1628 1586
1629 /* Grab the seqno we're going to make this request be, and bump the 1587 seqno = ring->add_request(dev, ring, file_priv, flush_domains);
1630 * next (skipping 0 so it can be the reserved no-seqno value).
1631 */
1632 seqno = dev_priv->mm.next_gem_seqno;
1633 dev_priv->mm.next_gem_seqno++;
1634 if (dev_priv->mm.next_gem_seqno == 0)
1635 dev_priv->mm.next_gem_seqno++;
1636
1637 if (HAS_PIPE_CONTROL(dev)) {
1638 u32 scratch_addr = dev_priv->seqno_gfx_addr + 128;
1639
1640 /*
1641 * Workaround qword write incoherence by flushing the
1642 * PIPE_NOTIFY buffers out to memory before requesting
1643 * an interrupt.
1644 */
1645 BEGIN_LP_RING(32);
1646 OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |
1647 PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH);
1648 OUT_RING(dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT);
1649 OUT_RING(seqno);
1650 OUT_RING(0);
1651 PIPE_CONTROL_FLUSH(scratch_addr);
1652 scratch_addr += 128; /* write to separate cachelines */
1653 PIPE_CONTROL_FLUSH(scratch_addr);
1654 scratch_addr += 128;
1655 PIPE_CONTROL_FLUSH(scratch_addr);
1656 scratch_addr += 128;
1657 PIPE_CONTROL_FLUSH(scratch_addr);
1658 scratch_addr += 128;
1659 PIPE_CONTROL_FLUSH(scratch_addr);
1660 scratch_addr += 128;
1661 PIPE_CONTROL_FLUSH(scratch_addr);
1662 OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |
1663 PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH |
1664 PIPE_CONTROL_NOTIFY);
1665 OUT_RING(dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT);
1666 OUT_RING(seqno);
1667 OUT_RING(0);
1668 ADVANCE_LP_RING();
1669 } else {
1670 BEGIN_LP_RING(4);
1671 OUT_RING(MI_STORE_DWORD_INDEX);
1672 OUT_RING(I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
1673 OUT_RING(seqno);
1674
1675 OUT_RING(MI_USER_INTERRUPT);
1676 ADVANCE_LP_RING();
1677 }
1678
1679 DRM_DEBUG_DRIVER("%d\n", seqno);
1680 1588
1681 request->seqno = seqno; 1589 request->seqno = seqno;
1590 request->ring = ring;
1682 request->emitted_jiffies = jiffies; 1591 request->emitted_jiffies = jiffies;
1683 was_empty = list_empty(&dev_priv->mm.request_list); 1592 was_empty = list_empty(&ring->request_list);
1684 list_add_tail(&request->list, &dev_priv->mm.request_list); 1593 list_add_tail(&request->list, &ring->request_list);
1594
1685 if (i915_file_priv) { 1595 if (i915_file_priv) {
1686 list_add_tail(&request->client_list, 1596 list_add_tail(&request->client_list,
1687 &i915_file_priv->mm.request_list); 1597 &i915_file_priv->mm.request_list);
@@ -1693,7 +1603,7 @@ i915_add_request(struct drm_device *dev, struct drm_file *file_priv,
1693 * domain we're flushing with our flush. 1603 * domain we're flushing with our flush.
1694 */ 1604 */
1695 if (flush_domains != 0) 1605 if (flush_domains != 0)
1696 i915_gem_process_flushing_list(dev, flush_domains, seqno); 1606 i915_gem_process_flushing_list(dev, flush_domains, seqno, ring);
1697 1607
1698 if (!dev_priv->mm.suspended) { 1608 if (!dev_priv->mm.suspended) {
1699 mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); 1609 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,
1710 * before signalling the CPU 1620 * before signalling the CPU
1711 */ 1621 */
1712static uint32_t 1622static uint32_t
1713i915_retire_commands(struct drm_device *dev) 1623i915_retire_commands(struct drm_device *dev, struct intel_ring_buffer *ring)
1714{ 1624{
1715 drm_i915_private_t *dev_priv = dev->dev_private;
1716 uint32_t cmd = MI_FLUSH | MI_NO_WRITE_FLUSH;
1717 uint32_t flush_domains = 0; 1625 uint32_t flush_domains = 0;
1718 RING_LOCALS;
1719 1626
1720 /* The sampler always gets flushed on i965 (sigh) */ 1627 /* The sampler always gets flushed on i965 (sigh) */
1721 if (IS_I965G(dev)) 1628 if (IS_I965G(dev))
1722 flush_domains |= I915_GEM_DOMAIN_SAMPLER; 1629 flush_domains |= I915_GEM_DOMAIN_SAMPLER;
1723 BEGIN_LP_RING(2); 1630
1724 OUT_RING(cmd); 1631 ring->flush(dev, ring,
1725 OUT_RING(0); /* noop */ 1632 I915_GEM_DOMAIN_COMMAND, flush_domains);
1726 ADVANCE_LP_RING();
1727 return flush_domains; 1633 return flush_domains;
1728} 1634}
1729 1635
@@ -1743,11 +1649,11 @@ i915_gem_retire_request(struct drm_device *dev,
1743 * by the ringbuffer to the flushing/inactive lists as appropriate. 1649 * by the ringbuffer to the flushing/inactive lists as appropriate.
1744 */ 1650 */
1745 spin_lock(&dev_priv->mm.active_list_lock); 1651 spin_lock(&dev_priv->mm.active_list_lock);
1746 while (!list_empty(&dev_priv->mm.active_list)) { 1652 while (!list_empty(&request->ring->active_list)) {
1747 struct drm_gem_object *obj; 1653 struct drm_gem_object *obj;
1748 struct drm_i915_gem_object *obj_priv; 1654 struct drm_i915_gem_object *obj_priv;
1749 1655
1750 obj_priv = list_first_entry(&dev_priv->mm.active_list, 1656 obj_priv = list_first_entry(&request->ring->active_list,
1751 struct drm_i915_gem_object, 1657 struct drm_i915_gem_object,
1752 list); 1658 list);
1753 obj = &obj_priv->base; 1659 obj = &obj_priv->base;
@@ -1794,35 +1700,33 @@ i915_seqno_passed(uint32_t seq1, uint32_t seq2)
1794} 1700}
1795 1701
1796uint32_t 1702uint32_t
1797i915_get_gem_seqno(struct drm_device *dev) 1703i915_get_gem_seqno(struct drm_device *dev,
1704 struct intel_ring_buffer *ring)
1798{ 1705{
1799 drm_i915_private_t *dev_priv = dev->dev_private; 1706 return ring->get_gem_seqno(dev, ring);
1800
1801 if (HAS_PIPE_CONTROL(dev))
1802 return ((volatile u32 *)(dev_priv->seqno_page))[0];
1803 else
1804 return READ_HWSP(dev_priv, I915_GEM_HWS_INDEX);
1805} 1707}
1806 1708
1807/** 1709/**
1808 * This function clears the request list as sequence numbers are passed. 1710 * This function clears the request list as sequence numbers are passed.
1809 */ 1711 */
1810void 1712void
1811i915_gem_retire_requests(struct drm_device *dev) 1713i915_gem_retire_requests(struct drm_device *dev,
1714 struct intel_ring_buffer *ring)
1812{ 1715{
1813 drm_i915_private_t *dev_priv = dev->dev_private; 1716 drm_i915_private_t *dev_priv = dev->dev_private;
1814 uint32_t seqno; 1717 uint32_t seqno;
1815 1718
1816 if (!dev_priv->hw_status_page || list_empty(&dev_priv->mm.request_list)) 1719 if (!ring->status_page.page_addr
1720 || list_empty(&ring->request_list))
1817 return; 1721 return;
1818 1722
1819 seqno = i915_get_gem_seqno(dev); 1723 seqno = i915_get_gem_seqno(dev, ring);
1820 1724
1821 while (!list_empty(&dev_priv->mm.request_list)) { 1725 while (!list_empty(&ring->request_list)) {
1822 struct drm_i915_gem_request *request; 1726 struct drm_i915_gem_request *request;
1823 uint32_t retiring_seqno; 1727 uint32_t retiring_seqno;
1824 1728
1825 request = list_first_entry(&dev_priv->mm.request_list, 1729 request = list_first_entry(&ring->request_list,
1826 struct drm_i915_gem_request, 1730 struct drm_i915_gem_request,
1827 list); 1731 list);
1828 retiring_seqno = request->seqno; 1732 retiring_seqno = request->seqno;
@@ -1840,7 +1744,8 @@ i915_gem_retire_requests(struct drm_device *dev)
1840 1744
1841 if (unlikely (dev_priv->trace_irq_seqno && 1745 if (unlikely (dev_priv->trace_irq_seqno &&
1842 i915_seqno_passed(dev_priv->trace_irq_seqno, seqno))) { 1746 i915_seqno_passed(dev_priv->trace_irq_seqno, seqno))) {
1843 i915_user_irq_put(dev); 1747
1748 ring->user_irq_put(dev, ring);
1844 dev_priv->trace_irq_seqno = 0; 1749 dev_priv->trace_irq_seqno = 0;
1845 } 1750 }
1846} 1751}
@@ -1856,15 +1761,22 @@ i915_gem_retire_work_handler(struct work_struct *work)
1856 dev = dev_priv->dev; 1761 dev = dev_priv->dev;
1857 1762
1858 mutex_lock(&dev->struct_mutex); 1763 mutex_lock(&dev->struct_mutex);
1859 i915_gem_retire_requests(dev); 1764 i915_gem_retire_requests(dev, &dev_priv->render_ring);
1765
1766 if (HAS_BSD(dev))
1767 i915_gem_retire_requests(dev, &dev_priv->bsd_ring);
1768
1860 if (!dev_priv->mm.suspended && 1769 if (!dev_priv->mm.suspended &&
1861 !list_empty(&dev_priv->mm.request_list)) 1770 (!list_empty(&dev_priv->render_ring.request_list) ||
1771 (HAS_BSD(dev) &&
1772 !list_empty(&dev_priv->bsd_ring.request_list))))
1862 queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ); 1773 queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ);
1863 mutex_unlock(&dev->struct_mutex); 1774 mutex_unlock(&dev->struct_mutex);
1864} 1775}
1865 1776
1866int 1777int
1867i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible) 1778i915_do_wait_request(struct drm_device *dev, uint32_t seqno,
1779 int interruptible, struct intel_ring_buffer *ring)
1868{ 1780{
1869 drm_i915_private_t *dev_priv = dev->dev_private; 1781 drm_i915_private_t *dev_priv = dev->dev_private;
1870 u32 ier; 1782 u32 ier;
@@ -1875,7 +1787,7 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible)
1875 if (atomic_read(&dev_priv->mm.wedged)) 1787 if (atomic_read(&dev_priv->mm.wedged))
1876 return -EIO; 1788 return -EIO;
1877 1789
1878 if (!i915_seqno_passed(i915_get_gem_seqno(dev), seqno)) { 1790 if (!i915_seqno_passed(ring->get_gem_seqno(dev, ring), seqno)) {
1879 if (HAS_PCH_SPLIT(dev)) 1791 if (HAS_PCH_SPLIT(dev))
1880 ier = I915_READ(DEIER) | I915_READ(GTIER); 1792 ier = I915_READ(DEIER) | I915_READ(GTIER);
1881 else 1793 else
@@ -1889,19 +1801,21 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible)
1889 1801
1890 trace_i915_gem_request_wait_begin(dev, seqno); 1802 trace_i915_gem_request_wait_begin(dev, seqno);
1891 1803
1892 dev_priv->mm.waiting_gem_seqno = seqno; 1804 ring->waiting_gem_seqno = seqno;
1893 i915_user_irq_get(dev); 1805 ring->user_irq_get(dev, ring);
1894 if (interruptible) 1806 if (interruptible)
1895 ret = wait_event_interruptible(dev_priv->irq_queue, 1807 ret = wait_event_interruptible(ring->irq_queue,
1896 i915_seqno_passed(i915_get_gem_seqno(dev), seqno) || 1808 i915_seqno_passed(
1897 atomic_read(&dev_priv->mm.wedged)); 1809 ring->get_gem_seqno(dev, ring), seqno)
1810 || atomic_read(&dev_priv->mm.wedged));
1898 else 1811 else
1899 wait_event(dev_priv->irq_queue, 1812 wait_event(ring->irq_queue,
1900 i915_seqno_passed(i915_get_gem_seqno(dev), seqno) || 1813 i915_seqno_passed(
1901 atomic_read(&dev_priv->mm.wedged)); 1814 ring->get_gem_seqno(dev, ring), seqno)
1815 || atomic_read(&dev_priv->mm.wedged));
1902 1816
1903 i915_user_irq_put(dev); 1817 ring->user_irq_put(dev, ring);
1904 dev_priv->mm.waiting_gem_seqno = 0; 1818 ring->waiting_gem_seqno = 0;
1905 1819
1906 trace_i915_gem_request_wait_end(dev, seqno); 1820 trace_i915_gem_request_wait_end(dev, seqno);
1907 } 1821 }
@@ -1910,7 +1824,7 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible)
1910 1824
1911 if (ret && ret != -ERESTARTSYS) 1825 if (ret && ret != -ERESTARTSYS)
1912 DRM_ERROR("%s returns %d (awaiting %d at %d)\n", 1826 DRM_ERROR("%s returns %d (awaiting %d at %d)\n",
1913 __func__, ret, seqno, i915_get_gem_seqno(dev)); 1827 __func__, ret, seqno, ring->get_gem_seqno(dev, ring));
1914 1828
1915 /* Directly dispatch request retiring. While we have the work queue 1829 /* Directly dispatch request retiring. While we have the work queue
1916 * to handle this, the waiter on a request often wants an associated 1830 * 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)
1918 * a separate wait queue to handle that. 1832 * a separate wait queue to handle that.
1919 */ 1833 */
1920 if (ret == 0) 1834 if (ret == 0)
1921 i915_gem_retire_requests(dev); 1835 i915_gem_retire_requests(dev, ring);
1922 1836
1923 return ret; 1837 return ret;
1924} 1838}
@@ -1928,9 +1842,10 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible)
1928 * request and object lists appropriately for that event. 1842 * request and object lists appropriately for that event.
1929 */ 1843 */
1930static int 1844static int
1931i915_wait_request(struct drm_device *dev, uint32_t seqno) 1845i915_wait_request(struct drm_device *dev, uint32_t seqno,
1846 struct intel_ring_buffer *ring)
1932{ 1847{
1933 return i915_do_wait_request(dev, seqno, 1); 1848 return i915_do_wait_request(dev, seqno, 1, ring);
1934} 1849}
1935 1850
1936static void 1851static void
@@ -1939,71 +1854,29 @@ i915_gem_flush(struct drm_device *dev,
1939 uint32_t flush_domains) 1854 uint32_t flush_domains)
1940{ 1855{
1941 drm_i915_private_t *dev_priv = dev->dev_private; 1856 drm_i915_private_t *dev_priv = dev->dev_private;
1942 uint32_t cmd;
1943 RING_LOCALS;
1944
1945#if WATCH_EXEC
1946 DRM_INFO("%s: invalidate %08x flush %08x\n", __func__,
1947 invalidate_domains, flush_domains);
1948#endif
1949 trace_i915_gem_request_flush(dev, dev_priv->mm.next_gem_seqno,
1950 invalidate_domains, flush_domains);
1951
1952 if (flush_domains & I915_GEM_DOMAIN_CPU) 1857 if (flush_domains & I915_GEM_DOMAIN_CPU)
1953 drm_agp_chipset_flush(dev); 1858 drm_agp_chipset_flush(dev);
1859 dev_priv->render_ring.flush(dev, &dev_priv->render_ring,
1860 invalidate_domains,
1861 flush_domains);
1862
1863 if (HAS_BSD(dev))
1864 dev_priv->bsd_ring.flush(dev, &dev_priv->bsd_ring,
1865 invalidate_domains,
1866 flush_domains);
1867}
1954 1868
1955 if ((invalidate_domains | flush_domains) & I915_GEM_GPU_DOMAINS) { 1869static void
1956 /* 1870i915_gem_flush_ring(struct drm_device *dev,
1957 * read/write caches: 1871 uint32_t invalidate_domains,
1958 * 1872 uint32_t flush_domains,
1959 * I915_GEM_DOMAIN_RENDER is always invalidated, but is 1873 struct intel_ring_buffer *ring)
1960 * only flushed if MI_NO_WRITE_FLUSH is unset. On 965, it is 1874{
1961 * also flushed at 2d versus 3d pipeline switches. 1875 if (flush_domains & I915_GEM_DOMAIN_CPU)
1962 * 1876 drm_agp_chipset_flush(dev);
1963 * read-only caches: 1877 ring->flush(dev, ring,
1964 * 1878 invalidate_domains,
1965 * I915_GEM_DOMAIN_SAMPLER is flushed on pre-965 if 1879 flush_domains);
1966 * MI_READ_FLUSH is set, and is always flushed on 965.
1967 *
1968 * I915_GEM_DOMAIN_COMMAND may not exist?
1969 *
1970 * I915_GEM_DOMAIN_INSTRUCTION, which exists on 965, is
1971 * invalidated when MI_EXE_FLUSH is set.
1972 *
1973 * I915_GEM_DOMAIN_VERTEX, which exists on 965, is
1974 * invalidated with every MI_FLUSH.
1975 *
1976 * TLBs:
1977 *
1978 * On 965, TLBs associated with I915_GEM_DOMAIN_COMMAND
1979 * and I915_GEM_DOMAIN_CPU in are invalidated at PTE write and
1980 * I915_GEM_DOMAIN_RENDER and I915_GEM_DOMAIN_SAMPLER
1981 * are flushed at any MI_FLUSH.
1982 */
1983
1984 cmd = MI_FLUSH | MI_NO_WRITE_FLUSH;
1985 if ((invalidate_domains|flush_domains) &
1986 I915_GEM_DOMAIN_RENDER)
1987 cmd &= ~MI_NO_WRITE_FLUSH;
1988 if (!IS_I965G(dev)) {
1989 /*
1990 * On the 965, the sampler cache always gets flushed
1991 * and this bit is reserved.
1992 */
1993 if (invalidate_domains & I915_GEM_DOMAIN_SAMPLER)
1994 cmd |= MI_READ_FLUSH;
1995 }
1996 if (invalidate_domains & I915_GEM_DOMAIN_INSTRUCTION)
1997 cmd |= MI_EXE_FLUSH;
1998
1999#if WATCH_EXEC
2000 DRM_INFO("%s: queue flush %08x to ring\n", __func__, cmd);
2001#endif
2002 BEGIN_LP_RING(2);
2003 OUT_RING(cmd);
2004 OUT_RING(MI_NOOP);
2005 ADVANCE_LP_RING();
2006 }
2007} 1880}
2008 1881
2009/** 1882/**
@@ -2030,7 +1903,8 @@ i915_gem_object_wait_rendering(struct drm_gem_object *obj)
2030 DRM_INFO("%s: object %p wait for seqno %08x\n", 1903 DRM_INFO("%s: object %p wait for seqno %08x\n",
2031 __func__, obj, obj_priv->last_rendering_seqno); 1904 __func__, obj, obj_priv->last_rendering_seqno);
2032#endif 1905#endif
2033 ret = i915_wait_request(dev, obj_priv->last_rendering_seqno); 1906 ret = i915_wait_request(dev,
1907 obj_priv->last_rendering_seqno, obj_priv->ring);
2034 if (ret != 0) 1908 if (ret != 0)
2035 return ret; 1909 return ret;
2036 } 1910 }
@@ -2146,11 +2020,14 @@ i915_gpu_idle(struct drm_device *dev)
2146{ 2020{
2147 drm_i915_private_t *dev_priv = dev->dev_private; 2021 drm_i915_private_t *dev_priv = dev->dev_private;
2148 bool lists_empty; 2022 bool lists_empty;
2149 uint32_t seqno; 2023 uint32_t seqno1, seqno2;
2024 int ret;
2150 2025
2151 spin_lock(&dev_priv->mm.active_list_lock); 2026 spin_lock(&dev_priv->mm.active_list_lock);
2152 lists_empty = list_empty(&dev_priv->mm.flushing_list) && 2027 lists_empty = (list_empty(&dev_priv->mm.flushing_list) &&
2153 list_empty(&dev_priv->mm.active_list); 2028 list_empty(&dev_priv->render_ring.active_list) &&
2029 (!HAS_BSD(dev) ||
2030 list_empty(&dev_priv->bsd_ring.active_list)));
2154 spin_unlock(&dev_priv->mm.active_list_lock); 2031 spin_unlock(&dev_priv->mm.active_list_lock);
2155 2032
2156 if (lists_empty) 2033 if (lists_empty)
@@ -2158,11 +2035,25 @@ i915_gpu_idle(struct drm_device *dev)
2158 2035
2159 /* Flush everything onto the inactive list. */ 2036 /* Flush everything onto the inactive list. */
2160 i915_gem_flush(dev, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS); 2037 i915_gem_flush(dev, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
2161 seqno = i915_add_request(dev, NULL, I915_GEM_GPU_DOMAINS); 2038 seqno1 = i915_add_request(dev, NULL, I915_GEM_GPU_DOMAINS,
2162 if (seqno == 0) 2039 &dev_priv->render_ring);
2040 if (seqno1 == 0)
2163 return -ENOMEM; 2041 return -ENOMEM;
2042 ret = i915_wait_request(dev, seqno1, &dev_priv->render_ring);
2043
2044 if (HAS_BSD(dev)) {
2045 seqno2 = i915_add_request(dev, NULL, I915_GEM_GPU_DOMAINS,
2046 &dev_priv->bsd_ring);
2047 if (seqno2 == 0)
2048 return -ENOMEM;
2049
2050 ret = i915_wait_request(dev, seqno2, &dev_priv->bsd_ring);
2051 if (ret)
2052 return ret;
2053 }
2054
2164 2055
2165 return i915_wait_request(dev, seqno); 2056 return ret;
2166} 2057}
2167 2058
2168static int 2059static int
@@ -2175,7 +2066,9 @@ i915_gem_evict_everything(struct drm_device *dev)
2175 spin_lock(&dev_priv->mm.active_list_lock); 2066 spin_lock(&dev_priv->mm.active_list_lock);
2176 lists_empty = (list_empty(&dev_priv->mm.inactive_list) && 2067 lists_empty = (list_empty(&dev_priv->mm.inactive_list) &&
2177 list_empty(&dev_priv->mm.flushing_list) && 2068 list_empty(&dev_priv->mm.flushing_list) &&
2178 list_empty(&dev_priv->mm.active_list)); 2069 list_empty(&dev_priv->render_ring.active_list) &&
2070 (!HAS_BSD(dev)
2071 || list_empty(&dev_priv->bsd_ring.active_list)));
2179 spin_unlock(&dev_priv->mm.active_list_lock); 2072 spin_unlock(&dev_priv->mm.active_list_lock);
2180 2073
2181 if (lists_empty) 2074 if (lists_empty)
@@ -2195,7 +2088,9 @@ i915_gem_evict_everything(struct drm_device *dev)
2195 spin_lock(&dev_priv->mm.active_list_lock); 2088 spin_lock(&dev_priv->mm.active_list_lock);
2196 lists_empty = (list_empty(&dev_priv->mm.inactive_list) && 2089 lists_empty = (list_empty(&dev_priv->mm.inactive_list) &&
2197 list_empty(&dev_priv->mm.flushing_list) && 2090 list_empty(&dev_priv->mm.flushing_list) &&
2198 list_empty(&dev_priv->mm.active_list)); 2091 list_empty(&dev_priv->render_ring.active_list) &&
2092 (!HAS_BSD(dev)
2093 || list_empty(&dev_priv->bsd_ring.active_list)));
2199 spin_unlock(&dev_priv->mm.active_list_lock); 2094 spin_unlock(&dev_priv->mm.active_list_lock);
2200 BUG_ON(!lists_empty); 2095 BUG_ON(!lists_empty);
2201 2096
@@ -2209,8 +2104,13 @@ i915_gem_evict_something(struct drm_device *dev, int min_size)
2209 struct drm_gem_object *obj; 2104 struct drm_gem_object *obj;
2210 int ret; 2105 int ret;
2211 2106
2107 struct intel_ring_buffer *render_ring = &dev_priv->render_ring;
2108 struct intel_ring_buffer *bsd_ring = &dev_priv->bsd_ring;
2212 for (;;) { 2109 for (;;) {
2213 i915_gem_retire_requests(dev); 2110 i915_gem_retire_requests(dev, render_ring);
2111
2112 if (HAS_BSD(dev))
2113 i915_gem_retire_requests(dev, bsd_ring);
2214 2114
2215 /* If there's an inactive buffer available now, grab it 2115 /* If there's an inactive buffer available now, grab it
2216 * and be done. 2116 * and be done.
@@ -2234,14 +2134,30 @@ i915_gem_evict_something(struct drm_device *dev, int min_size)
2234 * things, wait for the next to finish and hopefully leave us 2134 * things, wait for the next to finish and hopefully leave us
2235 * a buffer to evict. 2135 * a buffer to evict.
2236 */ 2136 */
2237 if (!list_empty(&dev_priv->mm.request_list)) { 2137 if (!list_empty(&render_ring->request_list)) {
2138 struct drm_i915_gem_request *request;
2139
2140 request = list_first_entry(&render_ring->request_list,
2141 struct drm_i915_gem_request,
2142 list);
2143
2144 ret = i915_wait_request(dev,
2145 request->seqno, request->ring);
2146 if (ret)
2147 return ret;
2148
2149 continue;
2150 }
2151
2152 if (HAS_BSD(dev) && !list_empty(&bsd_ring->request_list)) {
2238 struct drm_i915_gem_request *request; 2153 struct drm_i915_gem_request *request;
2239 2154
2240 request = list_first_entry(&dev_priv->mm.request_list, 2155 request = list_first_entry(&bsd_ring->request_list,
2241 struct drm_i915_gem_request, 2156 struct drm_i915_gem_request,
2242 list); 2157 list);
2243 2158
2244 ret = i915_wait_request(dev, request->seqno); 2159 ret = i915_wait_request(dev,
2160 request->seqno, request->ring);
2245 if (ret) 2161 if (ret)
2246 return ret; 2162 return ret;
2247 2163
@@ -2268,10 +2184,13 @@ i915_gem_evict_something(struct drm_device *dev, int min_size)
2268 if (obj != NULL) { 2184 if (obj != NULL) {
2269 uint32_t seqno; 2185 uint32_t seqno;
2270 2186
2271 i915_gem_flush(dev, 2187 i915_gem_flush_ring(dev,
2188 obj->write_domain,
2272 obj->write_domain, 2189 obj->write_domain,
2273 obj->write_domain); 2190 obj_priv->ring);
2274 seqno = i915_add_request(dev, NULL, obj->write_domain); 2191 seqno = i915_add_request(dev, NULL,
2192 obj->write_domain,
2193 obj_priv->ring);
2275 if (seqno == 0) 2194 if (seqno == 0)
2276 return -ENOMEM; 2195 return -ENOMEM;
2277 continue; 2196 continue;
@@ -2299,6 +2218,9 @@ i915_gem_object_get_pages(struct drm_gem_object *obj,
2299 struct inode *inode; 2218 struct inode *inode;
2300 struct page *page; 2219 struct page *page;
2301 2220
2221 BUG_ON(obj_priv->pages_refcount
2222 == DRM_I915_GEM_OBJECT_MAX_PAGES_REFCOUNT);
2223
2302 if (obj_priv->pages_refcount++ != 0) 2224 if (obj_priv->pages_refcount++ != 0)
2303 return 0; 2225 return 0;
2304 2226
@@ -2697,6 +2619,14 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
2697 return -EINVAL; 2619 return -EINVAL;
2698 } 2620 }
2699 2621
2622 /* If the object is bigger than the entire aperture, reject it early
2623 * before evicting everything in a vain attempt to find space.
2624 */
2625 if (obj->size > dev->gtt_total) {
2626 DRM_ERROR("Attempting to bind an object larger than the aperture\n");
2627 return -E2BIG;
2628 }
2629
2700 search_free: 2630 search_free:
2701 free_space = drm_mm_search_free(&dev_priv->mm.gtt_space, 2631 free_space = drm_mm_search_free(&dev_priv->mm.gtt_space,
2702 obj->size, alignment, 0); 2632 obj->size, alignment, 0);
@@ -2807,6 +2737,7 @@ i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj)
2807{ 2737{
2808 struct drm_device *dev = obj->dev; 2738 struct drm_device *dev = obj->dev;
2809 uint32_t old_write_domain; 2739 uint32_t old_write_domain;
2740 struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
2810 2741
2811 if ((obj->write_domain & I915_GEM_GPU_DOMAINS) == 0) 2742 if ((obj->write_domain & I915_GEM_GPU_DOMAINS) == 0)
2812 return; 2743 return;
@@ -2814,7 +2745,7 @@ i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj)
2814 /* Queue the GPU write cache flushing we need. */ 2745 /* Queue the GPU write cache flushing we need. */
2815 old_write_domain = obj->write_domain; 2746 old_write_domain = obj->write_domain;
2816 i915_gem_flush(dev, 0, obj->write_domain); 2747 i915_gem_flush(dev, 0, obj->write_domain);
2817 (void) i915_add_request(dev, NULL, obj->write_domain); 2748 (void) i915_add_request(dev, NULL, obj->write_domain, obj_priv->ring);
2818 BUG_ON(obj->write_domain); 2749 BUG_ON(obj->write_domain);
2819 2750
2820 trace_i915_gem_object_change_domain(obj, 2751 trace_i915_gem_object_change_domain(obj,
@@ -2954,23 +2885,24 @@ i915_gem_object_set_to_display_plane(struct drm_gem_object *obj)
2954 DRM_INFO("%s: object %p wait for seqno %08x\n", 2885 DRM_INFO("%s: object %p wait for seqno %08x\n",
2955 __func__, obj, obj_priv->last_rendering_seqno); 2886 __func__, obj, obj_priv->last_rendering_seqno);
2956#endif 2887#endif
2957 ret = i915_do_wait_request(dev, obj_priv->last_rendering_seqno, 0); 2888 ret = i915_do_wait_request(dev,
2889 obj_priv->last_rendering_seqno,
2890 0,
2891 obj_priv->ring);
2958 if (ret != 0) 2892 if (ret != 0)
2959 return ret; 2893 return ret;
2960 } 2894 }
2961 2895
2896 i915_gem_object_flush_cpu_write_domain(obj);
2897
2962 old_write_domain = obj->write_domain; 2898 old_write_domain = obj->write_domain;
2963 old_read_domains = obj->read_domains; 2899 old_read_domains = obj->read_domains;
2964 2900
2965 obj->read_domains &= I915_GEM_DOMAIN_GTT;
2966
2967 i915_gem_object_flush_cpu_write_domain(obj);
2968
2969 /* It should now be out of any other write domains, and we can update 2901 /* It should now be out of any other write domains, and we can update
2970 * the domain values for our changes. 2902 * the domain values for our changes.
2971 */ 2903 */
2972 BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_GTT) != 0); 2904 BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_GTT) != 0);
2973 obj->read_domains |= I915_GEM_DOMAIN_GTT; 2905 obj->read_domains = I915_GEM_DOMAIN_GTT;
2974 obj->write_domain = I915_GEM_DOMAIN_GTT; 2906 obj->write_domain = I915_GEM_DOMAIN_GTT;
2975 obj_priv->dirty = 1; 2907 obj_priv->dirty = 1;
2976 2908
@@ -3354,9 +3286,13 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
3354 obj_priv->tiling_mode != I915_TILING_NONE; 3286 obj_priv->tiling_mode != I915_TILING_NONE;
3355 3287
3356 /* Check fence reg constraints and rebind if necessary */ 3288 /* Check fence reg constraints and rebind if necessary */
3357 if (need_fence && !i915_gem_object_fence_offset_ok(obj, 3289 if (need_fence &&
3358 obj_priv->tiling_mode)) 3290 !i915_gem_object_fence_offset_ok(obj,
3359 i915_gem_object_unbind(obj); 3291 obj_priv->tiling_mode)) {
3292 ret = i915_gem_object_unbind(obj);
3293 if (ret)
3294 return ret;
3295 }
3360 3296
3361 /* Choose the GTT offset for our buffer and put it there. */ 3297 /* Choose the GTT offset for our buffer and put it there. */
3362 ret = i915_gem_object_pin(obj, (uint32_t) entry->alignment); 3298 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,
3370 if (need_fence) { 3306 if (need_fence) {
3371 ret = i915_gem_object_get_fence_reg(obj); 3307 ret = i915_gem_object_get_fence_reg(obj);
3372 if (ret != 0) { 3308 if (ret != 0) {
3373 if (ret != -EBUSY && ret != -ERESTARTSYS)
3374 DRM_ERROR("Failure to install fence: %d\n",
3375 ret);
3376 i915_gem_object_unpin(obj); 3309 i915_gem_object_unpin(obj);
3377 return ret; 3310 return ret;
3378 } 3311 }
@@ -3545,62 +3478,6 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
3545 return 0; 3478 return 0;
3546} 3479}
3547 3480
3548/** Dispatch a batchbuffer to the ring
3549 */
3550static int
3551i915_dispatch_gem_execbuffer(struct drm_device *dev,
3552 struct drm_i915_gem_execbuffer2 *exec,
3553 struct drm_clip_rect *cliprects,
3554 uint64_t exec_offset)
3555{
3556 drm_i915_private_t *dev_priv = dev->dev_private;
3557 int nbox = exec->num_cliprects;
3558 int i = 0, count;
3559 uint32_t exec_start, exec_len;
3560 RING_LOCALS;
3561
3562 exec_start = (uint32_t) exec_offset + exec->batch_start_offset;
3563 exec_len = (uint32_t) exec->batch_len;
3564
3565 trace_i915_gem_request_submit(dev, dev_priv->mm.next_gem_seqno + 1);
3566
3567 count = nbox ? nbox : 1;
3568
3569 for (i = 0; i < count; i++) {
3570 if (i < nbox) {
3571 int ret = i915_emit_box(dev, cliprects, i,
3572 exec->DR1, exec->DR4);
3573 if (ret)
3574 return ret;
3575 }
3576
3577 if (IS_I830(dev) || IS_845G(dev)) {
3578 BEGIN_LP_RING(4);
3579 OUT_RING(MI_BATCH_BUFFER);
3580 OUT_RING(exec_start | MI_BATCH_NON_SECURE);
3581 OUT_RING(exec_start + exec_len - 4);
3582 OUT_RING(0);
3583 ADVANCE_LP_RING();
3584 } else {
3585 BEGIN_LP_RING(2);
3586 if (IS_I965G(dev)) {
3587 OUT_RING(MI_BATCH_BUFFER_START |
3588 (2 << 6) |
3589 MI_BATCH_NON_SECURE_I965);
3590 OUT_RING(exec_start);
3591 } else {
3592 OUT_RING(MI_BATCH_BUFFER_START |
3593 (2 << 6));
3594 OUT_RING(exec_start | MI_BATCH_NON_SECURE);
3595 }
3596 ADVANCE_LP_RING();
3597 }
3598 }
3599
3600 /* XXX breadcrumb */
3601 return 0;
3602}
3603
3604/* Throttle our rendering by waiting until the ring has completed our requests 3481/* Throttle our rendering by waiting until the ring has completed our requests
3605 * emitted over 20 msec ago. 3482 * emitted over 20 msec ago.
3606 * 3483 *
@@ -3629,7 +3506,7 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file_priv)
3629 if (time_after_eq(request->emitted_jiffies, recent_enough)) 3506 if (time_after_eq(request->emitted_jiffies, recent_enough))
3630 break; 3507 break;
3631 3508
3632 ret = i915_wait_request(dev, request->seqno); 3509 ret = i915_wait_request(dev, request->seqno, request->ring);
3633 if (ret != 0) 3510 if (ret != 0)
3634 break; 3511 break;
3635 } 3512 }
@@ -3786,10 +3663,22 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
3786 uint32_t seqno, flush_domains, reloc_index; 3663 uint32_t seqno, flush_domains, reloc_index;
3787 int pin_tries, flips; 3664 int pin_tries, flips;
3788 3665
3666 struct intel_ring_buffer *ring = NULL;
3667
3789#if WATCH_EXEC 3668#if WATCH_EXEC
3790 DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n", 3669 DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n",
3791 (int) args->buffers_ptr, args->buffer_count, args->batch_len); 3670 (int) args->buffers_ptr, args->buffer_count, args->batch_len);
3792#endif 3671#endif
3672 if (args->flags & I915_EXEC_BSD) {
3673 if (!HAS_BSD(dev)) {
3674 DRM_ERROR("execbuf with wrong flag\n");
3675 return -EINVAL;
3676 }
3677 ring = &dev_priv->bsd_ring;
3678 } else {
3679 ring = &dev_priv->render_ring;
3680 }
3681
3793 3682
3794 if (args->buffer_count < 1) { 3683 if (args->buffer_count < 1) {
3795 DRM_ERROR("execbuf with %d buffers\n", args->buffer_count); 3684 DRM_ERROR("execbuf with %d buffers\n", args->buffer_count);
@@ -3902,11 +3791,19 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
3902 if (ret != -ENOSPC || pin_tries >= 1) { 3791 if (ret != -ENOSPC || pin_tries >= 1) {
3903 if (ret != -ERESTARTSYS) { 3792 if (ret != -ERESTARTSYS) {
3904 unsigned long long total_size = 0; 3793 unsigned long long total_size = 0;
3905 for (i = 0; i < args->buffer_count; i++) 3794 int num_fences = 0;
3795 for (i = 0; i < args->buffer_count; i++) {
3796 obj_priv = object_list[i]->driver_private;
3797
3906 total_size += object_list[i]->size; 3798 total_size += object_list[i]->size;
3907 DRM_ERROR("Failed to pin buffer %d of %d, total %llu bytes: %d\n", 3799 num_fences +=
3800 exec_list[i].flags & EXEC_OBJECT_NEEDS_FENCE &&
3801 obj_priv->tiling_mode != I915_TILING_NONE;
3802 }
3803 DRM_ERROR("Failed to pin buffer %d of %d, total %llu bytes, %d fences: %d\n",
3908 pinned+1, args->buffer_count, 3804 pinned+1, args->buffer_count,
3909 total_size, ret); 3805 total_size, num_fences,
3806 ret);
3910 DRM_ERROR("%d objects [%d pinned], " 3807 DRM_ERROR("%d objects [%d pinned], "
3911 "%d object bytes [%d pinned], " 3808 "%d object bytes [%d pinned], "
3912 "%d/%d gtt bytes\n", 3809 "%d/%d gtt bytes\n",
@@ -3976,9 +3873,16 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
3976 i915_gem_flush(dev, 3873 i915_gem_flush(dev,
3977 dev->invalidate_domains, 3874 dev->invalidate_domains,
3978 dev->flush_domains); 3875 dev->flush_domains);
3979 if (dev->flush_domains & I915_GEM_GPU_DOMAINS) 3876 if (dev->flush_domains & I915_GEM_GPU_DOMAINS) {
3980 (void)i915_add_request(dev, file_priv, 3877 (void)i915_add_request(dev, file_priv,
3981 dev->flush_domains); 3878 dev->flush_domains,
3879 &dev_priv->render_ring);
3880
3881 if (HAS_BSD(dev))
3882 (void)i915_add_request(dev, file_priv,
3883 dev->flush_domains,
3884 &dev_priv->bsd_ring);
3885 }
3982 } 3886 }
3983 3887
3984 for (i = 0; i < args->buffer_count; i++) { 3888 for (i = 0; i < args->buffer_count; i++) {
@@ -4015,7 +3919,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
4015#endif 3919#endif
4016 3920
4017 /* Exec the batchbuffer */ 3921 /* Exec the batchbuffer */
4018 ret = i915_dispatch_gem_execbuffer(dev, args, cliprects, exec_offset); 3922 ret = ring->dispatch_gem_execbuffer(dev, ring, args,
3923 cliprects, exec_offset);
4019 if (ret) { 3924 if (ret) {
4020 DRM_ERROR("dispatch failed %d\n", ret); 3925 DRM_ERROR("dispatch failed %d\n", ret);
4021 goto err; 3926 goto err;
@@ -4025,7 +3930,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
4025 * Ensure that the commands in the batch buffer are 3930 * Ensure that the commands in the batch buffer are
4026 * finished before the interrupt fires 3931 * finished before the interrupt fires
4027 */ 3932 */
4028 flush_domains = i915_retire_commands(dev); 3933 flush_domains = i915_retire_commands(dev, ring);
4029 3934
4030 i915_verify_inactive(dev, __FILE__, __LINE__); 3935 i915_verify_inactive(dev, __FILE__, __LINE__);
4031 3936
@@ -4036,12 +3941,13 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
4036 * *some* interrupts representing completion of buffers that we can 3941 * *some* interrupts representing completion of buffers that we can
4037 * wait on when trying to clear up gtt space). 3942 * wait on when trying to clear up gtt space).
4038 */ 3943 */
4039 seqno = i915_add_request(dev, file_priv, flush_domains); 3944 seqno = i915_add_request(dev, file_priv, flush_domains, ring);
4040 BUG_ON(seqno == 0); 3945 BUG_ON(seqno == 0);
4041 for (i = 0; i < args->buffer_count; i++) { 3946 for (i = 0; i < args->buffer_count; i++) {
4042 struct drm_gem_object *obj = object_list[i]; 3947 struct drm_gem_object *obj = object_list[i];
3948 obj_priv = to_intel_bo(obj);
4043 3949
4044 i915_gem_object_move_to_active(obj, seqno); 3950 i915_gem_object_move_to_active(obj, seqno, ring);
4045#if WATCH_LRU 3951#if WATCH_LRU
4046 DRM_INFO("%s: move to exec list %p\n", __func__, obj); 3952 DRM_INFO("%s: move to exec list %p\n", __func__, obj);
4047#endif 3953#endif
@@ -4153,7 +4059,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
4153 exec2.DR4 = args->DR4; 4059 exec2.DR4 = args->DR4;
4154 exec2.num_cliprects = args->num_cliprects; 4060 exec2.num_cliprects = args->num_cliprects;
4155 exec2.cliprects_ptr = args->cliprects_ptr; 4061 exec2.cliprects_ptr = args->cliprects_ptr;
4156 exec2.flags = 0; 4062 exec2.flags = I915_EXEC_RENDER;
4157 4063
4158 ret = i915_gem_do_execbuffer(dev, data, file_priv, &exec2, exec2_list); 4064 ret = i915_gem_do_execbuffer(dev, data, file_priv, &exec2, exec2_list);
4159 if (!ret) { 4065 if (!ret) {
@@ -4239,7 +4145,20 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment)
4239 struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); 4145 struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
4240 int ret; 4146 int ret;
4241 4147
4148 BUG_ON(obj_priv->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT);
4149
4242 i915_verify_inactive(dev, __FILE__, __LINE__); 4150 i915_verify_inactive(dev, __FILE__, __LINE__);
4151
4152 if (obj_priv->gtt_space != NULL) {
4153 if (alignment == 0)
4154 alignment = i915_gem_get_gtt_alignment(obj);
4155 if (obj_priv->gtt_offset & (alignment - 1)) {
4156 ret = i915_gem_object_unbind(obj);
4157 if (ret)
4158 return ret;
4159 }
4160 }
4161
4243 if (obj_priv->gtt_space == NULL) { 4162 if (obj_priv->gtt_space == NULL) {
4244 ret = i915_gem_object_bind_to_gtt(obj, alignment); 4163 ret = i915_gem_object_bind_to_gtt(obj, alignment);
4245 if (ret) 4164 if (ret)
@@ -4392,6 +4311,7 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
4392 struct drm_i915_gem_busy *args = data; 4311 struct drm_i915_gem_busy *args = data;
4393 struct drm_gem_object *obj; 4312 struct drm_gem_object *obj;
4394 struct drm_i915_gem_object *obj_priv; 4313 struct drm_i915_gem_object *obj_priv;
4314 drm_i915_private_t *dev_priv = dev->dev_private;
4395 4315
4396 obj = drm_gem_object_lookup(dev, file_priv, args->handle); 4316 obj = drm_gem_object_lookup(dev, file_priv, args->handle);
4397 if (obj == NULL) { 4317 if (obj == NULL) {
@@ -4406,7 +4326,10 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
4406 * actually unmasked, and our working set ends up being larger than 4326 * actually unmasked, and our working set ends up being larger than
4407 * required. 4327 * required.
4408 */ 4328 */
4409 i915_gem_retire_requests(dev); 4329 i915_gem_retire_requests(dev, &dev_priv->render_ring);
4330
4331 if (HAS_BSD(dev))
4332 i915_gem_retire_requests(dev, &dev_priv->bsd_ring);
4410 4333
4411 obj_priv = to_intel_bo(obj); 4334 obj_priv = to_intel_bo(obj);
4412 /* Don't count being on the flushing list against the object being 4335 /* Don't count being on the flushing list against the object being
@@ -4573,7 +4496,10 @@ i915_gem_idle(struct drm_device *dev)
4573 4496
4574 mutex_lock(&dev->struct_mutex); 4497 mutex_lock(&dev->struct_mutex);
4575 4498
4576 if (dev_priv->mm.suspended || dev_priv->ring.ring_obj == NULL) { 4499 if (dev_priv->mm.suspended ||
4500 (dev_priv->render_ring.gem_object == NULL) ||
4501 (HAS_BSD(dev) &&
4502 dev_priv->bsd_ring.gem_object == NULL)) {
4577 mutex_unlock(&dev->struct_mutex); 4503 mutex_unlock(&dev->struct_mutex);
4578 return 0; 4504 return 0;
4579 } 4505 }
@@ -4654,71 +4580,6 @@ err:
4654 return ret; 4580 return ret;
4655} 4581}
4656 4582
4657static int
4658i915_gem_init_hws(struct drm_device *dev)
4659{
4660 drm_i915_private_t *dev_priv = dev->dev_private;
4661 struct drm_gem_object *obj;
4662 struct drm_i915_gem_object *obj_priv;
4663 int ret;
4664
4665 /* If we need a physical address for the status page, it's already
4666 * initialized at driver load time.
4667 */
4668 if (!I915_NEED_GFX_HWS(dev))
4669 return 0;
4670
4671 obj = i915_gem_alloc_object(dev, 4096);
4672 if (obj == NULL) {
4673 DRM_ERROR("Failed to allocate status page\n");
4674 ret = -ENOMEM;
4675 goto err;
4676 }
4677 obj_priv = to_intel_bo(obj);
4678 obj_priv->agp_type = AGP_USER_CACHED_MEMORY;
4679
4680 ret = i915_gem_object_pin(obj, 4096);
4681 if (ret != 0) {
4682 drm_gem_object_unreference(obj);
4683 goto err_unref;
4684 }
4685
4686 dev_priv->status_gfx_addr = obj_priv->gtt_offset;
4687
4688 dev_priv->hw_status_page = kmap(obj_priv->pages[0]);
4689 if (dev_priv->hw_status_page == NULL) {
4690 DRM_ERROR("Failed to map status page.\n");
4691 memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
4692 ret = -EINVAL;
4693 goto err_unpin;
4694 }
4695
4696 if (HAS_PIPE_CONTROL(dev)) {
4697 ret = i915_gem_init_pipe_control(dev);
4698 if (ret)
4699 goto err_unpin;
4700 }
4701
4702 dev_priv->hws_obj = obj;
4703 memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
4704 if (IS_GEN6(dev)) {
4705 I915_WRITE(HWS_PGA_GEN6, dev_priv->status_gfx_addr);
4706 I915_READ(HWS_PGA_GEN6); /* posting read */
4707 } else {
4708 I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
4709 I915_READ(HWS_PGA); /* posting read */
4710 }
4711 DRM_DEBUG_DRIVER("hws offset: 0x%08x\n", dev_priv->status_gfx_addr);
4712
4713 return 0;
4714
4715err_unpin:
4716 i915_gem_object_unpin(obj);
4717err_unref:
4718 drm_gem_object_unreference(obj);
4719err:
4720 return 0;
4721}
4722 4583
4723static void 4584static void
4724i915_gem_cleanup_pipe_control(struct drm_device *dev) 4585i915_gem_cleanup_pipe_control(struct drm_device *dev)
@@ -4737,146 +4598,46 @@ i915_gem_cleanup_pipe_control(struct drm_device *dev)
4737 dev_priv->seqno_page = NULL; 4598 dev_priv->seqno_page = NULL;
4738} 4599}
4739 4600
4740static void
4741i915_gem_cleanup_hws(struct drm_device *dev)
4742{
4743 drm_i915_private_t *dev_priv = dev->dev_private;
4744 struct drm_gem_object *obj;
4745 struct drm_i915_gem_object *obj_priv;
4746
4747 if (dev_priv->hws_obj == NULL)
4748 return;
4749
4750 obj = dev_priv->hws_obj;
4751 obj_priv = to_intel_bo(obj);
4752
4753 kunmap(obj_priv->pages[0]);
4754 i915_gem_object_unpin(obj);
4755 drm_gem_object_unreference(obj);
4756 dev_priv->hws_obj = NULL;
4757
4758 memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
4759 dev_priv->hw_status_page = NULL;
4760
4761 if (HAS_PIPE_CONTROL(dev))
4762 i915_gem_cleanup_pipe_control(dev);
4763
4764 /* Write high address into HWS_PGA when disabling. */
4765 I915_WRITE(HWS_PGA, 0x1ffff000);
4766}
4767
4768int 4601int
4769i915_gem_init_ringbuffer(struct drm_device *dev) 4602i915_gem_init_ringbuffer(struct drm_device *dev)
4770{ 4603{
4771 drm_i915_private_t *dev_priv = dev->dev_private; 4604 drm_i915_private_t *dev_priv = dev->dev_private;
4772 struct drm_gem_object *obj;
4773 struct drm_i915_gem_object *obj_priv;
4774 drm_i915_ring_buffer_t *ring = &dev_priv->ring;
4775 int ret; 4605 int ret;
4776 u32 head;
4777
4778 ret = i915_gem_init_hws(dev);
4779 if (ret != 0)
4780 return ret;
4781 4606
4782 obj = i915_gem_alloc_object(dev, 128 * 1024); 4607 dev_priv->render_ring = render_ring;
4783 if (obj == NULL) {
4784 DRM_ERROR("Failed to allocate ringbuffer\n");
4785 i915_gem_cleanup_hws(dev);
4786 return -ENOMEM;
4787 }
4788 obj_priv = to_intel_bo(obj);
4789 4608
4790 ret = i915_gem_object_pin(obj, 4096); 4609 if (!I915_NEED_GFX_HWS(dev)) {
4791 if (ret != 0) { 4610 dev_priv->render_ring.status_page.page_addr
4792 drm_gem_object_unreference(obj); 4611 = dev_priv->status_page_dmah->vaddr;
4793 i915_gem_cleanup_hws(dev); 4612 memset(dev_priv->render_ring.status_page.page_addr,
4794 return ret; 4613 0, PAGE_SIZE);
4795 } 4614 }
4796 4615
4797 /* Set up the kernel mapping for the ring. */ 4616 if (HAS_PIPE_CONTROL(dev)) {
4798 ring->Size = obj->size; 4617 ret = i915_gem_init_pipe_control(dev);
4799 4618 if (ret)
4800 ring->map.offset = dev->agp->base + obj_priv->gtt_offset; 4619 return ret;
4801 ring->map.size = obj->size;
4802 ring->map.type = 0;
4803 ring->map.flags = 0;
4804 ring->map.mtrr = 0;
4805
4806 drm_core_ioremap_wc(&ring->map, dev);
4807 if (ring->map.handle == NULL) {
4808 DRM_ERROR("Failed to map ringbuffer.\n");
4809 memset(&dev_priv->ring, 0, sizeof(dev_priv->ring));
4810 i915_gem_object_unpin(obj);
4811 drm_gem_object_unreference(obj);
4812 i915_gem_cleanup_hws(dev);
4813 return -EINVAL;
4814 }
4815 ring->ring_obj = obj;
4816 ring->virtual_start = ring->map.handle;
4817
4818 /* Stop the ring if it's running. */
4819 I915_WRITE(PRB0_CTL, 0);
4820 I915_WRITE(PRB0_TAIL, 0);
4821 I915_WRITE(PRB0_HEAD, 0);
4822
4823 /* Initialize the ring. */
4824 I915_WRITE(PRB0_START, obj_priv->gtt_offset);
4825 head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
4826
4827 /* G45 ring initialization fails to reset head to zero */
4828 if (head != 0) {
4829 DRM_ERROR("Ring head not reset to zero "
4830 "ctl %08x head %08x tail %08x start %08x\n",
4831 I915_READ(PRB0_CTL),
4832 I915_READ(PRB0_HEAD),
4833 I915_READ(PRB0_TAIL),
4834 I915_READ(PRB0_START));
4835 I915_WRITE(PRB0_HEAD, 0);
4836
4837 DRM_ERROR("Ring head forced to zero "
4838 "ctl %08x head %08x tail %08x start %08x\n",
4839 I915_READ(PRB0_CTL),
4840 I915_READ(PRB0_HEAD),
4841 I915_READ(PRB0_TAIL),
4842 I915_READ(PRB0_START));
4843 }
4844
4845 I915_WRITE(PRB0_CTL,
4846 ((obj->size - 4096) & RING_NR_PAGES) |
4847 RING_NO_REPORT |
4848 RING_VALID);
4849
4850 head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
4851
4852 /* If the head is still not zero, the ring is dead */
4853 if (head != 0) {
4854 DRM_ERROR("Ring initialization failed "
4855 "ctl %08x head %08x tail %08x start %08x\n",
4856 I915_READ(PRB0_CTL),
4857 I915_READ(PRB0_HEAD),
4858 I915_READ(PRB0_TAIL),
4859 I915_READ(PRB0_START));
4860 return -EIO;
4861 } 4620 }
4862 4621
4863 /* Update our cache of the ring state */ 4622 ret = intel_init_ring_buffer(dev, &dev_priv->render_ring);
4864 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 4623 if (ret)
4865 i915_kernel_lost_context(dev); 4624 goto cleanup_pipe_control;
4866 else {
4867 ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
4868 ring->tail = I915_READ(PRB0_TAIL) & TAIL_ADDR;
4869 ring->space = ring->head - (ring->tail + 8);
4870 if (ring->space < 0)
4871 ring->space += ring->Size;
4872 }
4873 4625
4874 if (IS_I9XX(dev) && !IS_GEN3(dev)) { 4626 if (HAS_BSD(dev)) {
4875 I915_WRITE(MI_MODE, 4627 dev_priv->bsd_ring = bsd_ring;
4876 (VS_TIMER_DISPATCH) << 16 | VS_TIMER_DISPATCH); 4628 ret = intel_init_ring_buffer(dev, &dev_priv->bsd_ring);
4629 if (ret)
4630 goto cleanup_render_ring;
4877 } 4631 }
4878 4632
4879 return 0; 4633 return 0;
4634
4635cleanup_render_ring:
4636 intel_cleanup_ring_buffer(dev, &dev_priv->render_ring);
4637cleanup_pipe_control:
4638 if (HAS_PIPE_CONTROL(dev))
4639 i915_gem_cleanup_pipe_control(dev);
4640 return ret;
4880} 4641}
4881 4642
4882void 4643void
@@ -4884,17 +4645,11 @@ i915_gem_cleanup_ringbuffer(struct drm_device *dev)
4884{ 4645{
4885 drm_i915_private_t *dev_priv = dev->dev_private; 4646 drm_i915_private_t *dev_priv = dev->dev_private;
4886 4647
4887 if (dev_priv->ring.ring_obj == NULL) 4648 intel_cleanup_ring_buffer(dev, &dev_priv->render_ring);
4888 return; 4649 if (HAS_BSD(dev))
4889 4650 intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring);
4890 drm_core_ioremapfree(&dev_priv->ring.map, dev); 4651 if (HAS_PIPE_CONTROL(dev))
4891 4652 i915_gem_cleanup_pipe_control(dev);
4892 i915_gem_object_unpin(dev_priv->ring.ring_obj);
4893 drm_gem_object_unreference(dev_priv->ring.ring_obj);
4894 dev_priv->ring.ring_obj = NULL;
4895 memset(&dev_priv->ring, 0, sizeof(dev_priv->ring));
4896
4897 i915_gem_cleanup_hws(dev);
4898} 4653}
4899 4654
4900int 4655int
@@ -4922,12 +4677,14 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
4922 } 4677 }
4923 4678
4924 spin_lock(&dev_priv->mm.active_list_lock); 4679 spin_lock(&dev_priv->mm.active_list_lock);
4925 BUG_ON(!list_empty(&dev_priv->mm.active_list)); 4680 BUG_ON(!list_empty(&dev_priv->render_ring.active_list));
4681 BUG_ON(HAS_BSD(dev) && !list_empty(&dev_priv->bsd_ring.active_list));
4926 spin_unlock(&dev_priv->mm.active_list_lock); 4682 spin_unlock(&dev_priv->mm.active_list_lock);
4927 4683
4928 BUG_ON(!list_empty(&dev_priv->mm.flushing_list)); 4684 BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
4929 BUG_ON(!list_empty(&dev_priv->mm.inactive_list)); 4685 BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
4930 BUG_ON(!list_empty(&dev_priv->mm.request_list)); 4686 BUG_ON(!list_empty(&dev_priv->render_ring.request_list));
4687 BUG_ON(HAS_BSD(dev) && !list_empty(&dev_priv->bsd_ring.request_list));
4931 mutex_unlock(&dev->struct_mutex); 4688 mutex_unlock(&dev->struct_mutex);
4932 4689
4933 drm_irq_install(dev); 4690 drm_irq_install(dev);
@@ -4966,18 +4723,20 @@ i915_gem_load(struct drm_device *dev)
4966 drm_i915_private_t *dev_priv = dev->dev_private; 4723 drm_i915_private_t *dev_priv = dev->dev_private;
4967 4724
4968 spin_lock_init(&dev_priv->mm.active_list_lock); 4725 spin_lock_init(&dev_priv->mm.active_list_lock);
4969 INIT_LIST_HEAD(&dev_priv->mm.active_list);
4970 INIT_LIST_HEAD(&dev_priv->mm.flushing_list); 4726 INIT_LIST_HEAD(&dev_priv->mm.flushing_list);
4971 INIT_LIST_HEAD(&dev_priv->mm.gpu_write_list); 4727 INIT_LIST_HEAD(&dev_priv->mm.gpu_write_list);
4972 INIT_LIST_HEAD(&dev_priv->mm.inactive_list); 4728 INIT_LIST_HEAD(&dev_priv->mm.inactive_list);
4973 INIT_LIST_HEAD(&dev_priv->mm.request_list);
4974 INIT_LIST_HEAD(&dev_priv->mm.fence_list); 4729 INIT_LIST_HEAD(&dev_priv->mm.fence_list);
4730 INIT_LIST_HEAD(&dev_priv->render_ring.active_list);
4731 INIT_LIST_HEAD(&dev_priv->render_ring.request_list);
4732 if (HAS_BSD(dev)) {
4733 INIT_LIST_HEAD(&dev_priv->bsd_ring.active_list);
4734 INIT_LIST_HEAD(&dev_priv->bsd_ring.request_list);
4735 }
4975 for (i = 0; i < 16; i++) 4736 for (i = 0; i < 16; i++)
4976 INIT_LIST_HEAD(&dev_priv->fence_regs[i].lru_list); 4737 INIT_LIST_HEAD(&dev_priv->fence_regs[i].lru_list);
4977 INIT_DELAYED_WORK(&dev_priv->mm.retire_work, 4738 INIT_DELAYED_WORK(&dev_priv->mm.retire_work,
4978 i915_gem_retire_work_handler); 4739 i915_gem_retire_work_handler);
4979 dev_priv->mm.next_gem_seqno = 1;
4980
4981 spin_lock(&shrink_list_lock); 4740 spin_lock(&shrink_list_lock);
4982 list_add(&dev_priv->mm.shrink_list, &shrink_list); 4741 list_add(&dev_priv->mm.shrink_list, &shrink_list);
4983 spin_unlock(&shrink_list_lock); 4742 spin_unlock(&shrink_list_lock);
@@ -5209,7 +4968,9 @@ i915_gpu_is_active(struct drm_device *dev)
5209 4968
5210 spin_lock(&dev_priv->mm.active_list_lock); 4969 spin_lock(&dev_priv->mm.active_list_lock);
5211 lists_empty = list_empty(&dev_priv->mm.flushing_list) && 4970 lists_empty = list_empty(&dev_priv->mm.flushing_list) &&
5212 list_empty(&dev_priv->mm.active_list); 4971 list_empty(&dev_priv->render_ring.active_list);
4972 if (HAS_BSD(dev))
4973 lists_empty &= list_empty(&dev_priv->bsd_ring.active_list);
5213 spin_unlock(&dev_priv->mm.active_list_lock); 4974 spin_unlock(&dev_priv->mm.active_list_lock);
5214 4975
5215 return !lists_empty; 4976 return !lists_empty;
@@ -5254,8 +5015,10 @@ rescan:
5254 continue; 5015 continue;
5255 5016
5256 spin_unlock(&shrink_list_lock); 5017 spin_unlock(&shrink_list_lock);
5018 i915_gem_retire_requests(dev, &dev_priv->render_ring);
5257 5019
5258 i915_gem_retire_requests(dev); 5020 if (HAS_BSD(dev))
5021 i915_gem_retire_requests(dev, &dev_priv->bsd_ring);
5259 5022
5260 list_for_each_entry_safe(obj_priv, next_obj, 5023 list_for_each_entry_safe(obj_priv, next_obj,
5261 &dev_priv->mm.inactive_list, 5024 &dev_priv->mm.inactive_list,
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 8c3f0802686d..2479be001e40 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -53,7 +53,7 @@
53 I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) 53 I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT)
54 54
55/** Interrupts that we mask and unmask at runtime. */ 55/** Interrupts that we mask and unmask at runtime. */
56#define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT) 56#define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT | I915_BSD_USER_INTERRUPT)
57 57
58#define I915_PIPE_VBLANK_STATUS (PIPE_START_VBLANK_INTERRUPT_STATUS |\ 58#define I915_PIPE_VBLANK_STATUS (PIPE_START_VBLANK_INTERRUPT_STATUS |\
59 PIPE_VBLANK_INTERRUPT_STATUS) 59 PIPE_VBLANK_INTERRUPT_STATUS)
@@ -74,7 +74,7 @@ ironlake_enable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask)
74 } 74 }
75} 75}
76 76
77static inline void 77void
78ironlake_disable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask) 78ironlake_disable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask)
79{ 79{
80 if ((dev_priv->gt_irq_mask_reg & mask) != mask) { 80 if ((dev_priv->gt_irq_mask_reg & mask) != mask) {
@@ -115,7 +115,7 @@ i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask)
115 } 115 }
116} 116}
117 117
118static inline void 118void
119i915_disable_irq(drm_i915_private_t *dev_priv, u32 mask) 119i915_disable_irq(drm_i915_private_t *dev_priv, u32 mask)
120{ 120{
121 if ((dev_priv->irq_mask_reg & mask) != mask) { 121 if ((dev_priv->irq_mask_reg & mask) != mask) {
@@ -278,10 +278,9 @@ static void i915_handle_rps_change(struct drm_device *dev)
278{ 278{
279 drm_i915_private_t *dev_priv = dev->dev_private; 279 drm_i915_private_t *dev_priv = dev->dev_private;
280 u32 busy_up, busy_down, max_avg, min_avg; 280 u32 busy_up, busy_down, max_avg, min_avg;
281 u16 rgvswctl;
282 u8 new_delay = dev_priv->cur_delay; 281 u8 new_delay = dev_priv->cur_delay;
283 282
284 I915_WRITE(MEMINTRSTS, I915_READ(MEMINTRSTS) & ~MEMINT_EVAL_CHG); 283 I915_WRITE16(MEMINTRSTS, MEMINT_EVAL_CHG);
285 busy_up = I915_READ(RCPREVBSYTUPAVG); 284 busy_up = I915_READ(RCPREVBSYTUPAVG);
286 busy_down = I915_READ(RCPREVBSYTDNAVG); 285 busy_down = I915_READ(RCPREVBSYTDNAVG);
287 max_avg = I915_READ(RCBMAXAVG); 286 max_avg = I915_READ(RCBMAXAVG);
@@ -300,27 +299,8 @@ static void i915_handle_rps_change(struct drm_device *dev)
300 new_delay = dev_priv->min_delay; 299 new_delay = dev_priv->min_delay;
301 } 300 }
302 301
303 DRM_DEBUG("rps change requested: %d -> %d\n", 302 if (ironlake_set_drps(dev, new_delay))
304 dev_priv->cur_delay, new_delay); 303 dev_priv->cur_delay = new_delay;
305
306 rgvswctl = I915_READ(MEMSWCTL);
307 if (rgvswctl & MEMCTL_CMD_STS) {
308 DRM_ERROR("gpu busy, RCS change rejected\n");
309 return; /* still busy with another command */
310 }
311
312 /* Program the new state */
313 rgvswctl = (MEMCTL_CMD_CHFREQ << MEMCTL_CMD_SHIFT) |
314 (new_delay << MEMCTL_FREQ_SHIFT) | MEMCTL_SFCAVM;
315 I915_WRITE(MEMSWCTL, rgvswctl);
316 POSTING_READ(MEMSWCTL);
317
318 rgvswctl |= MEMCTL_CMD_STS;
319 I915_WRITE(MEMSWCTL, rgvswctl);
320
321 dev_priv->cur_delay = new_delay;
322
323 DRM_DEBUG("rps changed\n");
324 304
325 return; 305 return;
326} 306}
@@ -331,6 +311,7 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev)
331 int ret = IRQ_NONE; 311 int ret = IRQ_NONE;
332 u32 de_iir, gt_iir, de_ier, pch_iir; 312 u32 de_iir, gt_iir, de_ier, pch_iir;
333 struct drm_i915_master_private *master_priv; 313 struct drm_i915_master_private *master_priv;
314 struct intel_ring_buffer *render_ring = &dev_priv->render_ring;
334 315
335 /* disable master interrupt before clearing iir */ 316 /* disable master interrupt before clearing iir */
336 de_ier = I915_READ(DEIER); 317 de_ier = I915_READ(DEIER);
@@ -354,13 +335,16 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev)
354 } 335 }
355 336
356 if (gt_iir & GT_PIPE_NOTIFY) { 337 if (gt_iir & GT_PIPE_NOTIFY) {
357 u32 seqno = i915_get_gem_seqno(dev); 338 u32 seqno = render_ring->get_gem_seqno(dev, render_ring);
358 dev_priv->mm.irq_gem_seqno = seqno; 339 render_ring->irq_gem_seqno = seqno;
359 trace_i915_gem_request_complete(dev, seqno); 340 trace_i915_gem_request_complete(dev, seqno);
360 DRM_WAKEUP(&dev_priv->irq_queue); 341 DRM_WAKEUP(&dev_priv->render_ring.irq_queue);
361 dev_priv->hangcheck_count = 0; 342 dev_priv->hangcheck_count = 0;
362 mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); 343 mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD);
363 } 344 }
345 if (gt_iir & GT_BSD_USER_INTERRUPT)
346 DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue);
347
364 348
365 if (de_iir & DE_GSE) 349 if (de_iir & DE_GSE)
366 ironlake_opregion_gse_intr(dev); 350 ironlake_opregion_gse_intr(dev);
@@ -388,7 +372,7 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev)
388 } 372 }
389 373
390 if (de_iir & DE_PCU_EVENT) { 374 if (de_iir & DE_PCU_EVENT) {
391 I915_WRITE(MEMINTRSTS, I915_READ(MEMINTRSTS)); 375 I915_WRITE16(MEMINTRSTS, I915_READ(MEMINTRSTS));
392 i915_handle_rps_change(dev); 376 i915_handle_rps_change(dev);
393 } 377 }
394 378
@@ -536,17 +520,18 @@ i915_ringbuffer_last_batch(struct drm_device *dev)
536 */ 520 */
537 bbaddr = 0; 521 bbaddr = 0;
538 head = I915_READ(PRB0_HEAD) & HEAD_ADDR; 522 head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
539 ring = (u32 *)(dev_priv->ring.virtual_start + head); 523 ring = (u32 *)(dev_priv->render_ring.virtual_start + head);
540 524
541 while (--ring >= (u32 *)dev_priv->ring.virtual_start) { 525 while (--ring >= (u32 *)dev_priv->render_ring.virtual_start) {
542 bbaddr = i915_get_bbaddr(dev, ring); 526 bbaddr = i915_get_bbaddr(dev, ring);
543 if (bbaddr) 527 if (bbaddr)
544 break; 528 break;
545 } 529 }
546 530
547 if (bbaddr == 0) { 531 if (bbaddr == 0) {
548 ring = (u32 *)(dev_priv->ring.virtual_start + dev_priv->ring.Size); 532 ring = (u32 *)(dev_priv->render_ring.virtual_start
549 while (--ring >= (u32 *)dev_priv->ring.virtual_start) { 533 + dev_priv->render_ring.size);
534 while (--ring >= (u32 *)dev_priv->render_ring.virtual_start) {
550 bbaddr = i915_get_bbaddr(dev, ring); 535 bbaddr = i915_get_bbaddr(dev, ring);
551 if (bbaddr) 536 if (bbaddr)
552 break; 537 break;
@@ -587,7 +572,7 @@ static void i915_capture_error_state(struct drm_device *dev)
587 return; 572 return;
588 } 573 }
589 574
590 error->seqno = i915_get_gem_seqno(dev); 575 error->seqno = i915_get_gem_seqno(dev, &dev_priv->render_ring);
591 error->eir = I915_READ(EIR); 576 error->eir = I915_READ(EIR);
592 error->pgtbl_er = I915_READ(PGTBL_ER); 577 error->pgtbl_er = I915_READ(PGTBL_ER);
593 error->pipeastat = I915_READ(PIPEASTAT); 578 error->pipeastat = I915_READ(PIPEASTAT);
@@ -615,7 +600,9 @@ static void i915_capture_error_state(struct drm_device *dev)
615 batchbuffer[0] = NULL; 600 batchbuffer[0] = NULL;
616 batchbuffer[1] = NULL; 601 batchbuffer[1] = NULL;
617 count = 0; 602 count = 0;
618 list_for_each_entry(obj_priv, &dev_priv->mm.active_list, list) { 603 list_for_each_entry(obj_priv,
604 &dev_priv->render_ring.active_list, list) {
605
619 struct drm_gem_object *obj = &obj_priv->base; 606 struct drm_gem_object *obj = &obj_priv->base;
620 607
621 if (batchbuffer[0] == NULL && 608 if (batchbuffer[0] == NULL &&
@@ -639,7 +626,8 @@ static void i915_capture_error_state(struct drm_device *dev)
639 error->batchbuffer[1] = i915_error_object_create(dev, batchbuffer[1]); 626 error->batchbuffer[1] = i915_error_object_create(dev, batchbuffer[1]);
640 627
641 /* Record the ringbuffer */ 628 /* Record the ringbuffer */
642 error->ringbuffer = i915_error_object_create(dev, dev_priv->ring.ring_obj); 629 error->ringbuffer = i915_error_object_create(dev,
630 dev_priv->render_ring.gem_object);
643 631
644 /* Record buffers on the active list. */ 632 /* Record buffers on the active list. */
645 error->active_bo = NULL; 633 error->active_bo = NULL;
@@ -651,7 +639,8 @@ static void i915_capture_error_state(struct drm_device *dev)
651 639
652 if (error->active_bo) { 640 if (error->active_bo) {
653 int i = 0; 641 int i = 0;
654 list_for_each_entry(obj_priv, &dev_priv->mm.active_list, list) { 642 list_for_each_entry(obj_priv,
643 &dev_priv->render_ring.active_list, list) {
655 struct drm_gem_object *obj = &obj_priv->base; 644 struct drm_gem_object *obj = &obj_priv->base;
656 645
657 error->active_bo[i].size = obj->size; 646 error->active_bo[i].size = obj->size;
@@ -703,24 +692,13 @@ void i915_destroy_error_state(struct drm_device *dev)
703 i915_error_state_free(dev, error); 692 i915_error_state_free(dev, error);
704} 693}
705 694
706/** 695static void i915_report_and_clear_eir(struct drm_device *dev)
707 * i915_handle_error - handle an error interrupt
708 * @dev: drm device
709 *
710 * Do some basic checking of regsiter state at error interrupt time and
711 * dump it to the syslog. Also call i915_capture_error_state() to make
712 * sure we get a record and make it available in debugfs. Fire a uevent
713 * so userspace knows something bad happened (should trigger collection
714 * of a ring dump etc.).
715 */
716static void i915_handle_error(struct drm_device *dev, bool wedged)
717{ 696{
718 struct drm_i915_private *dev_priv = dev->dev_private; 697 struct drm_i915_private *dev_priv = dev->dev_private;
719 u32 eir = I915_READ(EIR); 698 u32 eir = I915_READ(EIR);
720 u32 pipea_stats = I915_READ(PIPEASTAT);
721 u32 pipeb_stats = I915_READ(PIPEBSTAT);
722 699
723 i915_capture_error_state(dev); 700 if (!eir)
701 return;
724 702
725 printk(KERN_ERR "render error detected, EIR: 0x%08x\n", 703 printk(KERN_ERR "render error detected, EIR: 0x%08x\n",
726 eir); 704 eir);
@@ -766,6 +744,9 @@ static void i915_handle_error(struct drm_device *dev, bool wedged)
766 } 744 }
767 745
768 if (eir & I915_ERROR_MEMORY_REFRESH) { 746 if (eir & I915_ERROR_MEMORY_REFRESH) {
747 u32 pipea_stats = I915_READ(PIPEASTAT);
748 u32 pipeb_stats = I915_READ(PIPEBSTAT);
749
769 printk(KERN_ERR "memory refresh error\n"); 750 printk(KERN_ERR "memory refresh error\n");
770 printk(KERN_ERR "PIPEASTAT: 0x%08x\n", 751 printk(KERN_ERR "PIPEASTAT: 0x%08x\n",
771 pipea_stats); 752 pipea_stats);
@@ -822,6 +803,24 @@ static void i915_handle_error(struct drm_device *dev, bool wedged)
822 I915_WRITE(EMR, I915_READ(EMR) | eir); 803 I915_WRITE(EMR, I915_READ(EMR) | eir);
823 I915_WRITE(IIR, I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT); 804 I915_WRITE(IIR, I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT);
824 } 805 }
806}
807
808/**
809 * i915_handle_error - handle an error interrupt
810 * @dev: drm device
811 *
812 * Do some basic checking of regsiter state at error interrupt time and
813 * dump it to the syslog. Also call i915_capture_error_state() to make
814 * sure we get a record and make it available in debugfs. Fire a uevent
815 * so userspace knows something bad happened (should trigger collection
816 * of a ring dump etc.).
817 */
818static void i915_handle_error(struct drm_device *dev, bool wedged)
819{
820 struct drm_i915_private *dev_priv = dev->dev_private;
821
822 i915_capture_error_state(dev);
823 i915_report_and_clear_eir(dev);
825 824
826 if (wedged) { 825 if (wedged) {
827 atomic_set(&dev_priv->mm.wedged, 1); 826 atomic_set(&dev_priv->mm.wedged, 1);
@@ -829,7 +828,7 @@ static void i915_handle_error(struct drm_device *dev, bool wedged)
829 /* 828 /*
830 * Wakeup waiting processes so they don't hang 829 * Wakeup waiting processes so they don't hang
831 */ 830 */
832 DRM_WAKEUP(&dev_priv->irq_queue); 831 DRM_WAKEUP(&dev_priv->render_ring.irq_queue);
833 } 832 }
834 833
835 queue_work(dev_priv->wq, &dev_priv->error_work); 834 queue_work(dev_priv->wq, &dev_priv->error_work);
@@ -848,6 +847,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
848 unsigned long irqflags; 847 unsigned long irqflags;
849 int irq_received; 848 int irq_received;
850 int ret = IRQ_NONE; 849 int ret = IRQ_NONE;
850 struct intel_ring_buffer *render_ring = &dev_priv->render_ring;
851 851
852 atomic_inc(&dev_priv->irq_received); 852 atomic_inc(&dev_priv->irq_received);
853 853
@@ -928,14 +928,18 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
928 } 928 }
929 929
930 if (iir & I915_USER_INTERRUPT) { 930 if (iir & I915_USER_INTERRUPT) {
931 u32 seqno = i915_get_gem_seqno(dev); 931 u32 seqno =
932 dev_priv->mm.irq_gem_seqno = seqno; 932 render_ring->get_gem_seqno(dev, render_ring);
933 render_ring->irq_gem_seqno = seqno;
933 trace_i915_gem_request_complete(dev, seqno); 934 trace_i915_gem_request_complete(dev, seqno);
934 DRM_WAKEUP(&dev_priv->irq_queue); 935 DRM_WAKEUP(&dev_priv->render_ring.irq_queue);
935 dev_priv->hangcheck_count = 0; 936 dev_priv->hangcheck_count = 0;
936 mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); 937 mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD);
937 } 938 }
938 939
940 if (HAS_BSD(dev) && (iir & I915_BSD_USER_INTERRUPT))
941 DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue);
942
939 if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) 943 if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT)
940 intel_prepare_page_flip(dev, 0); 944 intel_prepare_page_flip(dev, 0);
941 945
@@ -984,7 +988,6 @@ static int i915_emit_irq(struct drm_device * dev)
984{ 988{
985 drm_i915_private_t *dev_priv = dev->dev_private; 989 drm_i915_private_t *dev_priv = dev->dev_private;
986 struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; 990 struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
987 RING_LOCALS;
988 991
989 i915_kernel_lost_context(dev); 992 i915_kernel_lost_context(dev);
990 993
@@ -1006,43 +1009,13 @@ static int i915_emit_irq(struct drm_device * dev)
1006 return dev_priv->counter; 1009 return dev_priv->counter;
1007} 1010}
1008 1011
1009void i915_user_irq_get(struct drm_device *dev)
1010{
1011 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
1012 unsigned long irqflags;
1013
1014 spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
1015 if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1)) {
1016 if (HAS_PCH_SPLIT(dev))
1017 ironlake_enable_graphics_irq(dev_priv, GT_PIPE_NOTIFY);
1018 else
1019 i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
1020 }
1021 spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
1022}
1023
1024void i915_user_irq_put(struct drm_device *dev)
1025{
1026 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
1027 unsigned long irqflags;
1028
1029 spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
1030 BUG_ON(dev->irq_enabled && dev_priv->user_irq_refcount <= 0);
1031 if (dev->irq_enabled && (--dev_priv->user_irq_refcount == 0)) {
1032 if (HAS_PCH_SPLIT(dev))
1033 ironlake_disable_graphics_irq(dev_priv, GT_PIPE_NOTIFY);
1034 else
1035 i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
1036 }
1037 spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
1038}
1039
1040void i915_trace_irq_get(struct drm_device *dev, u32 seqno) 1012void i915_trace_irq_get(struct drm_device *dev, u32 seqno)
1041{ 1013{
1042 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 1014 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
1015 struct intel_ring_buffer *render_ring = &dev_priv->render_ring;
1043 1016
1044 if (dev_priv->trace_irq_seqno == 0) 1017 if (dev_priv->trace_irq_seqno == 0)
1045 i915_user_irq_get(dev); 1018 render_ring->user_irq_get(dev, render_ring);
1046 1019
1047 dev_priv->trace_irq_seqno = seqno; 1020 dev_priv->trace_irq_seqno = seqno;
1048} 1021}
@@ -1052,6 +1025,7 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr)
1052 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 1025 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
1053 struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; 1026 struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
1054 int ret = 0; 1027 int ret = 0;
1028 struct intel_ring_buffer *render_ring = &dev_priv->render_ring;
1055 1029
1056 DRM_DEBUG_DRIVER("irq_nr=%d breadcrumb=%d\n", irq_nr, 1030 DRM_DEBUG_DRIVER("irq_nr=%d breadcrumb=%d\n", irq_nr,
1057 READ_BREADCRUMB(dev_priv)); 1031 READ_BREADCRUMB(dev_priv));
@@ -1065,10 +1039,10 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr)
1065 if (master_priv->sarea_priv) 1039 if (master_priv->sarea_priv)
1066 master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; 1040 master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
1067 1041
1068 i915_user_irq_get(dev); 1042 render_ring->user_irq_get(dev, render_ring);
1069 DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ, 1043 DRM_WAIT_ON(ret, dev_priv->render_ring.irq_queue, 3 * DRM_HZ,
1070 READ_BREADCRUMB(dev_priv) >= irq_nr); 1044 READ_BREADCRUMB(dev_priv) >= irq_nr);
1071 i915_user_irq_put(dev); 1045 render_ring->user_irq_put(dev, render_ring);
1072 1046
1073 if (ret == -EBUSY) { 1047 if (ret == -EBUSY) {
1074 DRM_ERROR("EBUSY -- rec: %d emitted: %d\n", 1048 DRM_ERROR("EBUSY -- rec: %d emitted: %d\n",
@@ -1087,7 +1061,7 @@ int i915_irq_emit(struct drm_device *dev, void *data,
1087 drm_i915_irq_emit_t *emit = data; 1061 drm_i915_irq_emit_t *emit = data;
1088 int result; 1062 int result;
1089 1063
1090 if (!dev_priv || !dev_priv->ring.virtual_start) { 1064 if (!dev_priv || !dev_priv->render_ring.virtual_start) {
1091 DRM_ERROR("called with no initialization\n"); 1065 DRM_ERROR("called with no initialization\n");
1092 return -EINVAL; 1066 return -EINVAL;
1093 } 1067 }
@@ -1233,9 +1207,12 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
1233 return -EINVAL; 1207 return -EINVAL;
1234} 1208}
1235 1209
1236struct drm_i915_gem_request *i915_get_tail_request(struct drm_device *dev) { 1210struct drm_i915_gem_request *
1211i915_get_tail_request(struct drm_device *dev)
1212{
1237 drm_i915_private_t *dev_priv = dev->dev_private; 1213 drm_i915_private_t *dev_priv = dev->dev_private;
1238 return list_entry(dev_priv->mm.request_list.prev, struct drm_i915_gem_request, list); 1214 return list_entry(dev_priv->render_ring.request_list.prev,
1215 struct drm_i915_gem_request, list);
1239} 1216}
1240 1217
1241/** 1218/**
@@ -1260,8 +1237,10 @@ void i915_hangcheck_elapsed(unsigned long data)
1260 acthd = I915_READ(ACTHD_I965); 1237 acthd = I915_READ(ACTHD_I965);
1261 1238
1262 /* If all work is done then ACTHD clearly hasn't advanced. */ 1239 /* If all work is done then ACTHD clearly hasn't advanced. */
1263 if (list_empty(&dev_priv->mm.request_list) || 1240 if (list_empty(&dev_priv->render_ring.request_list) ||
1264 i915_seqno_passed(i915_get_gem_seqno(dev), i915_get_tail_request(dev)->seqno)) { 1241 i915_seqno_passed(i915_get_gem_seqno(dev,
1242 &dev_priv->render_ring),
1243 i915_get_tail_request(dev)->seqno)) {
1265 dev_priv->hangcheck_count = 0; 1244 dev_priv->hangcheck_count = 0;
1266 return; 1245 return;
1267 } 1246 }
@@ -1314,7 +1293,7 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
1314 /* enable kind of interrupts always enabled */ 1293 /* enable kind of interrupts always enabled */
1315 u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT | 1294 u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT |
1316 DE_PLANEA_FLIP_DONE | DE_PLANEB_FLIP_DONE; 1295 DE_PLANEA_FLIP_DONE | DE_PLANEB_FLIP_DONE;
1317 u32 render_mask = GT_PIPE_NOTIFY; 1296 u32 render_mask = GT_PIPE_NOTIFY | GT_BSD_USER_INTERRUPT;
1318 u32 hotplug_mask = SDE_CRT_HOTPLUG | SDE_PORTB_HOTPLUG | 1297 u32 hotplug_mask = SDE_CRT_HOTPLUG | SDE_PORTB_HOTPLUG |
1319 SDE_PORTC_HOTPLUG | SDE_PORTD_HOTPLUG; 1298 SDE_PORTC_HOTPLUG | SDE_PORTD_HOTPLUG;
1320 1299
@@ -1328,7 +1307,7 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
1328 (void) I915_READ(DEIER); 1307 (void) I915_READ(DEIER);
1329 1308
1330 /* user interrupt should be enabled, but masked initial */ 1309 /* user interrupt should be enabled, but masked initial */
1331 dev_priv->gt_irq_mask_reg = 0xffffffff; 1310 dev_priv->gt_irq_mask_reg = ~render_mask;
1332 dev_priv->gt_irq_enable_reg = render_mask; 1311 dev_priv->gt_irq_enable_reg = render_mask;
1333 1312
1334 I915_WRITE(GTIIR, I915_READ(GTIIR)); 1313 I915_WRITE(GTIIR, I915_READ(GTIIR));
@@ -1391,7 +1370,10 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
1391 u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR; 1370 u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR;
1392 u32 error_mask; 1371 u32 error_mask;
1393 1372
1394 DRM_INIT_WAITQUEUE(&dev_priv->irq_queue); 1373 DRM_INIT_WAITQUEUE(&dev_priv->render_ring.irq_queue);
1374
1375 if (HAS_BSD(dev))
1376 DRM_INIT_WAITQUEUE(&dev_priv->bsd_ring.irq_queue);
1395 1377
1396 dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B; 1378 dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
1397 1379
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index f3e39cc46f0d..64b0a3afd92b 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -334,6 +334,7 @@
334#define I915_DEBUG_INTERRUPT (1<<2) 334#define I915_DEBUG_INTERRUPT (1<<2)
335#define I915_USER_INTERRUPT (1<<1) 335#define I915_USER_INTERRUPT (1<<1)
336#define I915_ASLE_INTERRUPT (1<<0) 336#define I915_ASLE_INTERRUPT (1<<0)
337#define I915_BSD_USER_INTERRUPT (1<<25)
337#define EIR 0x020b0 338#define EIR 0x020b0
338#define EMR 0x020b4 339#define EMR 0x020b4
339#define ESR 0x020b8 340#define ESR 0x020b8
@@ -368,6 +369,36 @@
368#define BB_ADDR 0x02140 /* 8 bytes */ 369#define BB_ADDR 0x02140 /* 8 bytes */
369#define GFX_FLSH_CNTL 0x02170 /* 915+ only */ 370#define GFX_FLSH_CNTL 0x02170 /* 915+ only */
370 371
372/* GEN6 interrupt control */
373#define GEN6_RENDER_HWSTAM 0x2098
374#define GEN6_RENDER_IMR 0x20a8
375#define GEN6_RENDER_CONTEXT_SWITCH_INTERRUPT (1 << 8)
376#define GEN6_RENDER_PPGTT_PAGE_FAULT (1 << 7)
377#define GEN6_RENDER TIMEOUT_COUNTER_EXPIRED (1 << 6)
378#define GEN6_RENDER_L3_PARITY_ERROR (1 << 5)
379#define GEN6_RENDER_PIPE_CONTROL_NOTIFY_INTERRUPT (1 << 4)
380#define GEN6_RENDER_COMMAND_PARSER_MASTER_ERROR (1 << 3)
381#define GEN6_RENDER_SYNC_STATUS (1 << 2)
382#define GEN6_RENDER_DEBUG_INTERRUPT (1 << 1)
383#define GEN6_RENDER_USER_INTERRUPT (1 << 0)
384
385#define GEN6_BLITTER_HWSTAM 0x22098
386#define GEN6_BLITTER_IMR 0x220a8
387#define GEN6_BLITTER_MI_FLUSH_DW_NOTIFY_INTERRUPT (1 << 26)
388#define GEN6_BLITTER_COMMAND_PARSER_MASTER_ERROR (1 << 25)
389#define GEN6_BLITTER_SYNC_STATUS (1 << 24)
390#define GEN6_BLITTER_USER_INTERRUPT (1 << 22)
391/*
392 * BSD (bit stream decoder instruction and interrupt control register defines
393 * (G4X and Ironlake only)
394 */
395
396#define BSD_RING_TAIL 0x04030
397#define BSD_RING_HEAD 0x04034
398#define BSD_RING_START 0x04038
399#define BSD_RING_CTL 0x0403c
400#define BSD_RING_ACTHD 0x04074
401#define BSD_HWS_PGA 0x04080
371 402
372/* 403/*
373 * Framebuffer compression (915+ only) 404 * Framebuffer compression (915+ only)
@@ -805,6 +836,10 @@
805#define DCC_CHANNEL_XOR_DISABLE (1 << 10) 836#define DCC_CHANNEL_XOR_DISABLE (1 << 10)
806#define DCC_CHANNEL_XOR_BIT_17 (1 << 9) 837#define DCC_CHANNEL_XOR_BIT_17 (1 << 9)
807 838
839/** Pineview MCH register contains DDR3 setting */
840#define CSHRDDR3CTL 0x101a8
841#define CSHRDDR3CTL_DDR3 (1 << 2)
842
808/** 965 MCH register controlling DRAM channel configuration */ 843/** 965 MCH register controlling DRAM channel configuration */
809#define C0DRB3 0x10206 844#define C0DRB3 0x10206
810#define C1DRB3 0x10606 845#define C1DRB3 0x10606
@@ -826,6 +861,12 @@
826#define CLKCFG_MEM_800 (3 << 4) 861#define CLKCFG_MEM_800 (3 << 4)
827#define CLKCFG_MEM_MASK (7 << 4) 862#define CLKCFG_MEM_MASK (7 << 4)
828 863
864#define TR1 0x11006
865#define TSFS 0x11020
866#define TSFS_SLOPE_MASK 0x0000ff00
867#define TSFS_SLOPE_SHIFT 8
868#define TSFS_INTR_MASK 0x000000ff
869
829#define CRSTANDVID 0x11100 870#define CRSTANDVID 0x11100
830#define PXVFREQ_BASE 0x11110 /* P[0-15]VIDFREQ (0x1114c) (Ironlake) */ 871#define PXVFREQ_BASE 0x11110 /* P[0-15]VIDFREQ (0x1114c) (Ironlake) */
831#define PXVFREQ_PX_MASK 0x7f000000 872#define PXVFREQ_PX_MASK 0x7f000000
@@ -964,6 +1005,41 @@
964#define MEMSTAT_SRC_CTL_STDBY 3 1005#define MEMSTAT_SRC_CTL_STDBY 3
965#define RCPREVBSYTUPAVG 0x113b8 1006#define RCPREVBSYTUPAVG 0x113b8
966#define RCPREVBSYTDNAVG 0x113bc 1007#define RCPREVBSYTDNAVG 0x113bc
1008#define SDEW 0x1124c
1009#define CSIEW0 0x11250
1010#define CSIEW1 0x11254
1011#define CSIEW2 0x11258
1012#define PEW 0x1125c
1013#define DEW 0x11270
1014#define MCHAFE 0x112c0
1015#define CSIEC 0x112e0
1016#define DMIEC 0x112e4
1017#define DDREC 0x112e8
1018#define PEG0EC 0x112ec
1019#define PEG1EC 0x112f0
1020#define GFXEC 0x112f4
1021#define RPPREVBSYTUPAVG 0x113b8
1022#define RPPREVBSYTDNAVG 0x113bc
1023#define ECR 0x11600
1024#define ECR_GPFE (1<<31)
1025#define ECR_IMONE (1<<30)
1026#define ECR_CAP_MASK 0x0000001f /* Event range, 0-31 */
1027#define OGW0 0x11608
1028#define OGW1 0x1160c
1029#define EG0 0x11610
1030#define EG1 0x11614
1031#define EG2 0x11618
1032#define EG3 0x1161c
1033#define EG4 0x11620
1034#define EG5 0x11624
1035#define EG6 0x11628
1036#define EG7 0x1162c
1037#define PXW 0x11664
1038#define PXWL 0x11680
1039#define LCFUSE02 0x116c0
1040#define LCFUSE_HIV_MASK 0x000000ff
1041#define CSIPLL0 0x12c10
1042#define DDRMPLL1 0X12c20
967#define PEG_BAND_GAP_DATA 0x14d68 1043#define PEG_BAND_GAP_DATA 0x14d68
968 1044
969/* 1045/*
@@ -1055,7 +1131,6 @@
1055#define CRT_HOTPLUG_DETECT_VOLTAGE_325MV (0 << 2) 1131#define CRT_HOTPLUG_DETECT_VOLTAGE_325MV (0 << 2)
1056#define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2) 1132#define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2)
1057#define CRT_HOTPLUG_MASK (0x3fc) /* Bits 9-2 */ 1133#define CRT_HOTPLUG_MASK (0x3fc) /* Bits 9-2 */
1058#define CRT_FORCE_HOTPLUG_MASK 0xfffffe1f
1059 1134
1060#define PORT_HOTPLUG_STAT 0x61114 1135#define PORT_HOTPLUG_STAT 0x61114
1061#define HDMIB_HOTPLUG_INT_STATUS (1 << 29) 1136#define HDMIB_HOTPLUG_INT_STATUS (1 << 29)
@@ -2355,6 +2430,8 @@
2355#define GT_PIPE_NOTIFY (1 << 4) 2430#define GT_PIPE_NOTIFY (1 << 4)
2356#define GT_SYNC_STATUS (1 << 2) 2431#define GT_SYNC_STATUS (1 << 2)
2357#define GT_USER_INTERRUPT (1 << 0) 2432#define GT_USER_INTERRUPT (1 << 0)
2433#define GT_BSD_USER_INTERRUPT (1 << 5)
2434
2358 2435
2359#define GTISR 0x44010 2436#define GTISR 0x44010
2360#define GTIMR 0x44014 2437#define GTIMR 0x44014
@@ -2690,6 +2767,9 @@
2690#define SDVO_ENCODING (0) 2767#define SDVO_ENCODING (0)
2691#define TMDS_ENCODING (2 << 10) 2768#define TMDS_ENCODING (2 << 10)
2692#define NULL_PACKET_VSYNC_ENABLE (1 << 9) 2769#define NULL_PACKET_VSYNC_ENABLE (1 << 9)
2770/* CPT */
2771#define HDMI_MODE_SELECT (1 << 9)
2772#define DVI_MODE_SELECT (0)
2693#define SDVOB_BORDER_ENABLE (1 << 7) 2773#define SDVOB_BORDER_ENABLE (1 << 7)
2694#define AUDIO_ENABLE (1 << 6) 2774#define AUDIO_ENABLE (1 << 6)
2695#define VSYNC_ACTIVE_HIGH (1 << 4) 2775#define VSYNC_ACTIVE_HIGH (1 << 4)
diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h
index 9e4c45f68d6e..fab21760dd57 100644
--- a/drivers/gpu/drm/i915/i915_trace.h
+++ b/drivers/gpu/drm/i915/i915_trace.h
@@ -53,23 +53,6 @@ TRACE_EVENT(i915_gem_object_bind,
53 __entry->obj, __entry->gtt_offset) 53 __entry->obj, __entry->gtt_offset)
54); 54);
55 55
56TRACE_EVENT(i915_gem_object_clflush,
57
58 TP_PROTO(struct drm_gem_object *obj),
59
60 TP_ARGS(obj),
61
62 TP_STRUCT__entry(
63 __field(struct drm_gem_object *, obj)
64 ),
65
66 TP_fast_assign(
67 __entry->obj = obj;
68 ),
69
70 TP_printk("obj=%p", __entry->obj)
71);
72
73TRACE_EVENT(i915_gem_object_change_domain, 56TRACE_EVENT(i915_gem_object_change_domain,
74 57
75 TP_PROTO(struct drm_gem_object *obj, uint32_t old_read_domains, uint32_t old_write_domain), 58 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,
132 TP_printk("obj=%p", __entry->obj) 115 TP_printk("obj=%p", __entry->obj)
133); 116);
134 117
118DEFINE_EVENT(i915_gem_object, i915_gem_object_clflush,
119
120 TP_PROTO(struct drm_gem_object *obj),
121
122 TP_ARGS(obj)
123);
124
135DEFINE_EVENT(i915_gem_object, i915_gem_object_unbind, 125DEFINE_EVENT(i915_gem_object, i915_gem_object_unbind,
136 126
137 TP_PROTO(struct drm_gem_object *obj), 127 TP_PROTO(struct drm_gem_object *obj),
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index 4c748d8f73d6..96f75d7f6633 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -95,6 +95,16 @@ fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
95 panel_fixed_mode->clock = dvo_timing->clock * 10; 95 panel_fixed_mode->clock = dvo_timing->clock * 10;
96 panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED; 96 panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED;
97 97
98 if (dvo_timing->hsync_positive)
99 panel_fixed_mode->flags |= DRM_MODE_FLAG_PHSYNC;
100 else
101 panel_fixed_mode->flags |= DRM_MODE_FLAG_NHSYNC;
102
103 if (dvo_timing->vsync_positive)
104 panel_fixed_mode->flags |= DRM_MODE_FLAG_PVSYNC;
105 else
106 panel_fixed_mode->flags |= DRM_MODE_FLAG_NVSYNC;
107
98 /* Some VBTs have bogus h/vtotal values */ 108 /* Some VBTs have bogus h/vtotal values */
99 if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal) 109 if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal)
100 panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1; 110 panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1;
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index e16ac5a28c3c..22ff38455731 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -217,7 +217,8 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
217{ 217{
218 struct drm_device *dev = connector->dev; 218 struct drm_device *dev = connector->dev;
219 struct drm_i915_private *dev_priv = dev->dev_private; 219 struct drm_i915_private *dev_priv = dev->dev_private;
220 u32 hotplug_en; 220 u32 hotplug_en, orig, stat;
221 bool ret = false;
221 int i, tries = 0; 222 int i, tries = 0;
222 223
223 if (HAS_PCH_SPLIT(dev)) 224 if (HAS_PCH_SPLIT(dev))
@@ -232,8 +233,8 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
232 tries = 2; 233 tries = 2;
233 else 234 else
234 tries = 1; 235 tries = 1;
235 hotplug_en = I915_READ(PORT_HOTPLUG_EN); 236 hotplug_en = orig = I915_READ(PORT_HOTPLUG_EN);
236 hotplug_en &= CRT_FORCE_HOTPLUG_MASK; 237 hotplug_en &= CRT_HOTPLUG_MASK;
237 hotplug_en |= CRT_HOTPLUG_FORCE_DETECT; 238 hotplug_en |= CRT_HOTPLUG_FORCE_DETECT;
238 239
239 if (IS_G4X(dev)) 240 if (IS_G4X(dev))
@@ -255,11 +256,17 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
255 } while (time_after(timeout, jiffies)); 256 } while (time_after(timeout, jiffies));
256 } 257 }
257 258
258 if ((I915_READ(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_MONITOR_MASK) != 259 stat = I915_READ(PORT_HOTPLUG_STAT);
259 CRT_HOTPLUG_MONITOR_NONE) 260 if ((stat & CRT_HOTPLUG_MONITOR_MASK) != CRT_HOTPLUG_MONITOR_NONE)
260 return true; 261 ret = true;
262
263 /* clear the interrupt we just generated, if any */
264 I915_WRITE(PORT_HOTPLUG_STAT, CRT_HOTPLUG_INT_STATUS);
261 265
262 return false; 266 /* and put the bits back */
267 I915_WRITE(PORT_HOTPLUG_EN, orig);
268
269 return ret;
263} 270}
264 271
265static bool intel_crt_detect_ddc(struct drm_encoder *encoder) 272static bool intel_crt_detect_ddc(struct drm_encoder *encoder)
@@ -569,7 +576,7 @@ void intel_crt_init(struct drm_device *dev)
569 (1 << INTEL_ANALOG_CLONE_BIT) | 576 (1 << INTEL_ANALOG_CLONE_BIT) |
570 (1 << INTEL_SDVO_LVDS_CLONE_BIT); 577 (1 << INTEL_SDVO_LVDS_CLONE_BIT);
571 intel_encoder->crtc_mask = (1 << 0) | (1 << 1); 578 intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
572 connector->interlace_allowed = 0; 579 connector->interlace_allowed = 1;
573 connector->doublescan_allowed = 0; 580 connector->doublescan_allowed = 0;
574 581
575 drm_encoder_helper_add(&intel_encoder->enc, &intel_crt_helper_funcs); 582 drm_encoder_helper_add(&intel_encoder->enc, &intel_crt_helper_funcs);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index f469a84cacfd..cc8131ff319f 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1029,19 +1029,28 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
1029void i8xx_disable_fbc(struct drm_device *dev) 1029void i8xx_disable_fbc(struct drm_device *dev)
1030{ 1030{
1031 struct drm_i915_private *dev_priv = dev->dev_private; 1031 struct drm_i915_private *dev_priv = dev->dev_private;
1032 unsigned long timeout = jiffies + msecs_to_jiffies(1);
1032 u32 fbc_ctl; 1033 u32 fbc_ctl;
1033 1034
1034 if (!I915_HAS_FBC(dev)) 1035 if (!I915_HAS_FBC(dev))
1035 return; 1036 return;
1036 1037
1038 if (!(I915_READ(FBC_CONTROL) & FBC_CTL_EN))
1039 return; /* Already off, just return */
1040
1037 /* Disable compression */ 1041 /* Disable compression */
1038 fbc_ctl = I915_READ(FBC_CONTROL); 1042 fbc_ctl = I915_READ(FBC_CONTROL);
1039 fbc_ctl &= ~FBC_CTL_EN; 1043 fbc_ctl &= ~FBC_CTL_EN;
1040 I915_WRITE(FBC_CONTROL, fbc_ctl); 1044 I915_WRITE(FBC_CONTROL, fbc_ctl);
1041 1045
1042 /* Wait for compressing bit to clear */ 1046 /* Wait for compressing bit to clear */
1043 while (I915_READ(FBC_STATUS) & FBC_STAT_COMPRESSING) 1047 while (I915_READ(FBC_STATUS) & FBC_STAT_COMPRESSING) {
1044 ; /* nothing */ 1048 if (time_after(jiffies, timeout)) {
1049 DRM_DEBUG_DRIVER("FBC idle timed out\n");
1050 break;
1051 }
1052 ; /* do nothing */
1053 }
1045 1054
1046 intel_wait_for_vblank(dev); 1055 intel_wait_for_vblank(dev);
1047 1056
@@ -1239,10 +1248,11 @@ static void intel_update_fbc(struct drm_crtc *crtc,
1239 return; 1248 return;
1240 1249
1241out_disable: 1250out_disable:
1242 DRM_DEBUG_KMS("unsupported config, disabling FBC\n");
1243 /* Multiple disables should be harmless */ 1251 /* Multiple disables should be harmless */
1244 if (intel_fbc_enabled(dev)) 1252 if (intel_fbc_enabled(dev)) {
1253 DRM_DEBUG_KMS("unsupported config, disabling FBC\n");
1245 intel_disable_fbc(dev); 1254 intel_disable_fbc(dev);
1255 }
1246} 1256}
1247 1257
1248static int 1258static int
@@ -1386,7 +1396,8 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
1386 Start = obj_priv->gtt_offset; 1396 Start = obj_priv->gtt_offset;
1387 Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8); 1397 Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
1388 1398
1389 DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y); 1399 DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n",
1400 Start, Offset, x, y, crtc->fb->pitch);
1390 I915_WRITE(dspstride, crtc->fb->pitch); 1401 I915_WRITE(dspstride, crtc->fb->pitch);
1391 if (IS_I965G(dev)) { 1402 if (IS_I965G(dev)) {
1392 I915_WRITE(dspbase, Offset); 1403 I915_WRITE(dspbase, Offset);
@@ -2345,6 +2356,8 @@ static bool intel_crtc_mode_fixup(struct drm_crtc *crtc,
2345 if (mode->clock * 3 > 27000 * 4) 2356 if (mode->clock * 3 > 27000 * 4)
2346 return MODE_CLOCK_HIGH; 2357 return MODE_CLOCK_HIGH;
2347 } 2358 }
2359
2360 drm_mode_set_crtcinfo(adjusted_mode, 0);
2348 return true; 2361 return true;
2349} 2362}
2350 2363
@@ -2629,6 +2642,7 @@ static unsigned long intel_calculate_wm(unsigned long clock_in_khz,
2629 2642
2630struct cxsr_latency { 2643struct cxsr_latency {
2631 int is_desktop; 2644 int is_desktop;
2645 int is_ddr3;
2632 unsigned long fsb_freq; 2646 unsigned long fsb_freq;
2633 unsigned long mem_freq; 2647 unsigned long mem_freq;
2634 unsigned long display_sr; 2648 unsigned long display_sr;
@@ -2638,33 +2652,45 @@ struct cxsr_latency {
2638}; 2652};
2639 2653
2640static struct cxsr_latency cxsr_latency_table[] = { 2654static struct cxsr_latency cxsr_latency_table[] = {
2641 {1, 800, 400, 3382, 33382, 3983, 33983}, /* DDR2-400 SC */ 2655 {1, 0, 800, 400, 3382, 33382, 3983, 33983}, /* DDR2-400 SC */
2642 {1, 800, 667, 3354, 33354, 3807, 33807}, /* DDR2-667 SC */ 2656 {1, 0, 800, 667, 3354, 33354, 3807, 33807}, /* DDR2-667 SC */
2643 {1, 800, 800, 3347, 33347, 3763, 33763}, /* DDR2-800 SC */ 2657 {1, 0, 800, 800, 3347, 33347, 3763, 33763}, /* DDR2-800 SC */
2644 2658 {1, 1, 800, 667, 6420, 36420, 6873, 36873}, /* DDR3-667 SC */
2645 {1, 667, 400, 3400, 33400, 4021, 34021}, /* DDR2-400 SC */ 2659 {1, 1, 800, 800, 5902, 35902, 6318, 36318}, /* DDR3-800 SC */
2646 {1, 667, 667, 3372, 33372, 3845, 33845}, /* DDR2-667 SC */ 2660
2647 {1, 667, 800, 3386, 33386, 3822, 33822}, /* DDR2-800 SC */ 2661 {1, 0, 667, 400, 3400, 33400, 4021, 34021}, /* DDR2-400 SC */
2648 2662 {1, 0, 667, 667, 3372, 33372, 3845, 33845}, /* DDR2-667 SC */
2649 {1, 400, 400, 3472, 33472, 4173, 34173}, /* DDR2-400 SC */ 2663 {1, 0, 667, 800, 3386, 33386, 3822, 33822}, /* DDR2-800 SC */
2650 {1, 400, 667, 3443, 33443, 3996, 33996}, /* DDR2-667 SC */ 2664 {1, 1, 667, 667, 6438, 36438, 6911, 36911}, /* DDR3-667 SC */
2651 {1, 400, 800, 3430, 33430, 3946, 33946}, /* DDR2-800 SC */ 2665 {1, 1, 667, 800, 5941, 35941, 6377, 36377}, /* DDR3-800 SC */
2652 2666
2653 {0, 800, 400, 3438, 33438, 4065, 34065}, /* DDR2-400 SC */ 2667 {1, 0, 400, 400, 3472, 33472, 4173, 34173}, /* DDR2-400 SC */
2654 {0, 800, 667, 3410, 33410, 3889, 33889}, /* DDR2-667 SC */ 2668 {1, 0, 400, 667, 3443, 33443, 3996, 33996}, /* DDR2-667 SC */
2655 {0, 800, 800, 3403, 33403, 3845, 33845}, /* DDR2-800 SC */ 2669 {1, 0, 400, 800, 3430, 33430, 3946, 33946}, /* DDR2-800 SC */
2656 2670 {1, 1, 400, 667, 6509, 36509, 7062, 37062}, /* DDR3-667 SC */
2657 {0, 667, 400, 3456, 33456, 4103, 34106}, /* DDR2-400 SC */ 2671 {1, 1, 400, 800, 5985, 35985, 6501, 36501}, /* DDR3-800 SC */
2658 {0, 667, 667, 3428, 33428, 3927, 33927}, /* DDR2-667 SC */ 2672
2659 {0, 667, 800, 3443, 33443, 3905, 33905}, /* DDR2-800 SC */ 2673 {0, 0, 800, 400, 3438, 33438, 4065, 34065}, /* DDR2-400 SC */
2660 2674 {0, 0, 800, 667, 3410, 33410, 3889, 33889}, /* DDR2-667 SC */
2661 {0, 400, 400, 3528, 33528, 4255, 34255}, /* DDR2-400 SC */ 2675 {0, 0, 800, 800, 3403, 33403, 3845, 33845}, /* DDR2-800 SC */
2662 {0, 400, 667, 3500, 33500, 4079, 34079}, /* DDR2-667 SC */ 2676 {0, 1, 800, 667, 6476, 36476, 6955, 36955}, /* DDR3-667 SC */
2663 {0, 400, 800, 3487, 33487, 4029, 34029}, /* DDR2-800 SC */ 2677 {0, 1, 800, 800, 5958, 35958, 6400, 36400}, /* DDR3-800 SC */
2678
2679 {0, 0, 667, 400, 3456, 33456, 4103, 34106}, /* DDR2-400 SC */
2680 {0, 0, 667, 667, 3428, 33428, 3927, 33927}, /* DDR2-667 SC */
2681 {0, 0, 667, 800, 3443, 33443, 3905, 33905}, /* DDR2-800 SC */
2682 {0, 1, 667, 667, 6494, 36494, 6993, 36993}, /* DDR3-667 SC */
2683 {0, 1, 667, 800, 5998, 35998, 6460, 36460}, /* DDR3-800 SC */
2684
2685 {0, 0, 400, 400, 3528, 33528, 4255, 34255}, /* DDR2-400 SC */
2686 {0, 0, 400, 667, 3500, 33500, 4079, 34079}, /* DDR2-667 SC */
2687 {0, 0, 400, 800, 3487, 33487, 4029, 34029}, /* DDR2-800 SC */
2688 {0, 1, 400, 667, 6566, 36566, 7145, 37145}, /* DDR3-667 SC */
2689 {0, 1, 400, 800, 6042, 36042, 6584, 36584}, /* DDR3-800 SC */
2664}; 2690};
2665 2691
2666static struct cxsr_latency *intel_get_cxsr_latency(int is_desktop, int fsb, 2692static struct cxsr_latency *intel_get_cxsr_latency(int is_desktop, int is_ddr3,
2667 int mem) 2693 int fsb, int mem)
2668{ 2694{
2669 int i; 2695 int i;
2670 struct cxsr_latency *latency; 2696 struct cxsr_latency *latency;
@@ -2675,6 +2701,7 @@ static struct cxsr_latency *intel_get_cxsr_latency(int is_desktop, int fsb,
2675 for (i = 0; i < ARRAY_SIZE(cxsr_latency_table); i++) { 2701 for (i = 0; i < ARRAY_SIZE(cxsr_latency_table); i++) {
2676 latency = &cxsr_latency_table[i]; 2702 latency = &cxsr_latency_table[i];
2677 if (is_desktop == latency->is_desktop && 2703 if (is_desktop == latency->is_desktop &&
2704 is_ddr3 == latency->is_ddr3 &&
2678 fsb == latency->fsb_freq && mem == latency->mem_freq) 2705 fsb == latency->fsb_freq && mem == latency->mem_freq)
2679 return latency; 2706 return latency;
2680 } 2707 }
@@ -2789,8 +2816,8 @@ static void pineview_update_wm(struct drm_device *dev, int planea_clock,
2789 struct cxsr_latency *latency; 2816 struct cxsr_latency *latency;
2790 int sr_clock; 2817 int sr_clock;
2791 2818
2792 latency = intel_get_cxsr_latency(IS_PINEVIEW_G(dev), dev_priv->fsb_freq, 2819 latency = intel_get_cxsr_latency(IS_PINEVIEW_G(dev), dev_priv->is_ddr3,
2793 dev_priv->mem_freq); 2820 dev_priv->fsb_freq, dev_priv->mem_freq);
2794 if (!latency) { 2821 if (!latency) {
2795 DRM_DEBUG_KMS("Unknown FSB/MEM found, disable CxSR\n"); 2822 DRM_DEBUG_KMS("Unknown FSB/MEM found, disable CxSR\n");
2796 pineview_disable_cxsr(dev); 2823 pineview_disable_cxsr(dev);
@@ -3626,6 +3653,11 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
3626 pipeconf &= ~PIPEACONF_DOUBLE_WIDE; 3653 pipeconf &= ~PIPEACONF_DOUBLE_WIDE;
3627 } 3654 }
3628 3655
3656 dspcntr |= DISPLAY_PLANE_ENABLE;
3657 pipeconf |= PIPEACONF_ENABLE;
3658 dpll |= DPLL_VCO_ENABLE;
3659
3660
3629 /* Disable the panel fitter if it was on our pipe */ 3661 /* Disable the panel fitter if it was on our pipe */
3630 if (!HAS_PCH_SPLIT(dev) && intel_panel_fitter_pipe(dev) == pipe) 3662 if (!HAS_PCH_SPLIT(dev) && intel_panel_fitter_pipe(dev) == pipe)
3631 I915_WRITE(PFIT_CONTROL, 0); 3663 I915_WRITE(PFIT_CONTROL, 0);
@@ -3772,6 +3804,18 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
3772 } 3804 }
3773 } 3805 }
3774 3806
3807 if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
3808 pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;
3809 /* the chip adds 2 halflines automatically */
3810 adjusted_mode->crtc_vdisplay -= 1;
3811 adjusted_mode->crtc_vtotal -= 1;
3812 adjusted_mode->crtc_vblank_start -= 1;
3813 adjusted_mode->crtc_vblank_end -= 1;
3814 adjusted_mode->crtc_vsync_end -= 1;
3815 adjusted_mode->crtc_vsync_start -= 1;
3816 } else
3817 pipeconf &= ~PIPECONF_INTERLACE_W_FIELD_INDICATION; /* progressive */
3818
3775 I915_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) | 3819 I915_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) |
3776 ((adjusted_mode->crtc_htotal - 1) << 16)); 3820 ((adjusted_mode->crtc_htotal - 1) << 16));
3777 I915_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | 3821 I915_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) |
@@ -3934,6 +3978,13 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
3934 DRM_ERROR("failed to pin cursor bo\n"); 3978 DRM_ERROR("failed to pin cursor bo\n");
3935 goto fail_locked; 3979 goto fail_locked;
3936 } 3980 }
3981
3982 ret = i915_gem_object_set_to_gtt_domain(bo, 0);
3983 if (ret) {
3984 DRM_ERROR("failed to move cursor bo into the GTT\n");
3985 goto fail_unpin;
3986 }
3987
3937 addr = obj_priv->gtt_offset; 3988 addr = obj_priv->gtt_offset;
3938 } else { 3989 } else {
3939 ret = i915_gem_attach_phys_object(dev, bo, (pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1); 3990 ret = i915_gem_attach_phys_object(dev, bo, (pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1);
@@ -3977,6 +4028,8 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
3977 intel_crtc->cursor_bo = bo; 4028 intel_crtc->cursor_bo = bo;
3978 4029
3979 return 0; 4030 return 0;
4031fail_unpin:
4032 i915_gem_object_unpin(bo);
3980fail_locked: 4033fail_locked:
3981 mutex_unlock(&dev->struct_mutex); 4034 mutex_unlock(&dev->struct_mutex);
3982fail: 4035fail:
@@ -4436,6 +4489,8 @@ static void intel_idle_update(struct work_struct *work)
4436 4489
4437 mutex_lock(&dev->struct_mutex); 4490 mutex_lock(&dev->struct_mutex);
4438 4491
4492 i915_update_gfx_val(dev_priv);
4493
4439 if (IS_I945G(dev) || IS_I945GM(dev)) { 4494 if (IS_I945G(dev) || IS_I945GM(dev)) {
4440 DRM_DEBUG_DRIVER("enable memory self refresh on 945\n"); 4495 DRM_DEBUG_DRIVER("enable memory self refresh on 945\n");
4441 I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN_MASK | FW_BLC_SELF_EN); 4496 I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN_MASK | FW_BLC_SELF_EN);
@@ -4564,12 +4619,6 @@ void intel_finish_page_flip(struct drm_device *dev, int pipe)
4564 spin_lock_irqsave(&dev->event_lock, flags); 4619 spin_lock_irqsave(&dev->event_lock, flags);
4565 work = intel_crtc->unpin_work; 4620 work = intel_crtc->unpin_work;
4566 if (work == NULL || !work->pending) { 4621 if (work == NULL || !work->pending) {
4567 if (work && !work->pending) {
4568 obj_priv = to_intel_bo(work->pending_flip_obj);
4569 DRM_DEBUG_DRIVER("flip finish: %p (%d) not pending?\n",
4570 obj_priv,
4571 atomic_read(&obj_priv->pending_flip));
4572 }
4573 spin_unlock_irqrestore(&dev->event_lock, flags); 4622 spin_unlock_irqrestore(&dev->event_lock, flags);
4574 return; 4623 return;
4575 } 4624 }
@@ -4629,14 +4678,11 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
4629 unsigned long flags; 4678 unsigned long flags;
4630 int pipesrc_reg = (intel_crtc->pipe == 0) ? PIPEASRC : PIPEBSRC; 4679 int pipesrc_reg = (intel_crtc->pipe == 0) ? PIPEASRC : PIPEBSRC;
4631 int ret, pipesrc; 4680 int ret, pipesrc;
4632 RING_LOCALS;
4633 4681
4634 work = kzalloc(sizeof *work, GFP_KERNEL); 4682 work = kzalloc(sizeof *work, GFP_KERNEL);
4635 if (work == NULL) 4683 if (work == NULL)
4636 return -ENOMEM; 4684 return -ENOMEM;
4637 4685
4638 mutex_lock(&dev->struct_mutex);
4639
4640 work->event = event; 4686 work->event = event;
4641 work->dev = crtc->dev; 4687 work->dev = crtc->dev;
4642 intel_fb = to_intel_framebuffer(crtc->fb); 4688 intel_fb = to_intel_framebuffer(crtc->fb);
@@ -4646,10 +4692,10 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
4646 /* We borrow the event spin lock for protecting unpin_work */ 4692 /* We borrow the event spin lock for protecting unpin_work */
4647 spin_lock_irqsave(&dev->event_lock, flags); 4693 spin_lock_irqsave(&dev->event_lock, flags);
4648 if (intel_crtc->unpin_work) { 4694 if (intel_crtc->unpin_work) {
4649 DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
4650 spin_unlock_irqrestore(&dev->event_lock, flags); 4695 spin_unlock_irqrestore(&dev->event_lock, flags);
4651 kfree(work); 4696 kfree(work);
4652 mutex_unlock(&dev->struct_mutex); 4697
4698 DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
4653 return -EBUSY; 4699 return -EBUSY;
4654 } 4700 }
4655 intel_crtc->unpin_work = work; 4701 intel_crtc->unpin_work = work;
@@ -4658,13 +4704,19 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
4658 intel_fb = to_intel_framebuffer(fb); 4704 intel_fb = to_intel_framebuffer(fb);
4659 obj = intel_fb->obj; 4705 obj = intel_fb->obj;
4660 4706
4707 mutex_lock(&dev->struct_mutex);
4661 ret = intel_pin_and_fence_fb_obj(dev, obj); 4708 ret = intel_pin_and_fence_fb_obj(dev, obj);
4662 if (ret != 0) { 4709 if (ret != 0) {
4663 DRM_DEBUG_DRIVER("flip queue: %p pin & fence failed\n",
4664 to_intel_bo(obj));
4665 kfree(work);
4666 intel_crtc->unpin_work = NULL;
4667 mutex_unlock(&dev->struct_mutex); 4710 mutex_unlock(&dev->struct_mutex);
4711
4712 spin_lock_irqsave(&dev->event_lock, flags);
4713 intel_crtc->unpin_work = NULL;
4714 spin_unlock_irqrestore(&dev->event_lock, flags);
4715
4716 kfree(work);
4717
4718 DRM_DEBUG_DRIVER("flip queue: %p pin & fence failed\n",
4719 to_intel_bo(obj));
4668 return ret; 4720 return ret;
4669 } 4721 }
4670 4722
@@ -5023,10 +5075,32 @@ err_unref:
5023 return NULL; 5075 return NULL;
5024} 5076}
5025 5077
5078bool ironlake_set_drps(struct drm_device *dev, u8 val)
5079{
5080 struct drm_i915_private *dev_priv = dev->dev_private;
5081 u16 rgvswctl;
5082
5083 rgvswctl = I915_READ16(MEMSWCTL);
5084 if (rgvswctl & MEMCTL_CMD_STS) {
5085 DRM_DEBUG("gpu busy, RCS change rejected\n");
5086 return false; /* still busy with another command */
5087 }
5088
5089 rgvswctl = (MEMCTL_CMD_CHFREQ << MEMCTL_CMD_SHIFT) |
5090 (val << MEMCTL_FREQ_SHIFT) | MEMCTL_SFCAVM;
5091 I915_WRITE16(MEMSWCTL, rgvswctl);
5092 POSTING_READ16(MEMSWCTL);
5093
5094 rgvswctl |= MEMCTL_CMD_STS;
5095 I915_WRITE16(MEMSWCTL, rgvswctl);
5096
5097 return true;
5098}
5099
5026void ironlake_enable_drps(struct drm_device *dev) 5100void ironlake_enable_drps(struct drm_device *dev)
5027{ 5101{
5028 struct drm_i915_private *dev_priv = dev->dev_private; 5102 struct drm_i915_private *dev_priv = dev->dev_private;
5029 u32 rgvmodectl = I915_READ(MEMMODECTL), rgvswctl; 5103 u32 rgvmodectl = I915_READ(MEMMODECTL);
5030 u8 fmax, fmin, fstart, vstart; 5104 u8 fmax, fmin, fstart, vstart;
5031 int i = 0; 5105 int i = 0;
5032 5106
@@ -5045,13 +5119,21 @@ void ironlake_enable_drps(struct drm_device *dev)
5045 fmin = (rgvmodectl & MEMMODE_FMIN_MASK); 5119 fmin = (rgvmodectl & MEMMODE_FMIN_MASK);
5046 fstart = (rgvmodectl & MEMMODE_FSTART_MASK) >> 5120 fstart = (rgvmodectl & MEMMODE_FSTART_MASK) >>
5047 MEMMODE_FSTART_SHIFT; 5121 MEMMODE_FSTART_SHIFT;
5122 fstart = fmax;
5123
5048 vstart = (I915_READ(PXVFREQ_BASE + (fstart * 4)) & PXVFREQ_PX_MASK) >> 5124 vstart = (I915_READ(PXVFREQ_BASE + (fstart * 4)) & PXVFREQ_PX_MASK) >>
5049 PXVFREQ_PX_SHIFT; 5125 PXVFREQ_PX_SHIFT;
5050 5126
5051 dev_priv->max_delay = fstart; /* can't go to fmax w/o IPS */ 5127 dev_priv->fmax = fstart; /* IPS callback will increase this */
5128 dev_priv->fstart = fstart;
5129
5130 dev_priv->max_delay = fmax;
5052 dev_priv->min_delay = fmin; 5131 dev_priv->min_delay = fmin;
5053 dev_priv->cur_delay = fstart; 5132 dev_priv->cur_delay = fstart;
5054 5133
5134 DRM_DEBUG_DRIVER("fmax: %d, fmin: %d, fstart: %d\n", fmax, fmin,
5135 fstart);
5136
5055 I915_WRITE(MEMINTREN, MEMINT_CX_SUPR_EN | MEMINT_EVAL_CHG_EN); 5137 I915_WRITE(MEMINTREN, MEMINT_CX_SUPR_EN | MEMINT_EVAL_CHG_EN);
5056 5138
5057 /* 5139 /*
@@ -5073,20 +5155,19 @@ void ironlake_enable_drps(struct drm_device *dev)
5073 } 5155 }
5074 msleep(1); 5156 msleep(1);
5075 5157
5076 rgvswctl = (MEMCTL_CMD_CHFREQ << MEMCTL_CMD_SHIFT) | 5158 ironlake_set_drps(dev, fstart);
5077 (fstart << MEMCTL_FREQ_SHIFT) | MEMCTL_SFCAVM;
5078 I915_WRITE(MEMSWCTL, rgvswctl);
5079 POSTING_READ(MEMSWCTL);
5080 5159
5081 rgvswctl |= MEMCTL_CMD_STS; 5160 dev_priv->last_count1 = I915_READ(0x112e4) + I915_READ(0x112e8) +
5082 I915_WRITE(MEMSWCTL, rgvswctl); 5161 I915_READ(0x112e0);
5162 dev_priv->last_time1 = jiffies_to_msecs(jiffies);
5163 dev_priv->last_count2 = I915_READ(0x112f4);
5164 getrawmonotonic(&dev_priv->last_time2);
5083} 5165}
5084 5166
5085void ironlake_disable_drps(struct drm_device *dev) 5167void ironlake_disable_drps(struct drm_device *dev)
5086{ 5168{
5087 struct drm_i915_private *dev_priv = dev->dev_private; 5169 struct drm_i915_private *dev_priv = dev->dev_private;
5088 u32 rgvswctl; 5170 u16 rgvswctl = I915_READ16(MEMSWCTL);
5089 u8 fstart;
5090 5171
5091 /* Ack interrupts, disable EFC interrupt */ 5172 /* Ack interrupts, disable EFC interrupt */
5092 I915_WRITE(MEMINTREN, I915_READ(MEMINTREN) & ~MEMINT_EVAL_CHG_EN); 5173 I915_WRITE(MEMINTREN, I915_READ(MEMINTREN) & ~MEMINT_EVAL_CHG_EN);
@@ -5096,11 +5177,7 @@ void ironlake_disable_drps(struct drm_device *dev)
5096 I915_WRITE(DEIMR, I915_READ(DEIMR) | DE_PCU_EVENT); 5177 I915_WRITE(DEIMR, I915_READ(DEIMR) | DE_PCU_EVENT);
5097 5178
5098 /* Go back to the starting frequency */ 5179 /* Go back to the starting frequency */
5099 fstart = (I915_READ(MEMMODECTL) & MEMMODE_FSTART_MASK) >> 5180 ironlake_set_drps(dev, dev_priv->fstart);
5100 MEMMODE_FSTART_SHIFT;
5101 rgvswctl = (MEMCTL_CMD_CHFREQ << MEMCTL_CMD_SHIFT) |
5102 (fstart << MEMCTL_FREQ_SHIFT) | MEMCTL_SFCAVM;
5103 I915_WRITE(MEMSWCTL, rgvswctl);
5104 msleep(1); 5181 msleep(1);
5105 rgvswctl |= MEMCTL_CMD_STS; 5182 rgvswctl |= MEMCTL_CMD_STS;
5106 I915_WRITE(MEMSWCTL, rgvswctl); 5183 I915_WRITE(MEMSWCTL, rgvswctl);
@@ -5108,6 +5185,92 @@ void ironlake_disable_drps(struct drm_device *dev)
5108 5185
5109} 5186}
5110 5187
5188static unsigned long intel_pxfreq(u32 vidfreq)
5189{
5190 unsigned long freq;
5191 int div = (vidfreq & 0x3f0000) >> 16;
5192 int post = (vidfreq & 0x3000) >> 12;
5193 int pre = (vidfreq & 0x7);
5194
5195 if (!pre)
5196 return 0;
5197
5198 freq = ((div * 133333) / ((1<<post) * pre));
5199
5200 return freq;
5201}
5202
5203void intel_init_emon(struct drm_device *dev)
5204{
5205 struct drm_i915_private *dev_priv = dev->dev_private;
5206 u32 lcfuse;
5207 u8 pxw[16];
5208 int i;
5209
5210 /* Disable to program */
5211 I915_WRITE(ECR, 0);
5212 POSTING_READ(ECR);
5213
5214 /* Program energy weights for various events */
5215 I915_WRITE(SDEW, 0x15040d00);
5216 I915_WRITE(CSIEW0, 0x007f0000);
5217 I915_WRITE(CSIEW1, 0x1e220004);
5218 I915_WRITE(CSIEW2, 0x04000004);
5219
5220 for (i = 0; i < 5; i++)
5221 I915_WRITE(PEW + (i * 4), 0);
5222 for (i = 0; i < 3; i++)
5223 I915_WRITE(DEW + (i * 4), 0);
5224
5225 /* Program P-state weights to account for frequency power adjustment */
5226 for (i = 0; i < 16; i++) {
5227 u32 pxvidfreq = I915_READ(PXVFREQ_BASE + (i * 4));
5228 unsigned long freq = intel_pxfreq(pxvidfreq);
5229 unsigned long vid = (pxvidfreq & PXVFREQ_PX_MASK) >>
5230 PXVFREQ_PX_SHIFT;
5231 unsigned long val;
5232
5233 val = vid * vid;
5234 val *= (freq / 1000);
5235 val *= 255;
5236 val /= (127*127*900);
5237 if (val > 0xff)
5238 DRM_ERROR("bad pxval: %ld\n", val);
5239 pxw[i] = val;
5240 }
5241 /* Render standby states get 0 weight */
5242 pxw[14] = 0;
5243 pxw[15] = 0;
5244
5245 for (i = 0; i < 4; i++) {
5246 u32 val = (pxw[i*4] << 24) | (pxw[(i*4)+1] << 16) |
5247 (pxw[(i*4)+2] << 8) | (pxw[(i*4)+3]);
5248 I915_WRITE(PXW + (i * 4), val);
5249 }
5250
5251 /* Adjust magic regs to magic values (more experimental results) */
5252 I915_WRITE(OGW0, 0);
5253 I915_WRITE(OGW1, 0);
5254 I915_WRITE(EG0, 0x00007f00);
5255 I915_WRITE(EG1, 0x0000000e);
5256 I915_WRITE(EG2, 0x000e0000);
5257 I915_WRITE(EG3, 0x68000300);
5258 I915_WRITE(EG4, 0x42000000);
5259 I915_WRITE(EG5, 0x00140031);
5260 I915_WRITE(EG6, 0);
5261 I915_WRITE(EG7, 0);
5262
5263 for (i = 0; i < 8; i++)
5264 I915_WRITE(PXWL + (i * 4), 0);
5265
5266 /* Enable PMON + select events */
5267 I915_WRITE(ECR, 0x80000019);
5268
5269 lcfuse = I915_READ(LCFUSE02);
5270
5271 dev_priv->corr = (lcfuse & LCFUSE_HIV_MASK);
5272}
5273
5111void intel_init_clock_gating(struct drm_device *dev) 5274void intel_init_clock_gating(struct drm_device *dev)
5112{ 5275{
5113 struct drm_i915_private *dev_priv = dev->dev_private; 5276 struct drm_i915_private *dev_priv = dev->dev_private;
@@ -5277,11 +5440,13 @@ static void intel_init_display(struct drm_device *dev)
5277 dev_priv->display.update_wm = NULL; 5440 dev_priv->display.update_wm = NULL;
5278 } else if (IS_PINEVIEW(dev)) { 5441 } else if (IS_PINEVIEW(dev)) {
5279 if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev), 5442 if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev),
5443 dev_priv->is_ddr3,
5280 dev_priv->fsb_freq, 5444 dev_priv->fsb_freq,
5281 dev_priv->mem_freq)) { 5445 dev_priv->mem_freq)) {
5282 DRM_INFO("failed to find known CxSR latency " 5446 DRM_INFO("failed to find known CxSR latency "
5283 "(found fsb freq %d, mem freq %d), " 5447 "(found ddr%s fsb freq %d, mem freq %d), "
5284 "disabling CxSR\n", 5448 "disabling CxSR\n",
5449 (dev_priv->is_ddr3 == 1) ? "3": "2",
5285 dev_priv->fsb_freq, dev_priv->mem_freq); 5450 dev_priv->fsb_freq, dev_priv->mem_freq);
5286 /* Disable CxSR and never update its watermark again */ 5451 /* Disable CxSR and never update its watermark again */
5287 pineview_disable_cxsr(dev); 5452 pineview_disable_cxsr(dev);
@@ -5310,7 +5475,6 @@ static void intel_init_display(struct drm_device *dev)
5310void intel_modeset_init(struct drm_device *dev) 5475void intel_modeset_init(struct drm_device *dev)
5311{ 5476{
5312 struct drm_i915_private *dev_priv = dev->dev_private; 5477 struct drm_i915_private *dev_priv = dev->dev_private;
5313 int num_pipe;
5314 int i; 5478 int i;
5315 5479
5316 drm_mode_config_init(dev); 5480 drm_mode_config_init(dev);
@@ -5340,13 +5504,13 @@ void intel_modeset_init(struct drm_device *dev)
5340 dev->mode_config.fb_base = pci_resource_start(dev->pdev, 0); 5504 dev->mode_config.fb_base = pci_resource_start(dev->pdev, 0);
5341 5505
5342 if (IS_MOBILE(dev) || IS_I9XX(dev)) 5506 if (IS_MOBILE(dev) || IS_I9XX(dev))
5343 num_pipe = 2; 5507 dev_priv->num_pipe = 2;
5344 else 5508 else
5345 num_pipe = 1; 5509 dev_priv->num_pipe = 1;
5346 DRM_DEBUG_KMS("%d display pipe%s available.\n", 5510 DRM_DEBUG_KMS("%d display pipe%s available.\n",
5347 num_pipe, num_pipe > 1 ? "s" : ""); 5511 dev_priv->num_pipe, dev_priv->num_pipe > 1 ? "s" : "");
5348 5512
5349 for (i = 0; i < num_pipe; i++) { 5513 for (i = 0; i < dev_priv->num_pipe; i++) {
5350 intel_crtc_init(dev, i); 5514 intel_crtc_init(dev, i);
5351 } 5515 }
5352 5516
@@ -5354,8 +5518,10 @@ void intel_modeset_init(struct drm_device *dev)
5354 5518
5355 intel_init_clock_gating(dev); 5519 intel_init_clock_gating(dev);
5356 5520
5357 if (IS_IRONLAKE_M(dev)) 5521 if (IS_IRONLAKE_M(dev)) {
5358 ironlake_enable_drps(dev); 5522 ironlake_enable_drps(dev);
5523 intel_init_emon(dev);
5524 }
5359 5525
5360 INIT_WORK(&dev_priv->idle_work, intel_idle_update); 5526 INIT_WORK(&dev_priv->idle_work, intel_idle_update);
5361 setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer, 5527 setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer,
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 6b1c9a27c27a..49b54f05d3cf 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -576,7 +576,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
576 struct intel_encoder *intel_encoder; 576 struct intel_encoder *intel_encoder;
577 struct intel_dp_priv *dp_priv; 577 struct intel_dp_priv *dp_priv;
578 578
579 if (!encoder || encoder->crtc != crtc) 579 if (encoder->crtc != crtc)
580 continue; 580 continue;
581 581
582 intel_encoder = enc_to_intel_encoder(encoder); 582 intel_encoder = enc_to_intel_encoder(encoder);
@@ -675,10 +675,9 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
675 dp_priv->link_configuration[1] = dp_priv->lane_count; 675 dp_priv->link_configuration[1] = dp_priv->lane_count;
676 676
677 /* 677 /*
678 * Check for DPCD version > 1.1, 678 * Check for DPCD version > 1.1 and enhanced framing support
679 * enable enahanced frame stuff in that case
680 */ 679 */
681 if (dp_priv->dpcd[0] >= 0x11) { 680 if (dp_priv->dpcd[0] >= 0x11 && (dp_priv->dpcd[2] & DP_ENHANCED_FRAME_CAP)) {
682 dp_priv->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; 681 dp_priv->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
683 dp_priv->DP |= DP_ENHANCED_FRAMING; 682 dp_priv->DP |= DP_ENHANCED_FRAMING;
684 } 683 }
@@ -1208,6 +1207,8 @@ ironlake_dp_detect(struct drm_connector *connector)
1208 if (dp_priv->dpcd[0] != 0) 1207 if (dp_priv->dpcd[0] != 0)
1209 status = connector_status_connected; 1208 status = connector_status_connected;
1210 } 1209 }
1210 DRM_DEBUG_KMS("DPCD: %hx%hx%hx%hx\n", dp_priv->dpcd[0],
1211 dp_priv->dpcd[1], dp_priv->dpcd[2], dp_priv->dpcd[3]);
1211 return status; 1212 return status;
1212} 1213}
1213 1214
@@ -1352,7 +1353,7 @@ intel_trans_dp_port_sel (struct drm_crtc *crtc)
1352 struct intel_encoder *intel_encoder = NULL; 1353 struct intel_encoder *intel_encoder = NULL;
1353 1354
1354 list_for_each_entry(encoder, &mode_config->encoder_list, head) { 1355 list_for_each_entry(encoder, &mode_config->encoder_list, head) {
1355 if (!encoder || encoder->crtc != crtc) 1356 if (encoder->crtc != crtc)
1356 continue; 1357 continue;
1357 1358
1358 intel_encoder = enc_to_intel_encoder(encoder); 1359 intel_encoder = enc_to_intel_encoder(encoder);
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c
index 6f53cf7fbc50..c3c505244e07 100644
--- a/drivers/gpu/drm/i915/intel_fb.c
+++ b/drivers/gpu/drm/i915/intel_fb.c
@@ -105,7 +105,11 @@ static int intelfb_create(struct intel_fbdev *ifbdev,
105 } 105 }
106 106
107 /* Flush everything out, we'll be doing GTT only from now on */ 107 /* Flush everything out, we'll be doing GTT only from now on */
108 i915_gem_object_set_to_gtt_domain(fbo, 1); 108 ret = i915_gem_object_set_to_gtt_domain(fbo, 1);
109 if (ret) {
110 DRM_ERROR("failed to bind fb: %d.\n", ret);
111 goto out_unpin;
112 }
109 113
110 info = framebuffer_alloc(0, device); 114 info = framebuffer_alloc(0, device);
111 if (!info) { 115 if (!info) {
@@ -241,6 +245,7 @@ int intel_fbdev_init(struct drm_device *dev)
241{ 245{
242 struct intel_fbdev *ifbdev; 246 struct intel_fbdev *ifbdev;
243 drm_i915_private_t *dev_priv = dev->dev_private; 247 drm_i915_private_t *dev_priv = dev->dev_private;
248 int ret;
244 249
245 ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL); 250 ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL);
246 if (!ifbdev) 251 if (!ifbdev)
@@ -249,8 +254,13 @@ int intel_fbdev_init(struct drm_device *dev)
249 dev_priv->fbdev = ifbdev; 254 dev_priv->fbdev = ifbdev;
250 ifbdev->helper.funcs = &intel_fb_helper_funcs; 255 ifbdev->helper.funcs = &intel_fb_helper_funcs;
251 256
252 drm_fb_helper_init(dev, &ifbdev->helper, 2, 257 ret = drm_fb_helper_init(dev, &ifbdev->helper,
253 INTELFB_CONN_LIMIT); 258 dev_priv->num_pipe,
259 INTELFB_CONN_LIMIT);
260 if (ret) {
261 kfree(ifbdev);
262 return ret;
263 }
254 264
255 drm_fb_helper_single_add_all_connectors(&ifbdev->helper); 265 drm_fb_helper_single_add_all_connectors(&ifbdev->helper);
256 drm_fb_helper_initial_config(&ifbdev->helper, 32); 266 drm_fb_helper_initial_config(&ifbdev->helper, 32);
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 65727f0a79a3..83bd764b000e 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -59,8 +59,11 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
59 SDVO_VSYNC_ACTIVE_HIGH | 59 SDVO_VSYNC_ACTIVE_HIGH |
60 SDVO_HSYNC_ACTIVE_HIGH; 60 SDVO_HSYNC_ACTIVE_HIGH;
61 61
62 if (hdmi_priv->has_hdmi_sink) 62 if (hdmi_priv->has_hdmi_sink) {
63 sdvox |= SDVO_AUDIO_ENABLE; 63 sdvox |= SDVO_AUDIO_ENABLE;
64 if (HAS_PCH_CPT(dev))
65 sdvox |= HDMI_MODE_SELECT;
66 }
64 67
65 if (intel_crtc->pipe == 1) { 68 if (intel_crtc->pipe == 1) {
66 if (HAS_PCH_CPT(dev)) 69 if (HAS_PCH_CPT(dev))
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
index b0e17b06eb6e..d7ad5139d17c 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -211,9 +211,8 @@ static void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay)
211static int intel_overlay_on(struct intel_overlay *overlay) 211static int intel_overlay_on(struct intel_overlay *overlay)
212{ 212{
213 struct drm_device *dev = overlay->dev; 213 struct drm_device *dev = overlay->dev;
214 drm_i915_private_t *dev_priv = dev->dev_private;
215 int ret; 214 int ret;
216 RING_LOCALS; 215 drm_i915_private_t *dev_priv = dev->dev_private;
217 216
218 BUG_ON(overlay->active); 217 BUG_ON(overlay->active);
219 218
@@ -227,11 +226,13 @@ static int intel_overlay_on(struct intel_overlay *overlay)
227 OUT_RING(MI_NOOP); 226 OUT_RING(MI_NOOP);
228 ADVANCE_LP_RING(); 227 ADVANCE_LP_RING();
229 228
230 overlay->last_flip_req = i915_add_request(dev, NULL, 0); 229 overlay->last_flip_req =
230 i915_add_request(dev, NULL, 0, &dev_priv->render_ring);
231 if (overlay->last_flip_req == 0) 231 if (overlay->last_flip_req == 0)
232 return -ENOMEM; 232 return -ENOMEM;
233 233
234 ret = i915_do_wait_request(dev, overlay->last_flip_req, 1); 234 ret = i915_do_wait_request(dev,
235 overlay->last_flip_req, 1, &dev_priv->render_ring);
235 if (ret != 0) 236 if (ret != 0)
236 return ret; 237 return ret;
237 238
@@ -248,7 +249,6 @@ static void intel_overlay_continue(struct intel_overlay *overlay,
248 drm_i915_private_t *dev_priv = dev->dev_private; 249 drm_i915_private_t *dev_priv = dev->dev_private;
249 u32 flip_addr = overlay->flip_addr; 250 u32 flip_addr = overlay->flip_addr;
250 u32 tmp; 251 u32 tmp;
251 RING_LOCALS;
252 252
253 BUG_ON(!overlay->active); 253 BUG_ON(!overlay->active);
254 254
@@ -265,7 +265,8 @@ static void intel_overlay_continue(struct intel_overlay *overlay,
265 OUT_RING(flip_addr); 265 OUT_RING(flip_addr);
266 ADVANCE_LP_RING(); 266 ADVANCE_LP_RING();
267 267
268 overlay->last_flip_req = i915_add_request(dev, NULL, 0); 268 overlay->last_flip_req =
269 i915_add_request(dev, NULL, 0, &dev_priv->render_ring);
269} 270}
270 271
271static int intel_overlay_wait_flip(struct intel_overlay *overlay) 272static int intel_overlay_wait_flip(struct intel_overlay *overlay)
@@ -274,10 +275,10 @@ static int intel_overlay_wait_flip(struct intel_overlay *overlay)
274 drm_i915_private_t *dev_priv = dev->dev_private; 275 drm_i915_private_t *dev_priv = dev->dev_private;
275 int ret; 276 int ret;
276 u32 tmp; 277 u32 tmp;
277 RING_LOCALS;
278 278
279 if (overlay->last_flip_req != 0) { 279 if (overlay->last_flip_req != 0) {
280 ret = i915_do_wait_request(dev, overlay->last_flip_req, 1); 280 ret = i915_do_wait_request(dev, overlay->last_flip_req,
281 1, &dev_priv->render_ring);
281 if (ret == 0) { 282 if (ret == 0) {
282 overlay->last_flip_req = 0; 283 overlay->last_flip_req = 0;
283 284
@@ -296,11 +297,13 @@ static int intel_overlay_wait_flip(struct intel_overlay *overlay)
296 OUT_RING(MI_NOOP); 297 OUT_RING(MI_NOOP);
297 ADVANCE_LP_RING(); 298 ADVANCE_LP_RING();
298 299
299 overlay->last_flip_req = i915_add_request(dev, NULL, 0); 300 overlay->last_flip_req =
301 i915_add_request(dev, NULL, 0, &dev_priv->render_ring);
300 if (overlay->last_flip_req == 0) 302 if (overlay->last_flip_req == 0)
301 return -ENOMEM; 303 return -ENOMEM;
302 304
303 ret = i915_do_wait_request(dev, overlay->last_flip_req, 1); 305 ret = i915_do_wait_request(dev, overlay->last_flip_req,
306 1, &dev_priv->render_ring);
304 if (ret != 0) 307 if (ret != 0)
305 return ret; 308 return ret;
306 309
@@ -314,9 +317,8 @@ static int intel_overlay_off(struct intel_overlay *overlay)
314{ 317{
315 u32 flip_addr = overlay->flip_addr; 318 u32 flip_addr = overlay->flip_addr;
316 struct drm_device *dev = overlay->dev; 319 struct drm_device *dev = overlay->dev;
317 drm_i915_private_t *dev_priv = dev->dev_private; 320 drm_i915_private_t *dev_priv = dev->dev_private;
318 int ret; 321 int ret;
319 RING_LOCALS;
320 322
321 BUG_ON(!overlay->active); 323 BUG_ON(!overlay->active);
322 324
@@ -336,11 +338,13 @@ static int intel_overlay_off(struct intel_overlay *overlay)
336 OUT_RING(MI_NOOP); 338 OUT_RING(MI_NOOP);
337 ADVANCE_LP_RING(); 339 ADVANCE_LP_RING();
338 340
339 overlay->last_flip_req = i915_add_request(dev, NULL, 0); 341 overlay->last_flip_req =
342 i915_add_request(dev, NULL, 0, &dev_priv->render_ring);
340 if (overlay->last_flip_req == 0) 343 if (overlay->last_flip_req == 0)
341 return -ENOMEM; 344 return -ENOMEM;
342 345
343 ret = i915_do_wait_request(dev, overlay->last_flip_req, 1); 346 ret = i915_do_wait_request(dev, overlay->last_flip_req,
347 1, &dev_priv->render_ring);
344 if (ret != 0) 348 if (ret != 0)
345 return ret; 349 return ret;
346 350
@@ -354,11 +358,13 @@ static int intel_overlay_off(struct intel_overlay *overlay)
354 OUT_RING(MI_NOOP); 358 OUT_RING(MI_NOOP);
355 ADVANCE_LP_RING(); 359 ADVANCE_LP_RING();
356 360
357 overlay->last_flip_req = i915_add_request(dev, NULL, 0); 361 overlay->last_flip_req =
362 i915_add_request(dev, NULL, 0, &dev_priv->render_ring);
358 if (overlay->last_flip_req == 0) 363 if (overlay->last_flip_req == 0)
359 return -ENOMEM; 364 return -ENOMEM;
360 365
361 ret = i915_do_wait_request(dev, overlay->last_flip_req, 1); 366 ret = i915_do_wait_request(dev, overlay->last_flip_req,
367 1, &dev_priv->render_ring);
362 if (ret != 0) 368 if (ret != 0)
363 return ret; 369 return ret;
364 370
@@ -390,22 +396,23 @@ int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay,
390 int interruptible) 396 int interruptible)
391{ 397{
392 struct drm_device *dev = overlay->dev; 398 struct drm_device *dev = overlay->dev;
393 drm_i915_private_t *dev_priv = dev->dev_private;
394 struct drm_gem_object *obj; 399 struct drm_gem_object *obj;
400 drm_i915_private_t *dev_priv = dev->dev_private;
395 u32 flip_addr; 401 u32 flip_addr;
396 int ret; 402 int ret;
397 RING_LOCALS;
398 403
399 if (overlay->hw_wedged == HW_WEDGED) 404 if (overlay->hw_wedged == HW_WEDGED)
400 return -EIO; 405 return -EIO;
401 406
402 if (overlay->last_flip_req == 0) { 407 if (overlay->last_flip_req == 0) {
403 overlay->last_flip_req = i915_add_request(dev, NULL, 0); 408 overlay->last_flip_req =
409 i915_add_request(dev, NULL, 0, &dev_priv->render_ring);
404 if (overlay->last_flip_req == 0) 410 if (overlay->last_flip_req == 0)
405 return -ENOMEM; 411 return -ENOMEM;
406 } 412 }
407 413
408 ret = i915_do_wait_request(dev, overlay->last_flip_req, interruptible); 414 ret = i915_do_wait_request(dev, overlay->last_flip_req,
415 interruptible, &dev_priv->render_ring);
409 if (ret != 0) 416 if (ret != 0)
410 return ret; 417 return ret;
411 418
@@ -429,12 +436,13 @@ int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay,
429 OUT_RING(MI_NOOP); 436 OUT_RING(MI_NOOP);
430 ADVANCE_LP_RING(); 437 ADVANCE_LP_RING();
431 438
432 overlay->last_flip_req = i915_add_request(dev, NULL, 0); 439 overlay->last_flip_req = i915_add_request(dev, NULL,
440 0, &dev_priv->render_ring);
433 if (overlay->last_flip_req == 0) 441 if (overlay->last_flip_req == 0)
434 return -ENOMEM; 442 return -ENOMEM;
435 443
436 ret = i915_do_wait_request(dev, overlay->last_flip_req, 444 ret = i915_do_wait_request(dev, overlay->last_flip_req,
437 interruptible); 445 interruptible, &dev_priv->render_ring);
438 if (ret != 0) 446 if (ret != 0)
439 return ret; 447 return ret;
440 448
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
new file mode 100644
index 000000000000..cea4f1a8709e
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -0,0 +1,849 @@
1/*
2 * Copyright © 2008-2010 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 *
23 * Authors:
24 * Eric Anholt <eric@anholt.net>
25 * Zou Nan hai <nanhai.zou@intel.com>
26 * Xiang Hai hao<haihao.xiang@intel.com>
27 *
28 */
29
30#include "drmP.h"
31#include "drm.h"
32#include "i915_drv.h"
33#include "i915_drm.h"
34#include "i915_trace.h"
35
36static void
37render_ring_flush(struct drm_device *dev,
38 struct intel_ring_buffer *ring,
39 u32 invalidate_domains,
40 u32 flush_domains)
41{
42#if WATCH_EXEC
43 DRM_INFO("%s: invalidate %08x flush %08x\n", __func__,
44 invalidate_domains, flush_domains);
45#endif
46 u32 cmd;
47 trace_i915_gem_request_flush(dev, ring->next_seqno,
48 invalidate_domains, flush_domains);
49
50 if ((invalidate_domains | flush_domains) & I915_GEM_GPU_DOMAINS) {
51 /*
52 * read/write caches:
53 *
54 * I915_GEM_DOMAIN_RENDER is always invalidated, but is
55 * only flushed if MI_NO_WRITE_FLUSH is unset. On 965, it is
56 * also flushed at 2d versus 3d pipeline switches.
57 *
58 * read-only caches:
59 *
60 * I915_GEM_DOMAIN_SAMPLER is flushed on pre-965 if
61 * MI_READ_FLUSH is set, and is always flushed on 965.
62 *
63 * I915_GEM_DOMAIN_COMMAND may not exist?
64 *
65 * I915_GEM_DOMAIN_INSTRUCTION, which exists on 965, is
66 * invalidated when MI_EXE_FLUSH is set.
67 *
68 * I915_GEM_DOMAIN_VERTEX, which exists on 965, is
69 * invalidated with every MI_FLUSH.
70 *
71 * TLBs:
72 *
73 * On 965, TLBs associated with I915_GEM_DOMAIN_COMMAND
74 * and I915_GEM_DOMAIN_CPU in are invalidated at PTE write and
75 * I915_GEM_DOMAIN_RENDER and I915_GEM_DOMAIN_SAMPLER
76 * are flushed at any MI_FLUSH.
77 */
78
79 cmd = MI_FLUSH | MI_NO_WRITE_FLUSH;
80 if ((invalidate_domains|flush_domains) &
81 I915_GEM_DOMAIN_RENDER)
82 cmd &= ~MI_NO_WRITE_FLUSH;
83 if (!IS_I965G(dev)) {
84 /*
85 * On the 965, the sampler cache always gets flushed
86 * and this bit is reserved.
87 */
88 if (invalidate_domains & I915_GEM_DOMAIN_SAMPLER)
89 cmd |= MI_READ_FLUSH;
90 }
91 if (invalidate_domains & I915_GEM_DOMAIN_INSTRUCTION)
92 cmd |= MI_EXE_FLUSH;
93
94#if WATCH_EXEC
95 DRM_INFO("%s: queue flush %08x to ring\n", __func__, cmd);
96#endif
97 intel_ring_begin(dev, ring, 8);
98 intel_ring_emit(dev, ring, cmd);
99 intel_ring_emit(dev, ring, MI_NOOP);
100 intel_ring_advance(dev, ring);
101 }
102}
103
104static unsigned int render_ring_get_head(struct drm_device *dev,
105 struct intel_ring_buffer *ring)
106{
107 drm_i915_private_t *dev_priv = dev->dev_private;
108 return I915_READ(PRB0_HEAD) & HEAD_ADDR;
109}
110
111static unsigned int render_ring_get_tail(struct drm_device *dev,
112 struct intel_ring_buffer *ring)
113{
114 drm_i915_private_t *dev_priv = dev->dev_private;
115 return I915_READ(PRB0_TAIL) & TAIL_ADDR;
116}
117
118static unsigned int render_ring_get_active_head(struct drm_device *dev,
119 struct intel_ring_buffer *ring)
120{
121 drm_i915_private_t *dev_priv = dev->dev_private;
122 u32 acthd_reg = IS_I965G(dev) ? ACTHD_I965 : ACTHD;
123
124 return I915_READ(acthd_reg);
125}
126
127static void render_ring_advance_ring(struct drm_device *dev,
128 struct intel_ring_buffer *ring)
129{
130 drm_i915_private_t *dev_priv = dev->dev_private;
131 I915_WRITE(PRB0_TAIL, ring->tail);
132}
133
134static int init_ring_common(struct drm_device *dev,
135 struct intel_ring_buffer *ring)
136{
137 u32 head;
138 drm_i915_private_t *dev_priv = dev->dev_private;
139 struct drm_i915_gem_object *obj_priv;
140 obj_priv = to_intel_bo(ring->gem_object);
141
142 /* Stop the ring if it's running. */
143 I915_WRITE(ring->regs.ctl, 0);
144 I915_WRITE(ring->regs.head, 0);
145 I915_WRITE(ring->regs.tail, 0);
146
147 /* Initialize the ring. */
148 I915_WRITE(ring->regs.start, obj_priv->gtt_offset);
149 head = ring->get_head(dev, ring);
150
151 /* G45 ring initialization fails to reset head to zero */
152 if (head != 0) {
153 DRM_ERROR("%s head not reset to zero "
154 "ctl %08x head %08x tail %08x start %08x\n",
155 ring->name,
156 I915_READ(ring->regs.ctl),
157 I915_READ(ring->regs.head),
158 I915_READ(ring->regs.tail),
159 I915_READ(ring->regs.start));
160
161 I915_WRITE(ring->regs.head, 0);
162
163 DRM_ERROR("%s head forced to zero "
164 "ctl %08x head %08x tail %08x start %08x\n",
165 ring->name,
166 I915_READ(ring->regs.ctl),
167 I915_READ(ring->regs.head),
168 I915_READ(ring->regs.tail),
169 I915_READ(ring->regs.start));
170 }
171
172 I915_WRITE(ring->regs.ctl,
173 ((ring->gem_object->size - PAGE_SIZE) & RING_NR_PAGES)
174 | RING_NO_REPORT | RING_VALID);
175
176 head = I915_READ(ring->regs.head) & HEAD_ADDR;
177 /* If the head is still not zero, the ring is dead */
178 if (head != 0) {
179 DRM_ERROR("%s initialization failed "
180 "ctl %08x head %08x tail %08x start %08x\n",
181 ring->name,
182 I915_READ(ring->regs.ctl),
183 I915_READ(ring->regs.head),
184 I915_READ(ring->regs.tail),
185 I915_READ(ring->regs.start));
186 return -EIO;
187 }
188
189 if (!drm_core_check_feature(dev, DRIVER_MODESET))
190 i915_kernel_lost_context(dev);
191 else {
192 ring->head = ring->get_head(dev, ring);
193 ring->tail = ring->get_tail(dev, ring);
194 ring->space = ring->head - (ring->tail + 8);
195 if (ring->space < 0)
196 ring->space += ring->size;
197 }
198 return 0;
199}
200
201static int init_render_ring(struct drm_device *dev,
202 struct intel_ring_buffer *ring)
203{
204 drm_i915_private_t *dev_priv = dev->dev_private;
205 int ret = init_ring_common(dev, ring);
206 if (IS_I9XX(dev) && !IS_GEN3(dev)) {
207 I915_WRITE(MI_MODE,
208 (VS_TIMER_DISPATCH) << 16 | VS_TIMER_DISPATCH);
209 }
210 return ret;
211}
212
213#define PIPE_CONTROL_FLUSH(addr) \
214do { \
215 OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE | \
216 PIPE_CONTROL_DEPTH_STALL | 2); \
217 OUT_RING(addr | PIPE_CONTROL_GLOBAL_GTT); \
218 OUT_RING(0); \
219 OUT_RING(0); \
220} while (0)
221
222/**
223 * Creates a new sequence number, emitting a write of it to the status page
224 * plus an interrupt, which will trigger i915_user_interrupt_handler.
225 *
226 * Must be called with struct_lock held.
227 *
228 * Returned sequence numbers are nonzero on success.
229 */
230static u32
231render_ring_add_request(struct drm_device *dev,
232 struct intel_ring_buffer *ring,
233 struct drm_file *file_priv,
234 u32 flush_domains)
235{
236 u32 seqno;
237 drm_i915_private_t *dev_priv = dev->dev_private;
238 seqno = intel_ring_get_seqno(dev, ring);
239
240 if (IS_GEN6(dev)) {
241 BEGIN_LP_RING(6);
242 OUT_RING(GFX_OP_PIPE_CONTROL | 3);
243 OUT_RING(PIPE_CONTROL_QW_WRITE |
244 PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_IS_FLUSH |
245 PIPE_CONTROL_NOTIFY);
246 OUT_RING(dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT);
247 OUT_RING(seqno);
248 OUT_RING(0);
249 OUT_RING(0);
250 ADVANCE_LP_RING();
251 } else if (HAS_PIPE_CONTROL(dev)) {
252 u32 scratch_addr = dev_priv->seqno_gfx_addr + 128;
253
254 /*
255 * Workaround qword write incoherence by flushing the
256 * PIPE_NOTIFY buffers out to memory before requesting
257 * an interrupt.
258 */
259 BEGIN_LP_RING(32);
260 OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |
261 PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH);
262 OUT_RING(dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT);
263 OUT_RING(seqno);
264 OUT_RING(0);
265 PIPE_CONTROL_FLUSH(scratch_addr);
266 scratch_addr += 128; /* write to separate cachelines */
267 PIPE_CONTROL_FLUSH(scratch_addr);
268 scratch_addr += 128;
269 PIPE_CONTROL_FLUSH(scratch_addr);
270 scratch_addr += 128;
271 PIPE_CONTROL_FLUSH(scratch_addr);
272 scratch_addr += 128;
273 PIPE_CONTROL_FLUSH(scratch_addr);
274 scratch_addr += 128;
275 PIPE_CONTROL_FLUSH(scratch_addr);
276 OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |
277 PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH |
278 PIPE_CONTROL_NOTIFY);
279 OUT_RING(dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT);
280 OUT_RING(seqno);
281 OUT_RING(0);
282 ADVANCE_LP_RING();
283 } else {
284 BEGIN_LP_RING(4);
285 OUT_RING(MI_STORE_DWORD_INDEX);
286 OUT_RING(I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
287 OUT_RING(seqno);
288
289 OUT_RING(MI_USER_INTERRUPT);
290 ADVANCE_LP_RING();
291 }
292 return seqno;
293}
294
295static u32
296render_ring_get_gem_seqno(struct drm_device *dev,
297 struct intel_ring_buffer *ring)
298{
299 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
300 if (HAS_PIPE_CONTROL(dev))
301 return ((volatile u32 *)(dev_priv->seqno_page))[0];
302 else
303 return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
304}
305
306static void
307render_ring_get_user_irq(struct drm_device *dev,
308 struct intel_ring_buffer *ring)
309{
310 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
311 unsigned long irqflags;
312
313 spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
314 if (dev->irq_enabled && (++ring->user_irq_refcount == 1)) {
315 if (HAS_PCH_SPLIT(dev))
316 ironlake_enable_graphics_irq(dev_priv, GT_PIPE_NOTIFY);
317 else
318 i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
319 }
320 spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
321}
322
323static void
324render_ring_put_user_irq(struct drm_device *dev,
325 struct intel_ring_buffer *ring)
326{
327 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
328 unsigned long irqflags;
329
330 spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
331 BUG_ON(dev->irq_enabled && ring->user_irq_refcount <= 0);
332 if (dev->irq_enabled && (--ring->user_irq_refcount == 0)) {
333 if (HAS_PCH_SPLIT(dev))
334 ironlake_disable_graphics_irq(dev_priv, GT_PIPE_NOTIFY);
335 else
336 i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
337 }
338 spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
339}
340
341static void render_setup_status_page(struct drm_device *dev,
342 struct intel_ring_buffer *ring)
343{
344 drm_i915_private_t *dev_priv = dev->dev_private;
345 if (IS_GEN6(dev)) {
346 I915_WRITE(HWS_PGA_GEN6, ring->status_page.gfx_addr);
347 I915_READ(HWS_PGA_GEN6); /* posting read */
348 } else {
349 I915_WRITE(HWS_PGA, ring->status_page.gfx_addr);
350 I915_READ(HWS_PGA); /* posting read */
351 }
352
353}
354
355void
356bsd_ring_flush(struct drm_device *dev,
357 struct intel_ring_buffer *ring,
358 u32 invalidate_domains,
359 u32 flush_domains)
360{
361 intel_ring_begin(dev, ring, 8);
362 intel_ring_emit(dev, ring, MI_FLUSH);
363 intel_ring_emit(dev, ring, MI_NOOP);
364 intel_ring_advance(dev, ring);
365}
366
367static inline unsigned int bsd_ring_get_head(struct drm_device *dev,
368 struct intel_ring_buffer *ring)
369{
370 drm_i915_private_t *dev_priv = dev->dev_private;
371 return I915_READ(BSD_RING_HEAD) & HEAD_ADDR;
372}
373
374static inline unsigned int bsd_ring_get_tail(struct drm_device *dev,
375 struct intel_ring_buffer *ring)
376{
377 drm_i915_private_t *dev_priv = dev->dev_private;
378 return I915_READ(BSD_RING_TAIL) & TAIL_ADDR;
379}
380
381static inline unsigned int bsd_ring_get_active_head(struct drm_device *dev,
382 struct intel_ring_buffer *ring)
383{
384 drm_i915_private_t *dev_priv = dev->dev_private;
385 return I915_READ(BSD_RING_ACTHD);
386}
387
388static inline void bsd_ring_advance_ring(struct drm_device *dev,
389 struct intel_ring_buffer *ring)
390{
391 drm_i915_private_t *dev_priv = dev->dev_private;
392 I915_WRITE(BSD_RING_TAIL, ring->tail);
393}
394
395static int init_bsd_ring(struct drm_device *dev,
396 struct intel_ring_buffer *ring)
397{
398 return init_ring_common(dev, ring);
399}
400
401static u32
402bsd_ring_add_request(struct drm_device *dev,
403 struct intel_ring_buffer *ring,
404 struct drm_file *file_priv,
405 u32 flush_domains)
406{
407 u32 seqno;
408 seqno = intel_ring_get_seqno(dev, ring);
409 intel_ring_begin(dev, ring, 4);
410 intel_ring_emit(dev, ring, MI_STORE_DWORD_INDEX);
411 intel_ring_emit(dev, ring,
412 I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
413 intel_ring_emit(dev, ring, seqno);
414 intel_ring_emit(dev, ring, MI_USER_INTERRUPT);
415 intel_ring_advance(dev, ring);
416
417 DRM_DEBUG_DRIVER("%s %d\n", ring->name, seqno);
418
419 return seqno;
420}
421
422static void bsd_setup_status_page(struct drm_device *dev,
423 struct intel_ring_buffer *ring)
424{
425 drm_i915_private_t *dev_priv = dev->dev_private;
426 I915_WRITE(BSD_HWS_PGA, ring->status_page.gfx_addr);
427 I915_READ(BSD_HWS_PGA);
428}
429
430static void
431bsd_ring_get_user_irq(struct drm_device *dev,
432 struct intel_ring_buffer *ring)
433{
434 /* do nothing */
435}
436static void
437bsd_ring_put_user_irq(struct drm_device *dev,
438 struct intel_ring_buffer *ring)
439{
440 /* do nothing */
441}
442
443static u32
444bsd_ring_get_gem_seqno(struct drm_device *dev,
445 struct intel_ring_buffer *ring)
446{
447 return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
448}
449
450static int
451bsd_ring_dispatch_gem_execbuffer(struct drm_device *dev,
452 struct intel_ring_buffer *ring,
453 struct drm_i915_gem_execbuffer2 *exec,
454 struct drm_clip_rect *cliprects,
455 uint64_t exec_offset)
456{
457 uint32_t exec_start;
458 exec_start = (uint32_t) exec_offset + exec->batch_start_offset;
459 intel_ring_begin(dev, ring, 2);
460 intel_ring_emit(dev, ring, MI_BATCH_BUFFER_START |
461 (2 << 6) | MI_BATCH_NON_SECURE_I965);
462 intel_ring_emit(dev, ring, exec_start);
463 intel_ring_advance(dev, ring);
464 return 0;
465}
466
467
468static int
469render_ring_dispatch_gem_execbuffer(struct drm_device *dev,
470 struct intel_ring_buffer *ring,
471 struct drm_i915_gem_execbuffer2 *exec,
472 struct drm_clip_rect *cliprects,
473 uint64_t exec_offset)
474{
475 drm_i915_private_t *dev_priv = dev->dev_private;
476 int nbox = exec->num_cliprects;
477 int i = 0, count;
478 uint32_t exec_start, exec_len;
479 exec_start = (uint32_t) exec_offset + exec->batch_start_offset;
480 exec_len = (uint32_t) exec->batch_len;
481
482 trace_i915_gem_request_submit(dev, dev_priv->mm.next_gem_seqno + 1);
483
484 count = nbox ? nbox : 1;
485
486 for (i = 0; i < count; i++) {
487 if (i < nbox) {
488 int ret = i915_emit_box(dev, cliprects, i,
489 exec->DR1, exec->DR4);
490 if (ret)
491 return ret;
492 }
493
494 if (IS_I830(dev) || IS_845G(dev)) {
495 intel_ring_begin(dev, ring, 4);
496 intel_ring_emit(dev, ring, MI_BATCH_BUFFER);
497 intel_ring_emit(dev, ring,
498 exec_start | MI_BATCH_NON_SECURE);
499 intel_ring_emit(dev, ring, exec_start + exec_len - 4);
500 intel_ring_emit(dev, ring, 0);
501 } else {
502 intel_ring_begin(dev, ring, 4);
503 if (IS_I965G(dev)) {
504 intel_ring_emit(dev, ring,
505 MI_BATCH_BUFFER_START | (2 << 6)
506 | MI_BATCH_NON_SECURE_I965);
507 intel_ring_emit(dev, ring, exec_start);
508 } else {
509 intel_ring_emit(dev, ring, MI_BATCH_BUFFER_START
510 | (2 << 6));
511 intel_ring_emit(dev, ring, exec_start |
512 MI_BATCH_NON_SECURE);
513 }
514 }
515 intel_ring_advance(dev, ring);
516 }
517
518 /* XXX breadcrumb */
519 return 0;
520}
521
522static void cleanup_status_page(struct drm_device *dev,
523 struct intel_ring_buffer *ring)
524{
525 drm_i915_private_t *dev_priv = dev->dev_private;
526 struct drm_gem_object *obj;
527 struct drm_i915_gem_object *obj_priv;
528
529 obj = ring->status_page.obj;
530 if (obj == NULL)
531 return;
532 obj_priv = to_intel_bo(obj);
533
534 kunmap(obj_priv->pages[0]);
535 i915_gem_object_unpin(obj);
536 drm_gem_object_unreference(obj);
537 ring->status_page.obj = NULL;
538
539 memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
540}
541
542static int init_status_page(struct drm_device *dev,
543 struct intel_ring_buffer *ring)
544{
545 drm_i915_private_t *dev_priv = dev->dev_private;
546 struct drm_gem_object *obj;
547 struct drm_i915_gem_object *obj_priv;
548 int ret;
549
550 obj = i915_gem_alloc_object(dev, 4096);
551 if (obj == NULL) {
552 DRM_ERROR("Failed to allocate status page\n");
553 ret = -ENOMEM;
554 goto err;
555 }
556 obj_priv = to_intel_bo(obj);
557 obj_priv->agp_type = AGP_USER_CACHED_MEMORY;
558
559 ret = i915_gem_object_pin(obj, 4096);
560 if (ret != 0) {
561 goto err_unref;
562 }
563
564 ring->status_page.gfx_addr = obj_priv->gtt_offset;
565 ring->status_page.page_addr = kmap(obj_priv->pages[0]);
566 if (ring->status_page.page_addr == NULL) {
567 memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
568 goto err_unpin;
569 }
570 ring->status_page.obj = obj;
571 memset(ring->status_page.page_addr, 0, PAGE_SIZE);
572
573 ring->setup_status_page(dev, ring);
574 DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n",
575 ring->name, ring->status_page.gfx_addr);
576
577 return 0;
578
579err_unpin:
580 i915_gem_object_unpin(obj);
581err_unref:
582 drm_gem_object_unreference(obj);
583err:
584 return ret;
585}
586
587
588int intel_init_ring_buffer(struct drm_device *dev,
589 struct intel_ring_buffer *ring)
590{
591 int ret;
592 struct drm_i915_gem_object *obj_priv;
593 struct drm_gem_object *obj;
594 ring->dev = dev;
595
596 if (I915_NEED_GFX_HWS(dev)) {
597 ret = init_status_page(dev, ring);
598 if (ret)
599 return ret;
600 }
601
602 obj = i915_gem_alloc_object(dev, ring->size);
603 if (obj == NULL) {
604 DRM_ERROR("Failed to allocate ringbuffer\n");
605 ret = -ENOMEM;
606 goto cleanup;
607 }
608
609 ring->gem_object = obj;
610
611 ret = i915_gem_object_pin(obj, ring->alignment);
612 if (ret != 0) {
613 drm_gem_object_unreference(obj);
614 goto cleanup;
615 }
616
617 obj_priv = to_intel_bo(obj);
618 ring->map.size = ring->size;
619 ring->map.offset = dev->agp->base + obj_priv->gtt_offset;
620 ring->map.type = 0;
621 ring->map.flags = 0;
622 ring->map.mtrr = 0;
623
624 drm_core_ioremap_wc(&ring->map, dev);
625 if (ring->map.handle == NULL) {
626 DRM_ERROR("Failed to map ringbuffer.\n");
627 i915_gem_object_unpin(obj);
628 drm_gem_object_unreference(obj);
629 ret = -EINVAL;
630 goto cleanup;
631 }
632
633 ring->virtual_start = ring->map.handle;
634 ret = ring->init(dev, ring);
635 if (ret != 0) {
636 intel_cleanup_ring_buffer(dev, ring);
637 return ret;
638 }
639
640 if (!drm_core_check_feature(dev, DRIVER_MODESET))
641 i915_kernel_lost_context(dev);
642 else {
643 ring->head = ring->get_head(dev, ring);
644 ring->tail = ring->get_tail(dev, ring);
645 ring->space = ring->head - (ring->tail + 8);
646 if (ring->space < 0)
647 ring->space += ring->size;
648 }
649 INIT_LIST_HEAD(&ring->active_list);
650 INIT_LIST_HEAD(&ring->request_list);
651 return ret;
652cleanup:
653 cleanup_status_page(dev, ring);
654 return ret;
655}
656
657void intel_cleanup_ring_buffer(struct drm_device *dev,
658 struct intel_ring_buffer *ring)
659{
660 if (ring->gem_object == NULL)
661 return;
662
663 drm_core_ioremapfree(&ring->map, dev);
664
665 i915_gem_object_unpin(ring->gem_object);
666 drm_gem_object_unreference(ring->gem_object);
667 ring->gem_object = NULL;
668 cleanup_status_page(dev, ring);
669}
670
671int intel_wrap_ring_buffer(struct drm_device *dev,
672 struct intel_ring_buffer *ring)
673{
674 unsigned int *virt;
675 int rem;
676 rem = ring->size - ring->tail;
677
678 if (ring->space < rem) {
679 int ret = intel_wait_ring_buffer(dev, ring, rem);
680 if (ret)
681 return ret;
682 }
683
684 virt = (unsigned int *)(ring->virtual_start + ring->tail);
685 rem /= 4;
686 while (rem--)
687 *virt++ = MI_NOOP;
688
689 ring->tail = 0;
690
691 return 0;
692}
693
694int intel_wait_ring_buffer(struct drm_device *dev,
695 struct intel_ring_buffer *ring, int n)
696{
697 unsigned long end;
698
699 trace_i915_ring_wait_begin (dev);
700 end = jiffies + 3 * HZ;
701 do {
702 ring->head = ring->get_head(dev, ring);
703 ring->space = ring->head - (ring->tail + 8);
704 if (ring->space < 0)
705 ring->space += ring->size;
706 if (ring->space >= n) {
707 trace_i915_ring_wait_end (dev);
708 return 0;
709 }
710
711 if (dev->primary->master) {
712 struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
713 if (master_priv->sarea_priv)
714 master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
715 }
716
717 yield();
718 } while (!time_after(jiffies, end));
719 trace_i915_ring_wait_end (dev);
720 return -EBUSY;
721}
722
723void intel_ring_begin(struct drm_device *dev,
724 struct intel_ring_buffer *ring, int n)
725{
726 if (unlikely(ring->tail + n > ring->size))
727 intel_wrap_ring_buffer(dev, ring);
728 if (unlikely(ring->space < n))
729 intel_wait_ring_buffer(dev, ring, n);
730}
731
732void intel_ring_emit(struct drm_device *dev,
733 struct intel_ring_buffer *ring, unsigned int data)
734{
735 unsigned int *virt = ring->virtual_start + ring->tail;
736 *virt = data;
737 ring->tail += 4;
738 ring->tail &= ring->size - 1;
739 ring->space -= 4;
740}
741
742void intel_ring_advance(struct drm_device *dev,
743 struct intel_ring_buffer *ring)
744{
745 ring->advance_ring(dev, ring);
746}
747
748void intel_fill_struct(struct drm_device *dev,
749 struct intel_ring_buffer *ring,
750 void *data,
751 unsigned int len)
752{
753 unsigned int *virt = ring->virtual_start + ring->tail;
754 BUG_ON((len&~(4-1)) != 0);
755 intel_ring_begin(dev, ring, len);
756 memcpy(virt, data, len);
757 ring->tail += len;
758 ring->tail &= ring->size - 1;
759 ring->space -= len;
760 intel_ring_advance(dev, ring);
761}
762
763u32 intel_ring_get_seqno(struct drm_device *dev,
764 struct intel_ring_buffer *ring)
765{
766 u32 seqno;
767 seqno = ring->next_seqno;
768
769 /* reserve 0 for non-seqno */
770 if (++ring->next_seqno == 0)
771 ring->next_seqno = 1;
772 return seqno;
773}
774
775struct intel_ring_buffer render_ring = {
776 .name = "render ring",
777 .regs = {
778 .ctl = PRB0_CTL,
779 .head = PRB0_HEAD,
780 .tail = PRB0_TAIL,
781 .start = PRB0_START
782 },
783 .ring_flag = I915_EXEC_RENDER,
784 .size = 32 * PAGE_SIZE,
785 .alignment = PAGE_SIZE,
786 .virtual_start = NULL,
787 .dev = NULL,
788 .gem_object = NULL,
789 .head = 0,
790 .tail = 0,
791 .space = 0,
792 .next_seqno = 1,
793 .user_irq_refcount = 0,
794 .irq_gem_seqno = 0,
795 .waiting_gem_seqno = 0,
796 .setup_status_page = render_setup_status_page,
797 .init = init_render_ring,
798 .get_head = render_ring_get_head,
799 .get_tail = render_ring_get_tail,
800 .get_active_head = render_ring_get_active_head,
801 .advance_ring = render_ring_advance_ring,
802 .flush = render_ring_flush,
803 .add_request = render_ring_add_request,
804 .get_gem_seqno = render_ring_get_gem_seqno,
805 .user_irq_get = render_ring_get_user_irq,
806 .user_irq_put = render_ring_put_user_irq,
807 .dispatch_gem_execbuffer = render_ring_dispatch_gem_execbuffer,
808 .status_page = {NULL, 0, NULL},
809 .map = {0,}
810};
811
812/* ring buffer for bit-stream decoder */
813
814struct intel_ring_buffer bsd_ring = {
815 .name = "bsd ring",
816 .regs = {
817 .ctl = BSD_RING_CTL,
818 .head = BSD_RING_HEAD,
819 .tail = BSD_RING_TAIL,
820 .start = BSD_RING_START
821 },
822 .ring_flag = I915_EXEC_BSD,
823 .size = 32 * PAGE_SIZE,
824 .alignment = PAGE_SIZE,
825 .virtual_start = NULL,
826 .dev = NULL,
827 .gem_object = NULL,
828 .head = 0,
829 .tail = 0,
830 .space = 0,
831 .next_seqno = 1,
832 .user_irq_refcount = 0,
833 .irq_gem_seqno = 0,
834 .waiting_gem_seqno = 0,
835 .setup_status_page = bsd_setup_status_page,
836 .init = init_bsd_ring,
837 .get_head = bsd_ring_get_head,
838 .get_tail = bsd_ring_get_tail,
839 .get_active_head = bsd_ring_get_active_head,
840 .advance_ring = bsd_ring_advance_ring,
841 .flush = bsd_ring_flush,
842 .add_request = bsd_ring_add_request,
843 .get_gem_seqno = bsd_ring_get_gem_seqno,
844 .user_irq_get = bsd_ring_get_user_irq,
845 .user_irq_put = bsd_ring_put_user_irq,
846 .dispatch_gem_execbuffer = bsd_ring_dispatch_gem_execbuffer,
847 .status_page = {NULL, 0, NULL},
848 .map = {0,}
849};
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
new file mode 100644
index 000000000000..d5568d3766de
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -0,0 +1,124 @@
1#ifndef _INTEL_RINGBUFFER_H_
2#define _INTEL_RINGBUFFER_H_
3
4struct intel_hw_status_page {
5 void *page_addr;
6 unsigned int gfx_addr;
7 struct drm_gem_object *obj;
8};
9
10struct drm_i915_gem_execbuffer2;
11struct intel_ring_buffer {
12 const char *name;
13 struct ring_regs {
14 u32 ctl;
15 u32 head;
16 u32 tail;
17 u32 start;
18 } regs;
19 unsigned int ring_flag;
20 unsigned long size;
21 unsigned int alignment;
22 void *virtual_start;
23 struct drm_device *dev;
24 struct drm_gem_object *gem_object;
25
26 unsigned int head;
27 unsigned int tail;
28 unsigned int space;
29 u32 next_seqno;
30 struct intel_hw_status_page status_page;
31
32 u32 irq_gem_seqno; /* last seq seem at irq time */
33 u32 waiting_gem_seqno;
34 int user_irq_refcount;
35 void (*user_irq_get)(struct drm_device *dev,
36 struct intel_ring_buffer *ring);
37 void (*user_irq_put)(struct drm_device *dev,
38 struct intel_ring_buffer *ring);
39 void (*setup_status_page)(struct drm_device *dev,
40 struct intel_ring_buffer *ring);
41
42 int (*init)(struct drm_device *dev,
43 struct intel_ring_buffer *ring);
44
45 unsigned int (*get_head)(struct drm_device *dev,
46 struct intel_ring_buffer *ring);
47 unsigned int (*get_tail)(struct drm_device *dev,
48 struct intel_ring_buffer *ring);
49 unsigned int (*get_active_head)(struct drm_device *dev,
50 struct intel_ring_buffer *ring);
51 void (*advance_ring)(struct drm_device *dev,
52 struct intel_ring_buffer *ring);
53 void (*flush)(struct drm_device *dev,
54 struct intel_ring_buffer *ring,
55 u32 invalidate_domains,
56 u32 flush_domains);
57 u32 (*add_request)(struct drm_device *dev,
58 struct intel_ring_buffer *ring,
59 struct drm_file *file_priv,
60 u32 flush_domains);
61 u32 (*get_gem_seqno)(struct drm_device *dev,
62 struct intel_ring_buffer *ring);
63 int (*dispatch_gem_execbuffer)(struct drm_device *dev,
64 struct intel_ring_buffer *ring,
65 struct drm_i915_gem_execbuffer2 *exec,
66 struct drm_clip_rect *cliprects,
67 uint64_t exec_offset);
68
69 /**
70 * List of objects currently involved in rendering from the
71 * ringbuffer.
72 *
73 * Includes buffers having the contents of their GPU caches
74 * flushed, not necessarily primitives. last_rendering_seqno
75 * represents when the rendering involved will be completed.
76 *
77 * A reference is held on the buffer while on this list.
78 */
79 struct list_head active_list;
80
81 /**
82 * List of breadcrumbs associated with GPU requests currently
83 * outstanding.
84 */
85 struct list_head request_list;
86
87 wait_queue_head_t irq_queue;
88 drm_local_map_t map;
89};
90
91static inline u32
92intel_read_status_page(struct intel_ring_buffer *ring,
93 int reg)
94{
95 u32 *regs = ring->status_page.page_addr;
96 return regs[reg];
97}
98
99int intel_init_ring_buffer(struct drm_device *dev,
100 struct intel_ring_buffer *ring);
101void intel_cleanup_ring_buffer(struct drm_device *dev,
102 struct intel_ring_buffer *ring);
103int intel_wait_ring_buffer(struct drm_device *dev,
104 struct intel_ring_buffer *ring, int n);
105int intel_wrap_ring_buffer(struct drm_device *dev,
106 struct intel_ring_buffer *ring);
107void intel_ring_begin(struct drm_device *dev,
108 struct intel_ring_buffer *ring, int n);
109void intel_ring_emit(struct drm_device *dev,
110 struct intel_ring_buffer *ring, u32 data);
111void intel_fill_struct(struct drm_device *dev,
112 struct intel_ring_buffer *ring,
113 void *data,
114 unsigned int len);
115void intel_ring_advance(struct drm_device *dev,
116 struct intel_ring_buffer *ring);
117
118u32 intel_ring_get_seqno(struct drm_device *dev,
119 struct intel_ring_buffer *ring);
120
121extern struct intel_ring_buffer render_ring;
122extern struct intel_ring_buffer bsd_ring;
123
124#endif /* _INTEL_RINGBUFFER_H_ */
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index aba72c489a2f..76993ac16cc1 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -1479,7 +1479,7 @@ intel_find_analog_connector(struct drm_device *dev)
1479 intel_encoder = enc_to_intel_encoder(encoder); 1479 intel_encoder = enc_to_intel_encoder(encoder);
1480 if (intel_encoder->type == INTEL_OUTPUT_ANALOG) { 1480 if (intel_encoder->type == INTEL_OUTPUT_ANALOG) {
1481 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 1481 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
1482 if (connector && encoder == intel_attached_encoder(connector)) 1482 if (encoder == intel_attached_encoder(connector))
1483 return connector; 1483 return connector;
1484 } 1484 }
1485 } 1485 }
diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c
index e13f6af0037a..d4bcca8a5133 100644
--- a/drivers/gpu/drm/nouveau/nouveau_acpi.c
+++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c
@@ -34,7 +34,7 @@
34static struct nouveau_dsm_priv { 34static struct nouveau_dsm_priv {
35 bool dsm_detected; 35 bool dsm_detected;
36 acpi_handle dhandle; 36 acpi_handle dhandle;
37 acpi_handle dsm_handle; 37 acpi_handle rom_handle;
38} nouveau_dsm_priv; 38} nouveau_dsm_priv;
39 39
40static const char nouveau_dsm_muid[] = { 40static const char nouveau_dsm_muid[] = {
@@ -107,9 +107,9 @@ static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switchero
107static int nouveau_dsm_switchto(enum vga_switcheroo_client_id id) 107static int nouveau_dsm_switchto(enum vga_switcheroo_client_id id)
108{ 108{
109 if (id == VGA_SWITCHEROO_IGD) 109 if (id == VGA_SWITCHEROO_IGD)
110 return nouveau_dsm_switch_mux(nouveau_dsm_priv.dsm_handle, NOUVEAU_DSM_LED_STAMINA); 110 return nouveau_dsm_switch_mux(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_LED_STAMINA);
111 else 111 else
112 return nouveau_dsm_switch_mux(nouveau_dsm_priv.dsm_handle, NOUVEAU_DSM_LED_SPEED); 112 return nouveau_dsm_switch_mux(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_LED_SPEED);
113} 113}
114 114
115static int nouveau_dsm_power_state(enum vga_switcheroo_client_id id, 115static 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,
118 if (id == VGA_SWITCHEROO_IGD) 118 if (id == VGA_SWITCHEROO_IGD)
119 return 0; 119 return 0;
120 120
121 return nouveau_dsm_set_discrete_state(nouveau_dsm_priv.dsm_handle, state); 121 return nouveau_dsm_set_discrete_state(nouveau_dsm_priv.dhandle, state);
122} 122}
123 123
124static int nouveau_dsm_init(void) 124static int nouveau_dsm_init(void)
@@ -151,18 +151,18 @@ static bool nouveau_dsm_pci_probe(struct pci_dev *pdev)
151 dhandle = DEVICE_ACPI_HANDLE(&pdev->dev); 151 dhandle = DEVICE_ACPI_HANDLE(&pdev->dev);
152 if (!dhandle) 152 if (!dhandle)
153 return false; 153 return false;
154
154 status = acpi_get_handle(dhandle, "_DSM", &nvidia_handle); 155 status = acpi_get_handle(dhandle, "_DSM", &nvidia_handle);
155 if (ACPI_FAILURE(status)) { 156 if (ACPI_FAILURE(status)) {
156 return false; 157 return false;
157 } 158 }
158 159
159 ret= nouveau_dsm(nvidia_handle, NOUVEAU_DSM_SUPPORTED, 160 ret = nouveau_dsm(dhandle, NOUVEAU_DSM_SUPPORTED,
160 NOUVEAU_DSM_SUPPORTED_FUNCTIONS, &result); 161 NOUVEAU_DSM_SUPPORTED_FUNCTIONS, &result);
161 if (ret < 0) 162 if (ret < 0)
162 return false; 163 return false;
163 164
164 nouveau_dsm_priv.dhandle = dhandle; 165 nouveau_dsm_priv.dhandle = dhandle;
165 nouveau_dsm_priv.dsm_handle = nvidia_handle;
166 return true; 166 return true;
167} 167}
168 168
@@ -173,6 +173,7 @@ static bool nouveau_dsm_detect(void)
173 struct pci_dev *pdev = NULL; 173 struct pci_dev *pdev = NULL;
174 int has_dsm = 0; 174 int has_dsm = 0;
175 int vga_count = 0; 175 int vga_count = 0;
176
176 while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) { 177 while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
177 vga_count++; 178 vga_count++;
178 179
@@ -180,7 +181,7 @@ static bool nouveau_dsm_detect(void)
180 } 181 }
181 182
182 if (vga_count == 2 && has_dsm) { 183 if (vga_count == 2 && has_dsm) {
183 acpi_get_name(nouveau_dsm_priv.dsm_handle, ACPI_FULL_PATHNAME, &buffer); 184 acpi_get_name(nouveau_dsm_priv.dhandle, ACPI_FULL_PATHNAME, &buffer);
184 printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n", 185 printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n",
185 acpi_method_name); 186 acpi_method_name);
186 nouveau_dsm_priv.dsm_detected = true; 187 nouveau_dsm_priv.dsm_detected = true;
@@ -204,3 +205,57 @@ void nouveau_unregister_dsm_handler(void)
204{ 205{
205 vga_switcheroo_unregister_handler(); 206 vga_switcheroo_unregister_handler();
206} 207}
208
209/* retrieve the ROM in 4k blocks */
210static int nouveau_rom_call(acpi_handle rom_handle, uint8_t *bios,
211 int offset, int len)
212{
213 acpi_status status;
214 union acpi_object rom_arg_elements[2], *obj;
215 struct acpi_object_list rom_arg;
216 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL};
217
218 rom_arg.count = 2;
219 rom_arg.pointer = &rom_arg_elements[0];
220
221 rom_arg_elements[0].type = ACPI_TYPE_INTEGER;
222 rom_arg_elements[0].integer.value = offset;
223
224 rom_arg_elements[1].type = ACPI_TYPE_INTEGER;
225 rom_arg_elements[1].integer.value = len;
226
227 status = acpi_evaluate_object(rom_handle, NULL, &rom_arg, &buffer);
228 if (ACPI_FAILURE(status)) {
229 printk(KERN_INFO "failed to evaluate ROM got %s\n", acpi_format_exception(status));
230 return -ENODEV;
231 }
232 obj = (union acpi_object *)buffer.pointer;
233 memcpy(bios+offset, obj->buffer.pointer, len);
234 kfree(buffer.pointer);
235 return len;
236}
237
238bool nouveau_acpi_rom_supported(struct pci_dev *pdev)
239{
240 acpi_status status;
241 acpi_handle dhandle, rom_handle;
242
243 if (!nouveau_dsm_priv.dsm_detected)
244 return false;
245
246 dhandle = DEVICE_ACPI_HANDLE(&pdev->dev);
247 if (!dhandle)
248 return false;
249
250 status = acpi_get_handle(dhandle, "_ROM", &rom_handle);
251 if (ACPI_FAILURE(status))
252 return false;
253
254 nouveau_dsm_priv.rom_handle = rom_handle;
255 return true;
256}
257
258int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len)
259{
260 return nouveau_rom_call(nouveau_dsm_priv.rom_handle, bios, offset, len);
261}
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
index e7e69ccce5c9..fc924b649195 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
@@ -178,6 +178,25 @@ out:
178 pci_disable_rom(dev->pdev); 178 pci_disable_rom(dev->pdev);
179} 179}
180 180
181static void load_vbios_acpi(struct drm_device *dev, uint8_t *data)
182{
183 int i;
184 int ret;
185 int size = 64 * 1024;
186
187 if (!nouveau_acpi_rom_supported(dev->pdev))
188 return;
189
190 for (i = 0; i < (size / ROM_BIOS_PAGE); i++) {
191 ret = nouveau_acpi_get_bios_chunk(data,
192 (i * ROM_BIOS_PAGE),
193 ROM_BIOS_PAGE);
194 if (ret <= 0)
195 break;
196 }
197 return;
198}
199
181struct methods { 200struct methods {
182 const char desc[8]; 201 const char desc[8];
183 void (*loadbios)(struct drm_device *, uint8_t *); 202 void (*loadbios)(struct drm_device *, uint8_t *);
@@ -191,6 +210,7 @@ static struct methods nv04_methods[] = {
191}; 210};
192 211
193static struct methods nv50_methods[] = { 212static struct methods nv50_methods[] = {
213 { "ACPI", load_vbios_acpi, true },
194 { "PRAMIN", load_vbios_pramin, true }, 214 { "PRAMIN", load_vbios_pramin, true },
195 { "PROM", load_vbios_prom, false }, 215 { "PROM", load_vbios_prom, false },
196 { "PCIROM", load_vbios_pci, true }, 216 { "PCIROM", load_vbios_pci, true },
@@ -814,7 +834,7 @@ init_i2c_device_find(struct drm_device *dev, int i2c_index)
814 if (i2c_index == 0x81) 834 if (i2c_index == 0x81)
815 i2c_index = (dcb->i2c_default_indices & 0xf0) >> 4; 835 i2c_index = (dcb->i2c_default_indices & 0xf0) >> 4;
816 836
817 if (i2c_index > DCB_MAX_NUM_I2C_ENTRIES) { 837 if (i2c_index >= DCB_MAX_NUM_I2C_ENTRIES) {
818 NV_ERROR(dev, "invalid i2c_index 0x%x\n", i2c_index); 838 NV_ERROR(dev, "invalid i2c_index 0x%x\n", i2c_index);
819 return NULL; 839 return NULL;
820 } 840 }
@@ -2807,7 +2827,10 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
2807 2827
2808 BIOSLOG(bios, "0x%04X: Entry: 0x%08X\n", offset, gpio->entry); 2828 BIOSLOG(bios, "0x%04X: Entry: 0x%08X\n", offset, gpio->entry);
2809 2829
2810 nv50_gpio_set(bios->dev, gpio->tag, gpio->state_default); 2830 BIOSLOG(bios, "0x%04X: set gpio 0x%02x, state %d\n",
2831 offset, gpio->tag, gpio->state_default);
2832 if (bios->execute)
2833 nv50_gpio_set(bios->dev, gpio->tag, gpio->state_default);
2811 2834
2812 /* The NVIDIA binary driver doesn't appear to actually do 2835 /* The NVIDIA binary driver doesn't appear to actually do
2813 * any of this, my VBIOS does however. 2836 * 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
3897 3920
3898static uint8_t * 3921static uint8_t *
3899bios_output_config_match(struct drm_device *dev, struct dcb_entry *dcbent, 3922bios_output_config_match(struct drm_device *dev, struct dcb_entry *dcbent,
3900 uint16_t record, int record_len, int record_nr) 3923 uint16_t record, int record_len, int record_nr,
3924 bool match_link)
3901{ 3925{
3902 struct drm_nouveau_private *dev_priv = dev->dev_private; 3926 struct drm_nouveau_private *dev_priv = dev->dev_private;
3903 struct nvbios *bios = &dev_priv->vbios; 3927 struct nvbios *bios = &dev_priv->vbios;
@@ -3905,12 +3929,28 @@ bios_output_config_match(struct drm_device *dev, struct dcb_entry *dcbent,
3905 uint16_t table; 3929 uint16_t table;
3906 int i, v; 3930 int i, v;
3907 3931
3932 switch (dcbent->type) {
3933 case OUTPUT_TMDS:
3934 case OUTPUT_LVDS:
3935 case OUTPUT_DP:
3936 break;
3937 default:
3938 match_link = false;
3939 break;
3940 }
3941
3908 for (i = 0; i < record_nr; i++, record += record_len) { 3942 for (i = 0; i < record_nr; i++, record += record_len) {
3909 table = ROM16(bios->data[record]); 3943 table = ROM16(bios->data[record]);
3910 if (!table) 3944 if (!table)
3911 continue; 3945 continue;
3912 entry = ROM32(bios->data[table]); 3946 entry = ROM32(bios->data[table]);
3913 3947
3948 if (match_link) {
3949 v = (entry & 0x00c00000) >> 22;
3950 if (!(v & dcbent->sorconf.link))
3951 continue;
3952 }
3953
3914 v = (entry & 0x000f0000) >> 16; 3954 v = (entry & 0x000f0000) >> 16;
3915 if (!(v & dcbent->or)) 3955 if (!(v & dcbent->or))
3916 continue; 3956 continue;
@@ -3952,7 +3992,7 @@ nouveau_bios_dp_table(struct drm_device *dev, struct dcb_entry *dcbent,
3952 *length = table[4]; 3992 *length = table[4];
3953 return bios_output_config_match(dev, dcbent, 3993 return bios_output_config_match(dev, dcbent,
3954 bios->display.dp_table_ptr + table[1], 3994 bios->display.dp_table_ptr + table[1],
3955 table[2], table[3]); 3995 table[2], table[3], table[0] >= 0x21);
3956} 3996}
3957 3997
3958int 3998int
@@ -4041,7 +4081,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
4041 dcbent->type, dcbent->location, dcbent->or); 4081 dcbent->type, dcbent->location, dcbent->or);
4042 otable = bios_output_config_match(dev, dcbent, table[1] + 4082 otable = bios_output_config_match(dev, dcbent, table[1] +
4043 bios->display.script_table_ptr, 4083 bios->display.script_table_ptr,
4044 table[2], table[3]); 4084 table[2], table[3], table[0] >= 0x21);
4045 if (!otable) { 4085 if (!otable) {
4046 NV_ERROR(dev, "Couldn't find matching output script table\n"); 4086 NV_ERROR(dev, "Couldn't find matching output script table\n");
4047 return 1; 4087 return 1;
@@ -5533,12 +5573,6 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
5533 entry->bus = (conn >> 16) & 0xf; 5573 entry->bus = (conn >> 16) & 0xf;
5534 entry->location = (conn >> 20) & 0x3; 5574 entry->location = (conn >> 20) & 0x3;
5535 entry->or = (conn >> 24) & 0xf; 5575 entry->or = (conn >> 24) & 0xf;
5536 /*
5537 * Normal entries consist of a single bit, but dual link has the
5538 * next most significant bit set too
5539 */
5540 entry->duallink_possible =
5541 ((1 << (ffs(entry->or) - 1)) * 3 == entry->or);
5542 5576
5543 switch (entry->type) { 5577 switch (entry->type) {
5544 case OUTPUT_ANALOG: 5578 case OUTPUT_ANALOG:
@@ -5622,6 +5656,16 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
5622 break; 5656 break;
5623 } 5657 }
5624 5658
5659 if (dcb->version < 0x40) {
5660 /* Normal entries consist of a single bit, but dual link has
5661 * the next most significant bit set too
5662 */
5663 entry->duallink_possible =
5664 ((1 << (ffs(entry->or) - 1)) * 3 == entry->or);
5665 } else {
5666 entry->duallink_possible = (entry->sorconf.link == 3);
5667 }
5668
5625 /* unsure what DCB version introduces this, 3.0? */ 5669 /* unsure what DCB version introduces this, 3.0? */
5626 if (conf & 0x100000) 5670 if (conf & 0x100000)
5627 entry->i2c_upper_default = true; 5671 entry->i2c_upper_default = true;
@@ -6205,6 +6249,30 @@ nouveau_bios_i2c_devices_takedown(struct drm_device *dev)
6205 nouveau_i2c_fini(dev, entry); 6249 nouveau_i2c_fini(dev, entry);
6206} 6250}
6207 6251
6252static bool
6253nouveau_bios_posted(struct drm_device *dev)
6254{
6255 struct drm_nouveau_private *dev_priv = dev->dev_private;
6256 bool was_locked;
6257 unsigned htotal;
6258
6259 if (dev_priv->chipset >= NV_50) {
6260 if (NVReadVgaCrtc(dev, 0, 0x00) == 0 &&
6261 NVReadVgaCrtc(dev, 0, 0x1a) == 0)
6262 return false;
6263 return true;
6264 }
6265
6266 was_locked = NVLockVgaCrtcs(dev, false);
6267 htotal = NVReadVgaCrtc(dev, 0, 0x06);
6268 htotal |= (NVReadVgaCrtc(dev, 0, 0x07) & 0x01) << 8;
6269 htotal |= (NVReadVgaCrtc(dev, 0, 0x07) & 0x20) << 4;
6270 htotal |= (NVReadVgaCrtc(dev, 0, 0x25) & 0x01) << 10;
6271 htotal |= (NVReadVgaCrtc(dev, 0, 0x41) & 0x01) << 11;
6272 NVLockVgaCrtcs(dev, was_locked);
6273 return (htotal != 0);
6274}
6275
6208int 6276int
6209nouveau_bios_init(struct drm_device *dev) 6277nouveau_bios_init(struct drm_device *dev)
6210{ 6278{
@@ -6239,11 +6307,9 @@ nouveau_bios_init(struct drm_device *dev)
6239 bios->execute = false; 6307 bios->execute = false;
6240 6308
6241 /* ... unless card isn't POSTed already */ 6309 /* ... unless card isn't POSTed already */
6242 if (dev_priv->card_type >= NV_10 && 6310 if (!nouveau_bios_posted(dev)) {
6243 NVReadVgaCrtc(dev, 0, 0x00) == 0 &&
6244 NVReadVgaCrtc(dev, 0, 0x1a) == 0) {
6245 NV_INFO(dev, "Adaptor not initialised\n"); 6311 NV_INFO(dev, "Adaptor not initialised\n");
6246 if (dev_priv->card_type < NV_50) { 6312 if (dev_priv->card_type < NV_40) {
6247 NV_ERROR(dev, "Unable to POST this chipset\n"); 6313 NV_ERROR(dev, "Unable to POST this chipset\n");
6248 return -ENODEV; 6314 return -ENODEV;
6249 } 6315 }
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 7e663a79829f..149ed224c3cb 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -241,7 +241,8 @@ nouveau_connector_detect(struct drm_connector *connector)
241 if (nv_encoder && nv_connector->native_mode) { 241 if (nv_encoder && nv_connector->native_mode) {
242 unsigned status = connector_status_connected; 242 unsigned status = connector_status_connected;
243 243
244#ifdef CONFIG_ACPI 244#if defined(CONFIG_ACPI_BUTTON) || \
245 (defined(CONFIG_ACPI_BUTTON_MODULE) && defined(MODULE))
245 if (!nouveau_ignorelid && !acpi_lid_open()) 246 if (!nouveau_ignorelid && !acpi_lid_open())
246 status = connector_status_unknown; 247 status = connector_status_unknown;
247#endif 248#endif
@@ -431,24 +432,27 @@ nouveau_connector_set_property(struct drm_connector *connector,
431} 432}
432 433
433static struct drm_display_mode * 434static struct drm_display_mode *
434nouveau_connector_native_mode(struct nouveau_connector *connector) 435nouveau_connector_native_mode(struct drm_connector *connector)
435{ 436{
436 struct drm_device *dev = connector->base.dev; 437 struct drm_connector_helper_funcs *helper = connector->helper_private;
438 struct nouveau_connector *nv_connector = nouveau_connector(connector);
439 struct drm_device *dev = connector->dev;
437 struct drm_display_mode *mode, *largest = NULL; 440 struct drm_display_mode *mode, *largest = NULL;
438 int high_w = 0, high_h = 0, high_v = 0; 441 int high_w = 0, high_h = 0, high_v = 0;
439 442
440 /* Use preferred mode if there is one.. */ 443 list_for_each_entry(mode, &nv_connector->base.probed_modes, head) {
441 list_for_each_entry(mode, &connector->base.probed_modes, head) { 444 if (helper->mode_valid(connector, mode) != MODE_OK)
445 continue;
446
447 /* Use preferred mode if there is one.. */
442 if (mode->type & DRM_MODE_TYPE_PREFERRED) { 448 if (mode->type & DRM_MODE_TYPE_PREFERRED) {
443 NV_DEBUG_KMS(dev, "native mode from preferred\n"); 449 NV_DEBUG_KMS(dev, "native mode from preferred\n");
444 return drm_mode_duplicate(dev, mode); 450 return drm_mode_duplicate(dev, mode);
445 } 451 }
446 }
447 452
448 /* Otherwise, take the resolution with the largest width, then height, 453 /* Otherwise, take the resolution with the largest width, then
449 * then vertical refresh 454 * height, then vertical refresh
450 */ 455 */
451 list_for_each_entry(mode, &connector->base.probed_modes, head) {
452 if (mode->hdisplay < high_w) 456 if (mode->hdisplay < high_w)
453 continue; 457 continue;
454 458
@@ -552,7 +556,7 @@ nouveau_connector_get_modes(struct drm_connector *connector)
552 */ 556 */
553 if (!nv_connector->native_mode) 557 if (!nv_connector->native_mode)
554 nv_connector->native_mode = 558 nv_connector->native_mode =
555 nouveau_connector_native_mode(nv_connector); 559 nouveau_connector_native_mode(connector);
556 if (ret == 0 && nv_connector->native_mode) { 560 if (ret == 0 && nv_connector->native_mode) {
557 struct drm_display_mode *mode; 561 struct drm_display_mode *mode;
558 562
@@ -583,9 +587,9 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
583 587
584 switch (nv_encoder->dcb->type) { 588 switch (nv_encoder->dcb->type) {
585 case OUTPUT_LVDS: 589 case OUTPUT_LVDS:
586 BUG_ON(!nv_connector->native_mode); 590 if (nv_connector->native_mode &&
587 if (mode->hdisplay > nv_connector->native_mode->hdisplay || 591 (mode->hdisplay > nv_connector->native_mode->hdisplay ||
588 mode->vdisplay > nv_connector->native_mode->vdisplay) 592 mode->vdisplay > nv_connector->native_mode->vdisplay))
589 return MODE_PANEL; 593 return MODE_PANEL;
590 594
591 min_clock = 0; 595 min_clock = 0;
@@ -593,8 +597,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
593 break; 597 break;
594 case OUTPUT_TMDS: 598 case OUTPUT_TMDS:
595 if ((dev_priv->card_type >= NV_50 && !nouveau_duallink) || 599 if ((dev_priv->card_type >= NV_50 && !nouveau_duallink) ||
596 (dev_priv->card_type < NV_50 && 600 !nv_encoder->dcb->duallink_possible)
597 !nv_encoder->dcb->duallink_possible))
598 max_clock = 165000; 601 max_clock = 165000;
599 else 602 else
600 max_clock = 330000; 603 max_clock = 330000;
@@ -728,7 +731,7 @@ nouveau_connector_create_lvds(struct drm_device *dev,
728 if (ret == 0) 731 if (ret == 0)
729 goto out; 732 goto out;
730 nv_connector->detected_encoder = nv_encoder; 733 nv_connector->detected_encoder = nv_encoder;
731 nv_connector->native_mode = nouveau_connector_native_mode(nv_connector); 734 nv_connector->native_mode = nouveau_connector_native_mode(connector);
732 list_for_each_entry_safe(mode, temp, &connector->probed_modes, head) 735 list_for_each_entry_safe(mode, temp, &connector->probed_modes, head)
733 drm_mode_remove(connector, mode); 736 drm_mode_remove(connector, mode);
734 737
diff --git a/drivers/gpu/drm/nouveau/nouveau_crtc.h b/drivers/gpu/drm/nouveau/nouveau_crtc.h
index 49fa7b2d257e..cb1ce2a09162 100644
--- a/drivers/gpu/drm/nouveau/nouveau_crtc.h
+++ b/drivers/gpu/drm/nouveau/nouveau_crtc.h
@@ -40,6 +40,8 @@ struct nouveau_crtc {
40 int sharpness; 40 int sharpness;
41 int last_dpms; 41 int last_dpms;
42 42
43 int cursor_saved_x, cursor_saved_y;
44
43 struct { 45 struct {
44 int cpp; 46 int cpp;
45 bool blanked; 47 bool blanked;
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c
index c6079e36669d..273770432298 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.c
@@ -175,6 +175,13 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state)
175 nouveau_bo_unpin(nouveau_fb->nvbo); 175 nouveau_bo_unpin(nouveau_fb->nvbo);
176 } 176 }
177 177
178 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
179 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
180
181 nouveau_bo_unmap(nv_crtc->cursor.nvbo);
182 nouveau_bo_unpin(nv_crtc->cursor.nvbo);
183 }
184
178 NV_INFO(dev, "Evicting buffers...\n"); 185 NV_INFO(dev, "Evicting buffers...\n");
179 ttm_bo_evict_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM); 186 ttm_bo_evict_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM);
180 187
@@ -314,12 +321,34 @@ nouveau_pci_resume(struct pci_dev *pdev)
314 nouveau_bo_pin(nouveau_fb->nvbo, TTM_PL_FLAG_VRAM); 321 nouveau_bo_pin(nouveau_fb->nvbo, TTM_PL_FLAG_VRAM);
315 } 322 }
316 323
324 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
325 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
326 int ret;
327
328 ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
329 if (!ret)
330 ret = nouveau_bo_map(nv_crtc->cursor.nvbo);
331 if (ret)
332 NV_ERROR(dev, "Could not pin/map cursor.\n");
333 }
334
317 if (dev_priv->card_type < NV_50) { 335 if (dev_priv->card_type < NV_50) {
318 nv04_display_restore(dev); 336 nv04_display_restore(dev);
319 NVLockVgaCrtcs(dev, false); 337 NVLockVgaCrtcs(dev, false);
320 } else 338 } else
321 nv50_display_init(dev); 339 nv50_display_init(dev);
322 340
341 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
342 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
343
344 nv_crtc->cursor.set_offset(nv_crtc,
345 nv_crtc->cursor.nvbo->bo.offset -
346 dev_priv->vm_vram_base);
347
348 nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x,
349 nv_crtc->cursor_saved_y);
350 }
351
323 /* Force CLUT to get re-loaded during modeset */ 352 /* Force CLUT to get re-loaded during modeset */
324 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 353 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
325 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); 354 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index 5b134438effe..c69719106489 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -851,12 +851,17 @@ extern int nouveau_dma_init(struct nouveau_channel *);
851extern int nouveau_dma_wait(struct nouveau_channel *, int slots, int size); 851extern int nouveau_dma_wait(struct nouveau_channel *, int slots, int size);
852 852
853/* nouveau_acpi.c */ 853/* nouveau_acpi.c */
854#define ROM_BIOS_PAGE 4096
854#if defined(CONFIG_ACPI) 855#if defined(CONFIG_ACPI)
855void nouveau_register_dsm_handler(void); 856void nouveau_register_dsm_handler(void);
856void nouveau_unregister_dsm_handler(void); 857void nouveau_unregister_dsm_handler(void);
858int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len);
859bool nouveau_acpi_rom_supported(struct pci_dev *pdev);
857#else 860#else
858static inline void nouveau_register_dsm_handler(void) {} 861static inline void nouveau_register_dsm_handler(void) {}
859static inline void nouveau_unregister_dsm_handler(void) {} 862static inline void nouveau_unregister_dsm_handler(void) {}
863static inline bool nouveau_acpi_rom_supported(struct pci_dev *pdev) { return false; }
864static inline int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len) { return -EINVAL; }
860#endif 865#endif
861 866
862/* nouveau_backlight.c */ 867/* nouveau_backlight.c */
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
index fd4a2df715e9..c9a4a0d2a115 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
@@ -377,6 +377,7 @@ int nouveau_fbcon_init(struct drm_device *dev)
377{ 377{
378 struct drm_nouveau_private *dev_priv = dev->dev_private; 378 struct drm_nouveau_private *dev_priv = dev->dev_private;
379 struct nouveau_fbdev *nfbdev; 379 struct nouveau_fbdev *nfbdev;
380 int ret;
380 381
381 nfbdev = kzalloc(sizeof(struct nouveau_fbdev), GFP_KERNEL); 382 nfbdev = kzalloc(sizeof(struct nouveau_fbdev), GFP_KERNEL);
382 if (!nfbdev) 383 if (!nfbdev)
@@ -386,7 +387,12 @@ int nouveau_fbcon_init(struct drm_device *dev)
386 dev_priv->nfbdev = nfbdev; 387 dev_priv->nfbdev = nfbdev;
387 nfbdev->helper.funcs = &nouveau_fbcon_helper_funcs; 388 nfbdev->helper.funcs = &nouveau_fbcon_helper_funcs;
388 389
389 drm_fb_helper_init(dev, &nfbdev->helper, 2, 4); 390 ret = drm_fb_helper_init(dev, &nfbdev->helper, 2, 4);
391 if (ret) {
392 kfree(nfbdev);
393 return ret;
394 }
395
390 drm_fb_helper_single_add_all_connectors(&nfbdev->helper); 396 drm_fb_helper_single_add_all_connectors(&nfbdev->helper);
391 drm_fb_helper_initial_config(&nfbdev->helper, 32); 397 drm_fb_helper_initial_config(&nfbdev->helper, 32);
392 return 0; 398 return 0;
diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c
index 775a7017af64..c1fd42b0dad1 100644
--- a/drivers/gpu/drm/nouveau/nouveau_mem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_mem.c
@@ -540,7 +540,8 @@ nouveau_mem_detect(struct drm_device *dev)
540 dev_priv->vram_size = nv_rd32(dev, NV04_FIFO_DATA); 540 dev_priv->vram_size = nv_rd32(dev, NV04_FIFO_DATA);
541 dev_priv->vram_size &= NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK; 541 dev_priv->vram_size &= NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK;
542 if (dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac) 542 if (dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac)
543 dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10) << 12; 543 dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10);
544 dev_priv->vram_sys_base <<= 12;
544 } 545 }
545 546
546 NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20)); 547 NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20));
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
index e632339c323e..b02a231d6937 100644
--- a/drivers/gpu/drm/nouveau/nouveau_state.c
+++ b/drivers/gpu/drm/nouveau/nouveau_state.c
@@ -376,12 +376,15 @@ out_err:
376static void nouveau_switcheroo_set_state(struct pci_dev *pdev, 376static void nouveau_switcheroo_set_state(struct pci_dev *pdev,
377 enum vga_switcheroo_state state) 377 enum vga_switcheroo_state state)
378{ 378{
379 struct drm_device *dev = pci_get_drvdata(pdev);
379 pm_message_t pmm = { .event = PM_EVENT_SUSPEND }; 380 pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
380 if (state == VGA_SWITCHEROO_ON) { 381 if (state == VGA_SWITCHEROO_ON) {
381 printk(KERN_ERR "VGA switcheroo: switched nouveau on\n"); 382 printk(KERN_ERR "VGA switcheroo: switched nouveau on\n");
382 nouveau_pci_resume(pdev); 383 nouveau_pci_resume(pdev);
384 drm_kms_helper_poll_enable(dev);
383 } else { 385 } else {
384 printk(KERN_ERR "VGA switcheroo: switched nouveau off\n"); 386 printk(KERN_ERR "VGA switcheroo: switched nouveau off\n");
387 drm_kms_helper_poll_disable(dev);
385 nouveau_pci_suspend(pdev, pmm); 388 nouveau_pci_suspend(pdev, pmm);
386 } 389 }
387} 390}
@@ -776,29 +779,24 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
776 return ret; 779 return ret;
777 } 780 }
778 781
779 /* map larger RAMIN aperture on NV40 cards */ 782 /* Map PRAMIN BAR, or on older cards, the aperture withing BAR0 */
780 dev_priv->ramin = NULL;
781 if (dev_priv->card_type >= NV_40) { 783 if (dev_priv->card_type >= NV_40) {
782 int ramin_bar = 2; 784 int ramin_bar = 2;
783 if (pci_resource_len(dev->pdev, ramin_bar) == 0) 785 if (pci_resource_len(dev->pdev, ramin_bar) == 0)
784 ramin_bar = 3; 786 ramin_bar = 3;
785 787
786 dev_priv->ramin_size = pci_resource_len(dev->pdev, ramin_bar); 788 dev_priv->ramin_size = pci_resource_len(dev->pdev, ramin_bar);
787 dev_priv->ramin = ioremap( 789 dev_priv->ramin =
788 pci_resource_start(dev->pdev, ramin_bar), 790 ioremap(pci_resource_start(dev->pdev, ramin_bar),
789 dev_priv->ramin_size); 791 dev_priv->ramin_size);
790 if (!dev_priv->ramin) { 792 if (!dev_priv->ramin) {
791 NV_ERROR(dev, "Failed to init RAMIN mapping, " 793 NV_ERROR(dev, "Failed to PRAMIN BAR");
792 "limited instance memory available\n"); 794 return -ENOMEM;
793 } 795 }
794 } 796 } else {
795
796 /* On older cards (or if the above failed), create a map covering
797 * the BAR0 PRAMIN aperture */
798 if (!dev_priv->ramin) {
799 dev_priv->ramin_size = 1 * 1024 * 1024; 797 dev_priv->ramin_size = 1 * 1024 * 1024;
800 dev_priv->ramin = ioremap(mmio_start_offs + NV_RAMIN, 798 dev_priv->ramin = ioremap(mmio_start_offs + NV_RAMIN,
801 dev_priv->ramin_size); 799 dev_priv->ramin_size);
802 if (!dev_priv->ramin) { 800 if (!dev_priv->ramin) {
803 NV_ERROR(dev, "Failed to map BAR0 PRAMIN.\n"); 801 NV_ERROR(dev, "Failed to map BAR0 PRAMIN.\n");
804 return -ENOMEM; 802 return -ENOMEM;
@@ -913,6 +911,9 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data,
913 case NOUVEAU_GETPARAM_VM_VRAM_BASE: 911 case NOUVEAU_GETPARAM_VM_VRAM_BASE:
914 getparam->value = dev_priv->vm_vram_base; 912 getparam->value = dev_priv->vm_vram_base;
915 break; 913 break;
914 case NOUVEAU_GETPARAM_PTIMER_TIME:
915 getparam->value = dev_priv->engine.timer.read(dev);
916 break;
916 case NOUVEAU_GETPARAM_GRAPH_UNITS: 917 case NOUVEAU_GETPARAM_GRAPH_UNITS:
917 /* NV40 and NV50 versions are quite different, but register 918 /* NV40 and NV50 versions are quite different, but register
918 * address is the same. User is supposed to know the card 919 * address is the same. User is supposed to know the card
diff --git a/drivers/gpu/drm/nouveau/nv04_cursor.c b/drivers/gpu/drm/nouveau/nv04_cursor.c
index 89a91b9d8b25..aaf3de3bc816 100644
--- a/drivers/gpu/drm/nouveau/nv04_cursor.c
+++ b/drivers/gpu/drm/nouveau/nv04_cursor.c
@@ -20,6 +20,7 @@ nv04_cursor_hide(struct nouveau_crtc *nv_crtc, bool update)
20static void 20static void
21nv04_cursor_set_pos(struct nouveau_crtc *nv_crtc, int x, int y) 21nv04_cursor_set_pos(struct nouveau_crtc *nv_crtc, int x, int y)
22{ 22{
23 nv_crtc->cursor_saved_x = x; nv_crtc->cursor_saved_y = y;
23 NVWriteRAMDAC(nv_crtc->base.dev, nv_crtc->index, 24 NVWriteRAMDAC(nv_crtc->base.dev, nv_crtc->index,
24 NV_PRAMDAC_CU_START_POS, 25 NV_PRAMDAC_CU_START_POS,
25 XLATE(y, 0, NV_PRAMDAC_CU_START_POS_Y) | 26 XLATE(y, 0, NV_PRAMDAC_CU_START_POS_Y) |
diff --git a/drivers/gpu/drm/nouveau/nv40_graph.c b/drivers/gpu/drm/nouveau/nv40_graph.c
index 0616c96e4b67..704a25d04ac9 100644
--- a/drivers/gpu/drm/nouveau/nv40_graph.c
+++ b/drivers/gpu/drm/nouveau/nv40_graph.c
@@ -253,7 +253,11 @@ nv40_graph_init(struct drm_device *dev)
253 253
254 if (!dev_priv->engine.graph.ctxprog) { 254 if (!dev_priv->engine.graph.ctxprog) {
255 struct nouveau_grctx ctx = {}; 255 struct nouveau_grctx ctx = {};
256 uint32_t cp[256]; 256 uint32_t *cp;
257
258 cp = kmalloc(sizeof(*cp) * 256, GFP_KERNEL);
259 if (!cp)
260 return -ENOMEM;
257 261
258 ctx.dev = dev; 262 ctx.dev = dev;
259 ctx.mode = NOUVEAU_GRCTX_PROG; 263 ctx.mode = NOUVEAU_GRCTX_PROG;
@@ -265,6 +269,8 @@ nv40_graph_init(struct drm_device *dev)
265 nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0); 269 nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0);
266 for (i = 0; i < ctx.ctxprog_len; i++) 270 for (i = 0; i < ctx.ctxprog_len; i++)
267 nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, cp[i]); 271 nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, cp[i]);
272
273 kfree(cp);
268 } 274 }
269 275
270 /* No context present currently */ 276 /* No context present currently */
diff --git a/drivers/gpu/drm/nouveau/nv50_cursor.c b/drivers/gpu/drm/nouveau/nv50_cursor.c
index 753e723adb3a..03ad7ab14f09 100644
--- a/drivers/gpu/drm/nouveau/nv50_cursor.c
+++ b/drivers/gpu/drm/nouveau/nv50_cursor.c
@@ -107,6 +107,7 @@ nv50_cursor_set_pos(struct nouveau_crtc *nv_crtc, int x, int y)
107{ 107{
108 struct drm_device *dev = nv_crtc->base.dev; 108 struct drm_device *dev = nv_crtc->base.dev;
109 109
110 nv_crtc->cursor_saved_x = x; nv_crtc->cursor_saved_y = y;
110 nv_wr32(dev, NV50_PDISPLAY_CURSOR_USER_POS(nv_crtc->index), 111 nv_wr32(dev, NV50_PDISPLAY_CURSOR_USER_POS(nv_crtc->index),
111 ((y & 0xFFFF) << 16) | (x & 0xFFFF)); 112 ((y & 0xFFFF) << 16) | (x & 0xFFFF));
112 /* Needed to make the cursor move. */ 113 /* Needed to make the cursor move. */
diff --git a/drivers/gpu/drm/nouveau/nv50_fb.c b/drivers/gpu/drm/nouveau/nv50_fb.c
index a95e6941ba88..32611bd30e6d 100644
--- a/drivers/gpu/drm/nouveau/nv50_fb.c
+++ b/drivers/gpu/drm/nouveau/nv50_fb.c
@@ -6,10 +6,16 @@
6int 6int
7nv50_fb_init(struct drm_device *dev) 7nv50_fb_init(struct drm_device *dev)
8{ 8{
9 /* This is needed to get meaningful information from 100c90
10 * on traps. No idea what these values mean exactly. */
11 struct drm_nouveau_private *dev_priv = dev->dev_private; 9 struct drm_nouveau_private *dev_priv = dev->dev_private;
12 10
11 /* Not a clue what this is exactly. Without pointing it at a
12 * scratch page, VRAM->GART blits with M2MF (as in DDX DFS)
13 * cause IOMMU "read from address 0" errors (rh#561267)
14 */
15 nv_wr32(dev, 0x100c08, dev_priv->gart_info.sg_dummy_bus >> 8);
16
17 /* This is needed to get meaningful information from 100c90
18 * on traps. No idea what these values mean exactly. */
13 switch (dev_priv->chipset) { 19 switch (dev_priv->chipset) {
14 case 0x50: 20 case 0x50:
15 nv_wr32(dev, 0x100c90, 0x0707ff); 21 nv_wr32(dev, 0x100c90, 0x0707ff);
diff --git a/drivers/gpu/drm/nouveau/nv50_gpio.c b/drivers/gpu/drm/nouveau/nv50_gpio.c
index c61782b314e7..bb47ad737267 100644
--- a/drivers/gpu/drm/nouveau/nv50_gpio.c
+++ b/drivers/gpu/drm/nouveau/nv50_gpio.c
@@ -31,7 +31,7 @@ nv50_gpio_location(struct dcb_gpio_entry *gpio, uint32_t *reg, uint32_t *shift)
31{ 31{
32 const uint32_t nv50_gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 }; 32 const uint32_t nv50_gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 };
33 33
34 if (gpio->line > 32) 34 if (gpio->line >= 32)
35 return -EINVAL; 35 return -EINVAL;
36 36
37 *reg = nv50_gpio_reg[gpio->line >> 3]; 37 *reg = nv50_gpio_reg[gpio->line >> 3];
diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c
index b11eaf9c5c7c..812778db76ac 100644
--- a/drivers/gpu/drm/nouveau/nv50_sor.c
+++ b/drivers/gpu/drm/nouveau/nv50_sor.c
@@ -274,7 +274,6 @@ static const struct drm_encoder_funcs nv50_sor_encoder_funcs = {
274int 274int
275nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry) 275nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry)
276{ 276{
277 struct drm_nouveau_private *dev_priv = dev->dev_private;
278 struct nouveau_encoder *nv_encoder = NULL; 277 struct nouveau_encoder *nv_encoder = NULL;
279 struct drm_encoder *encoder; 278 struct drm_encoder *encoder;
280 bool dum; 279 bool dum;
@@ -324,11 +323,7 @@ nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry)
324 int or = nv_encoder->or, link = !(entry->dpconf.sor.link & 1); 323 int or = nv_encoder->or, link = !(entry->dpconf.sor.link & 1);
325 uint32_t tmp; 324 uint32_t tmp;
326 325
327 if (dev_priv->chipset < 0x90 || 326 tmp = nv_rd32(dev, 0x61c700 + (or * 0x800));
328 dev_priv->chipset == 0x92 || dev_priv->chipset == 0xa0)
329 tmp = nv_rd32(dev, NV50_PDISPLAY_SOR_MODE_CTRL_C(or));
330 else
331 tmp = nv_rd32(dev, NV90_PDISPLAY_SOR_MODE_CTRL_C(or));
332 327
333 switch ((tmp & 0x00000f00) >> 8) { 328 switch ((tmp & 0x00000f00) >> 8) {
334 case 8: 329 case 8:
diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile
index 3c91312dea9a..84b1f2729d43 100644
--- a/drivers/gpu/drm/radeon/Makefile
+++ b/drivers/gpu/drm/radeon/Makefile
@@ -33,6 +33,9 @@ $(obj)/rs600_reg_safe.h: $(src)/reg_srcs/rs600 $(obj)/mkregtable
33$(obj)/r600_reg_safe.h: $(src)/reg_srcs/r600 $(obj)/mkregtable 33$(obj)/r600_reg_safe.h: $(src)/reg_srcs/r600 $(obj)/mkregtable
34 $(call if_changed,mkregtable) 34 $(call if_changed,mkregtable)
35 35
36$(obj)/evergreen_reg_safe.h: $(src)/reg_srcs/evergreen $(obj)/mkregtable
37 $(call if_changed,mkregtable)
38
36$(obj)/r100.o: $(obj)/r100_reg_safe.h $(obj)/rn50_reg_safe.h 39$(obj)/r100.o: $(obj)/r100_reg_safe.h $(obj)/rn50_reg_safe.h
37 40
38$(obj)/r200.o: $(obj)/r200_reg_safe.h 41$(obj)/r200.o: $(obj)/r200_reg_safe.h
@@ -47,6 +50,8 @@ $(obj)/rs600.o: $(obj)/rs600_reg_safe.h
47 50
48$(obj)/r600_cs.o: $(obj)/r600_reg_safe.h 51$(obj)/r600_cs.o: $(obj)/r600_reg_safe.h
49 52
53$(obj)/evergreen_cs.o: $(obj)/evergreen_reg_safe.h
54
50radeon-y := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o \ 55radeon-y := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o \
51 radeon_irq.o r300_cmdbuf.o r600_cp.o 56 radeon_irq.o r300_cmdbuf.o r600_cp.o
52# add KMS driver 57# add KMS driver
@@ -60,7 +65,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \
60 rs400.o rs600.o rs690.o rv515.o r520.o r600.o rv770.o radeon_test.o \ 65 rs400.o rs600.o rs690.o rv515.o r520.o r600.o rv770.o radeon_test.o \
61 r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \ 66 r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \
62 r600_blit_kms.o radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o \ 67 r600_blit_kms.o radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o \
63 evergreen.o 68 evergreen.o evergreen_cs.o
64 69
65radeon-$(CONFIG_COMPAT) += radeon_ioc32.o 70radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
66radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o 71radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index 03dd6c41dc19..f3f2827017ef 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -707,6 +707,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode
707 break; 707 break;
708 case ATOM_DCPLL: 708 case ATOM_DCPLL:
709 case ATOM_PPLL_INVALID: 709 case ATOM_PPLL_INVALID:
710 default:
710 pll = &rdev->clock.dcpll; 711 pll = &rdev->clock.dcpll;
711 break; 712 break;
712 } 713 }
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 8c8e4d3cbaa3..4b6623df3b96 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -41,7 +41,18 @@ void evergreen_fini(struct radeon_device *rdev);
41 41
42void evergreen_pm_misc(struct radeon_device *rdev) 42void evergreen_pm_misc(struct radeon_device *rdev)
43{ 43{
44 44 int req_ps_idx = rdev->pm.requested_power_state_index;
45 int req_cm_idx = rdev->pm.requested_clock_mode_index;
46 struct radeon_power_state *ps = &rdev->pm.power_state[req_ps_idx];
47 struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage;
48
49 if ((voltage->type == VOLTAGE_SW) && voltage->voltage) {
50 if (voltage->voltage != rdev->pm.current_vddc) {
51 radeon_atom_set_voltage(rdev, voltage->voltage);
52 rdev->pm.current_vddc = voltage->voltage;
53 DRM_DEBUG("Setting: v: %d\n", voltage->voltage);
54 }
55 }
45} 56}
46 57
47void evergreen_pm_prepare(struct radeon_device *rdev) 58void evergreen_pm_prepare(struct radeon_device *rdev)
@@ -2148,7 +2159,7 @@ int evergreen_init(struct radeon_device *rdev)
2148 if (r) 2159 if (r)
2149 return r; 2160 return r;
2150 2161
2151 rdev->accel_working = false; 2162 rdev->accel_working = true;
2152 r = evergreen_startup(rdev); 2163 r = evergreen_startup(rdev);
2153 if (r) { 2164 if (r) {
2154 dev_err(rdev->dev, "disabling GPU acceleration\n"); 2165 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
index 000000000000..64516b950891
--- /dev/null
+++ b/drivers/gpu/drm/radeon/evergreen_cs.c
@@ -0,0 +1,1356 @@
1/*
2 * Copyright 2010 Advanced Micro Devices, Inc.
3 * Copyright 2008 Red Hat Inc.
4 * Copyright 2009 Jerome Glisse.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors: Dave Airlie
25 * Alex Deucher
26 * Jerome Glisse
27 */
28#include "drmP.h"
29#include "radeon.h"
30#include "evergreend.h"
31#include "evergreen_reg_safe.h"
32
33static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p,
34 struct radeon_cs_reloc **cs_reloc);
35
36struct evergreen_cs_track {
37 u32 group_size;
38 u32 nbanks;
39 u32 npipes;
40 /* value we track */
41 u32 nsamples;
42 u32 cb_color_base_last[12];
43 struct radeon_bo *cb_color_bo[12];
44 u32 cb_color_bo_offset[12];
45 struct radeon_bo *cb_color_fmask_bo[8];
46 struct radeon_bo *cb_color_cmask_bo[8];
47 u32 cb_color_info[12];
48 u32 cb_color_view[12];
49 u32 cb_color_pitch_idx[12];
50 u32 cb_color_slice_idx[12];
51 u32 cb_color_dim_idx[12];
52 u32 cb_color_dim[12];
53 u32 cb_color_pitch[12];
54 u32 cb_color_slice[12];
55 u32 cb_color_cmask_slice[8];
56 u32 cb_color_fmask_slice[8];
57 u32 cb_target_mask;
58 u32 cb_shader_mask;
59 u32 vgt_strmout_config;
60 u32 vgt_strmout_buffer_config;
61 u32 db_depth_control;
62 u32 db_depth_view;
63 u32 db_depth_size;
64 u32 db_depth_size_idx;
65 u32 db_z_info;
66 u32 db_z_idx;
67 u32 db_z_read_offset;
68 u32 db_z_write_offset;
69 struct radeon_bo *db_z_read_bo;
70 struct radeon_bo *db_z_write_bo;
71 u32 db_s_info;
72 u32 db_s_idx;
73 u32 db_s_read_offset;
74 u32 db_s_write_offset;
75 struct radeon_bo *db_s_read_bo;
76 struct radeon_bo *db_s_write_bo;
77};
78
79static void evergreen_cs_track_init(struct evergreen_cs_track *track)
80{
81 int i;
82
83 for (i = 0; i < 8; i++) {
84 track->cb_color_fmask_bo[i] = NULL;
85 track->cb_color_cmask_bo[i] = NULL;
86 track->cb_color_cmask_slice[i] = 0;
87 track->cb_color_fmask_slice[i] = 0;
88 }
89
90 for (i = 0; i < 12; i++) {
91 track->cb_color_base_last[i] = 0;
92 track->cb_color_bo[i] = NULL;
93 track->cb_color_bo_offset[i] = 0xFFFFFFFF;
94 track->cb_color_info[i] = 0;
95 track->cb_color_view[i] = 0;
96 track->cb_color_pitch_idx[i] = 0;
97 track->cb_color_slice_idx[i] = 0;
98 track->cb_color_dim[i] = 0;
99 track->cb_color_pitch[i] = 0;
100 track->cb_color_slice[i] = 0;
101 track->cb_color_dim[i] = 0;
102 }
103 track->cb_target_mask = 0xFFFFFFFF;
104 track->cb_shader_mask = 0xFFFFFFFF;
105
106 track->db_depth_view = 0xFFFFC000;
107 track->db_depth_size = 0xFFFFFFFF;
108 track->db_depth_size_idx = 0;
109 track->db_depth_control = 0xFFFFFFFF;
110 track->db_z_info = 0xFFFFFFFF;
111 track->db_z_idx = 0xFFFFFFFF;
112 track->db_z_read_offset = 0xFFFFFFFF;
113 track->db_z_write_offset = 0xFFFFFFFF;
114 track->db_z_read_bo = NULL;
115 track->db_z_write_bo = NULL;
116 track->db_s_info = 0xFFFFFFFF;
117 track->db_s_idx = 0xFFFFFFFF;
118 track->db_s_read_offset = 0xFFFFFFFF;
119 track->db_s_write_offset = 0xFFFFFFFF;
120 track->db_s_read_bo = NULL;
121 track->db_s_write_bo = NULL;
122}
123
124static inline int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
125{
126 /* XXX fill in */
127 return 0;
128}
129
130static int evergreen_cs_track_check(struct radeon_cs_parser *p)
131{
132 struct evergreen_cs_track *track = p->track;
133
134 /* we don't support stream out buffer yet */
135 if (track->vgt_strmout_config || track->vgt_strmout_buffer_config) {
136 dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n");
137 return -EINVAL;
138 }
139
140 /* XXX fill in */
141 return 0;
142}
143
144/**
145 * evergreen_cs_packet_parse() - parse cp packet and point ib index to next packet
146 * @parser: parser structure holding parsing context.
147 * @pkt: where to store packet informations
148 *
149 * Assume that chunk_ib_index is properly set. Will return -EINVAL
150 * if packet is bigger than remaining ib size. or if packets is unknown.
151 **/
152int evergreen_cs_packet_parse(struct radeon_cs_parser *p,
153 struct radeon_cs_packet *pkt,
154 unsigned idx)
155{
156 struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx];
157 uint32_t header;
158
159 if (idx >= ib_chunk->length_dw) {
160 DRM_ERROR("Can not parse packet at %d after CS end %d !\n",
161 idx, ib_chunk->length_dw);
162 return -EINVAL;
163 }
164 header = radeon_get_ib_value(p, idx);
165 pkt->idx = idx;
166 pkt->type = CP_PACKET_GET_TYPE(header);
167 pkt->count = CP_PACKET_GET_COUNT(header);
168 pkt->one_reg_wr = 0;
169 switch (pkt->type) {
170 case PACKET_TYPE0:
171 pkt->reg = CP_PACKET0_GET_REG(header);
172 break;
173 case PACKET_TYPE3:
174 pkt->opcode = CP_PACKET3_GET_OPCODE(header);
175 break;
176 case PACKET_TYPE2:
177 pkt->count = -1;
178 break;
179 default:
180 DRM_ERROR("Unknown packet type %d at %d !\n", pkt->type, idx);
181 return -EINVAL;
182 }
183 if ((pkt->count + 1 + pkt->idx) >= ib_chunk->length_dw) {
184 DRM_ERROR("Packet (%d:%d:%d) end after CS buffer (%d) !\n",
185 pkt->idx, pkt->type, pkt->count, ib_chunk->length_dw);
186 return -EINVAL;
187 }
188 return 0;
189}
190
191/**
192 * evergreen_cs_packet_next_reloc() - parse next packet which should be reloc packet3
193 * @parser: parser structure holding parsing context.
194 * @data: pointer to relocation data
195 * @offset_start: starting offset
196 * @offset_mask: offset mask (to align start offset on)
197 * @reloc: reloc informations
198 *
199 * Check next packet is relocation packet3, do bo validation and compute
200 * GPU offset using the provided start.
201 **/
202static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p,
203 struct radeon_cs_reloc **cs_reloc)
204{
205 struct radeon_cs_chunk *relocs_chunk;
206 struct radeon_cs_packet p3reloc;
207 unsigned idx;
208 int r;
209
210 if (p->chunk_relocs_idx == -1) {
211 DRM_ERROR("No relocation chunk !\n");
212 return -EINVAL;
213 }
214 *cs_reloc = NULL;
215 relocs_chunk = &p->chunks[p->chunk_relocs_idx];
216 r = evergreen_cs_packet_parse(p, &p3reloc, p->idx);
217 if (r) {
218 return r;
219 }
220 p->idx += p3reloc.count + 2;
221 if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
222 DRM_ERROR("No packet3 for relocation for packet at %d.\n",
223 p3reloc.idx);
224 return -EINVAL;
225 }
226 idx = radeon_get_ib_value(p, p3reloc.idx + 1);
227 if (idx >= relocs_chunk->length_dw) {
228 DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
229 idx, relocs_chunk->length_dw);
230 return -EINVAL;
231 }
232 /* FIXME: we assume reloc size is 4 dwords */
233 *cs_reloc = p->relocs_ptr[(idx / 4)];
234 return 0;
235}
236
237/**
238 * evergreen_cs_packet_next_is_pkt3_nop() - test if next packet is packet3 nop for reloc
239 * @parser: parser structure holding parsing context.
240 *
241 * Check next packet is relocation packet3, do bo validation and compute
242 * GPU offset using the provided start.
243 **/
244static inline int evergreen_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p)
245{
246 struct radeon_cs_packet p3reloc;
247 int r;
248
249 r = evergreen_cs_packet_parse(p, &p3reloc, p->idx);
250 if (r) {
251 return 0;
252 }
253 if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
254 return 0;
255 }
256 return 1;
257}
258
259/**
260 * evergreen_cs_packet_next_vline() - parse userspace VLINE packet
261 * @parser: parser structure holding parsing context.
262 *
263 * Userspace sends a special sequence for VLINE waits.
264 * PACKET0 - VLINE_START_END + value
265 * PACKET3 - WAIT_REG_MEM poll vline status reg
266 * RELOC (P3) - crtc_id in reloc.
267 *
268 * This function parses this and relocates the VLINE START END
269 * and WAIT_REG_MEM packets to the correct crtc.
270 * It also detects a switched off crtc and nulls out the
271 * wait in that case.
272 */
273static int evergreen_cs_packet_parse_vline(struct radeon_cs_parser *p)
274{
275 struct drm_mode_object *obj;
276 struct drm_crtc *crtc;
277 struct radeon_crtc *radeon_crtc;
278 struct radeon_cs_packet p3reloc, wait_reg_mem;
279 int crtc_id;
280 int r;
281 uint32_t header, h_idx, reg, wait_reg_mem_info;
282 volatile uint32_t *ib;
283
284 ib = p->ib->ptr;
285
286 /* parse the WAIT_REG_MEM */
287 r = evergreen_cs_packet_parse(p, &wait_reg_mem, p->idx);
288 if (r)
289 return r;
290
291 /* check its a WAIT_REG_MEM */
292 if (wait_reg_mem.type != PACKET_TYPE3 ||
293 wait_reg_mem.opcode != PACKET3_WAIT_REG_MEM) {
294 DRM_ERROR("vline wait missing WAIT_REG_MEM segment\n");
295 r = -EINVAL;
296 return r;
297 }
298
299 wait_reg_mem_info = radeon_get_ib_value(p, wait_reg_mem.idx + 1);
300 /* bit 4 is reg (0) or mem (1) */
301 if (wait_reg_mem_info & 0x10) {
302 DRM_ERROR("vline WAIT_REG_MEM waiting on MEM rather than REG\n");
303 r = -EINVAL;
304 return r;
305 }
306 /* waiting for value to be equal */
307 if ((wait_reg_mem_info & 0x7) != 0x3) {
308 DRM_ERROR("vline WAIT_REG_MEM function not equal\n");
309 r = -EINVAL;
310 return r;
311 }
312 if ((radeon_get_ib_value(p, wait_reg_mem.idx + 2) << 2) != EVERGREEN_VLINE_STATUS) {
313 DRM_ERROR("vline WAIT_REG_MEM bad reg\n");
314 r = -EINVAL;
315 return r;
316 }
317
318 if (radeon_get_ib_value(p, wait_reg_mem.idx + 5) != EVERGREEN_VLINE_STAT) {
319 DRM_ERROR("vline WAIT_REG_MEM bad bit mask\n");
320 r = -EINVAL;
321 return r;
322 }
323
324 /* jump over the NOP */
325 r = evergreen_cs_packet_parse(p, &p3reloc, p->idx + wait_reg_mem.count + 2);
326 if (r)
327 return r;
328
329 h_idx = p->idx - 2;
330 p->idx += wait_reg_mem.count + 2;
331 p->idx += p3reloc.count + 2;
332
333 header = radeon_get_ib_value(p, h_idx);
334 crtc_id = radeon_get_ib_value(p, h_idx + 2 + 7 + 1);
335 reg = CP_PACKET0_GET_REG(header);
336 mutex_lock(&p->rdev->ddev->mode_config.mutex);
337 obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);
338 if (!obj) {
339 DRM_ERROR("cannot find crtc %d\n", crtc_id);
340 r = -EINVAL;
341 goto out;
342 }
343 crtc = obj_to_crtc(obj);
344 radeon_crtc = to_radeon_crtc(crtc);
345 crtc_id = radeon_crtc->crtc_id;
346
347 if (!crtc->enabled) {
348 /* if the CRTC isn't enabled - we need to nop out the WAIT_REG_MEM */
349 ib[h_idx + 2] = PACKET2(0);
350 ib[h_idx + 3] = PACKET2(0);
351 ib[h_idx + 4] = PACKET2(0);
352 ib[h_idx + 5] = PACKET2(0);
353 ib[h_idx + 6] = PACKET2(0);
354 ib[h_idx + 7] = PACKET2(0);
355 ib[h_idx + 8] = PACKET2(0);
356 } else {
357 switch (reg) {
358 case EVERGREEN_VLINE_START_END:
359 header &= ~R600_CP_PACKET0_REG_MASK;
360 header |= (EVERGREEN_VLINE_START_END + radeon_crtc->crtc_offset) >> 2;
361 ib[h_idx] = header;
362 ib[h_idx + 4] = (EVERGREEN_VLINE_STATUS + radeon_crtc->crtc_offset) >> 2;
363 break;
364 default:
365 DRM_ERROR("unknown crtc reloc\n");
366 r = -EINVAL;
367 goto out;
368 }
369 }
370out:
371 mutex_unlock(&p->rdev->ddev->mode_config.mutex);
372 return r;
373}
374
375static int evergreen_packet0_check(struct radeon_cs_parser *p,
376 struct radeon_cs_packet *pkt,
377 unsigned idx, unsigned reg)
378{
379 int r;
380
381 switch (reg) {
382 case EVERGREEN_VLINE_START_END:
383 r = evergreen_cs_packet_parse_vline(p);
384 if (r) {
385 DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
386 idx, reg);
387 return r;
388 }
389 break;
390 default:
391 printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n",
392 reg, idx);
393 return -EINVAL;
394 }
395 return 0;
396}
397
398static int evergreen_cs_parse_packet0(struct radeon_cs_parser *p,
399 struct radeon_cs_packet *pkt)
400{
401 unsigned reg, i;
402 unsigned idx;
403 int r;
404
405 idx = pkt->idx + 1;
406 reg = pkt->reg;
407 for (i = 0; i <= pkt->count; i++, idx++, reg += 4) {
408 r = evergreen_packet0_check(p, pkt, idx, reg);
409 if (r) {
410 return r;
411 }
412 }
413 return 0;
414}
415
416/**
417 * evergreen_cs_check_reg() - check if register is authorized or not
418 * @parser: parser structure holding parsing context
419 * @reg: register we are testing
420 * @idx: index into the cs buffer
421 *
422 * This function will test against evergreen_reg_safe_bm and return 0
423 * if register is safe. If register is not flag as safe this function
424 * will test it against a list of register needind special handling.
425 */
426static inline int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
427{
428 struct evergreen_cs_track *track = (struct evergreen_cs_track *)p->track;
429 struct radeon_cs_reloc *reloc;
430 u32 last_reg = ARRAY_SIZE(evergreen_reg_safe_bm);
431 u32 m, i, tmp, *ib;
432 int r;
433
434 i = (reg >> 7);
435 if (i > last_reg) {
436 dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
437 return -EINVAL;
438 }
439 m = 1 << ((reg >> 2) & 31);
440 if (!(evergreen_reg_safe_bm[i] & m))
441 return 0;
442 ib = p->ib->ptr;
443 switch (reg) {
444 /* force following reg to 0 in an attemp to disable out buffer
445 * which will need us to better understand how it works to perform
446 * security check on it (Jerome)
447 */
448 case SQ_ESGS_RING_SIZE:
449 case SQ_GSVS_RING_SIZE:
450 case SQ_ESTMP_RING_SIZE:
451 case SQ_GSTMP_RING_SIZE:
452 case SQ_HSTMP_RING_SIZE:
453 case SQ_LSTMP_RING_SIZE:
454 case SQ_PSTMP_RING_SIZE:
455 case SQ_VSTMP_RING_SIZE:
456 case SQ_ESGS_RING_ITEMSIZE:
457 case SQ_ESTMP_RING_ITEMSIZE:
458 case SQ_GSTMP_RING_ITEMSIZE:
459 case SQ_GSVS_RING_ITEMSIZE:
460 case SQ_GS_VERT_ITEMSIZE:
461 case SQ_GS_VERT_ITEMSIZE_1:
462 case SQ_GS_VERT_ITEMSIZE_2:
463 case SQ_GS_VERT_ITEMSIZE_3:
464 case SQ_GSVS_RING_OFFSET_1:
465 case SQ_GSVS_RING_OFFSET_2:
466 case SQ_GSVS_RING_OFFSET_3:
467 case SQ_HSTMP_RING_ITEMSIZE:
468 case SQ_LSTMP_RING_ITEMSIZE:
469 case SQ_PSTMP_RING_ITEMSIZE:
470 case SQ_VSTMP_RING_ITEMSIZE:
471 case VGT_TF_RING_SIZE:
472 /* get value to populate the IB don't remove */
473 tmp =radeon_get_ib_value(p, idx);
474 ib[idx] = 0;
475 break;
476 case DB_DEPTH_CONTROL:
477 track->db_depth_control = radeon_get_ib_value(p, idx);
478 break;
479 case DB_Z_INFO:
480 r = evergreen_cs_packet_next_reloc(p, &reloc);
481 if (r) {
482 dev_warn(p->dev, "bad SET_CONTEXT_REG "
483 "0x%04X\n", reg);
484 return -EINVAL;
485 }
486 track->db_z_info = radeon_get_ib_value(p, idx);
487 ib[idx] &= ~Z_ARRAY_MODE(0xf);
488 track->db_z_info &= ~Z_ARRAY_MODE(0xf);
489 if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
490 ib[idx] |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
491 track->db_z_info |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
492 } else {
493 ib[idx] |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
494 track->db_z_info |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
495 }
496 break;
497 case DB_STENCIL_INFO:
498 track->db_s_info = radeon_get_ib_value(p, idx);
499 break;
500 case DB_DEPTH_VIEW:
501 track->db_depth_view = radeon_get_ib_value(p, idx);
502 break;
503 case DB_DEPTH_SIZE:
504 track->db_depth_size = radeon_get_ib_value(p, idx);
505 track->db_depth_size_idx = idx;
506 break;
507 case DB_Z_READ_BASE:
508 r = evergreen_cs_packet_next_reloc(p, &reloc);
509 if (r) {
510 dev_warn(p->dev, "bad SET_CONTEXT_REG "
511 "0x%04X\n", reg);
512 return -EINVAL;
513 }
514 track->db_z_read_offset = radeon_get_ib_value(p, idx);
515 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
516 track->db_z_read_bo = reloc->robj;
517 break;
518 case DB_Z_WRITE_BASE:
519 r = evergreen_cs_packet_next_reloc(p, &reloc);
520 if (r) {
521 dev_warn(p->dev, "bad SET_CONTEXT_REG "
522 "0x%04X\n", reg);
523 return -EINVAL;
524 }
525 track->db_z_write_offset = radeon_get_ib_value(p, idx);
526 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
527 track->db_z_write_bo = reloc->robj;
528 break;
529 case DB_STENCIL_READ_BASE:
530 r = evergreen_cs_packet_next_reloc(p, &reloc);
531 if (r) {
532 dev_warn(p->dev, "bad SET_CONTEXT_REG "
533 "0x%04X\n", reg);
534 return -EINVAL;
535 }
536 track->db_s_read_offset = radeon_get_ib_value(p, idx);
537 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
538 track->db_s_read_bo = reloc->robj;
539 break;
540 case DB_STENCIL_WRITE_BASE:
541 r = evergreen_cs_packet_next_reloc(p, &reloc);
542 if (r) {
543 dev_warn(p->dev, "bad SET_CONTEXT_REG "
544 "0x%04X\n", reg);
545 return -EINVAL;
546 }
547 track->db_s_write_offset = radeon_get_ib_value(p, idx);
548 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
549 track->db_s_write_bo = reloc->robj;
550 break;
551 case VGT_STRMOUT_CONFIG:
552 track->vgt_strmout_config = radeon_get_ib_value(p, idx);
553 break;
554 case VGT_STRMOUT_BUFFER_CONFIG:
555 track->vgt_strmout_buffer_config = radeon_get_ib_value(p, idx);
556 break;
557 case CB_TARGET_MASK:
558 track->cb_target_mask = radeon_get_ib_value(p, idx);
559 break;
560 case CB_SHADER_MASK:
561 track->cb_shader_mask = radeon_get_ib_value(p, idx);
562 break;
563 case PA_SC_AA_CONFIG:
564 tmp = radeon_get_ib_value(p, idx) & MSAA_NUM_SAMPLES_MASK;
565 track->nsamples = 1 << tmp;
566 break;
567 case CB_COLOR0_VIEW:
568 case CB_COLOR1_VIEW:
569 case CB_COLOR2_VIEW:
570 case CB_COLOR3_VIEW:
571 case CB_COLOR4_VIEW:
572 case CB_COLOR5_VIEW:
573 case CB_COLOR6_VIEW:
574 case CB_COLOR7_VIEW:
575 tmp = (reg - CB_COLOR0_VIEW) / 0x3c;
576 track->cb_color_view[tmp] = radeon_get_ib_value(p, idx);
577 break;
578 case CB_COLOR8_VIEW:
579 case CB_COLOR9_VIEW:
580 case CB_COLOR10_VIEW:
581 case CB_COLOR11_VIEW:
582 tmp = ((reg - CB_COLOR8_VIEW) / 0x1c) + 8;
583 track->cb_color_view[tmp] = radeon_get_ib_value(p, idx);
584 break;
585 case CB_COLOR0_INFO:
586 case CB_COLOR1_INFO:
587 case CB_COLOR2_INFO:
588 case CB_COLOR3_INFO:
589 case CB_COLOR4_INFO:
590 case CB_COLOR5_INFO:
591 case CB_COLOR6_INFO:
592 case CB_COLOR7_INFO:
593 r = evergreen_cs_packet_next_reloc(p, &reloc);
594 if (r) {
595 dev_warn(p->dev, "bad SET_CONTEXT_REG "
596 "0x%04X\n", reg);
597 return -EINVAL;
598 }
599 tmp = (reg - CB_COLOR0_INFO) / 0x3c;
600 track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
601 if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
602 ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
603 track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
604 } else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
605 ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
606 track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
607 }
608 break;
609 case CB_COLOR8_INFO:
610 case CB_COLOR9_INFO:
611 case CB_COLOR10_INFO:
612 case CB_COLOR11_INFO:
613 r = evergreen_cs_packet_next_reloc(p, &reloc);
614 if (r) {
615 dev_warn(p->dev, "bad SET_CONTEXT_REG "
616 "0x%04X\n", reg);
617 return -EINVAL;
618 }
619 tmp = ((reg - CB_COLOR8_INFO) / 0x1c) + 8;
620 track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
621 if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
622 ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
623 track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
624 } else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
625 ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
626 track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
627 }
628 break;
629 case CB_COLOR0_PITCH:
630 case CB_COLOR1_PITCH:
631 case CB_COLOR2_PITCH:
632 case CB_COLOR3_PITCH:
633 case CB_COLOR4_PITCH:
634 case CB_COLOR5_PITCH:
635 case CB_COLOR6_PITCH:
636 case CB_COLOR7_PITCH:
637 tmp = (reg - CB_COLOR0_PITCH) / 0x3c;
638 track->cb_color_pitch[tmp] = radeon_get_ib_value(p, idx);
639 track->cb_color_pitch_idx[tmp] = idx;
640 break;
641 case CB_COLOR8_PITCH:
642 case CB_COLOR9_PITCH:
643 case CB_COLOR10_PITCH:
644 case CB_COLOR11_PITCH:
645 tmp = ((reg - CB_COLOR8_PITCH) / 0x1c) + 8;
646 track->cb_color_pitch[tmp] = radeon_get_ib_value(p, idx);
647 track->cb_color_pitch_idx[tmp] = idx;
648 break;
649 case CB_COLOR0_SLICE:
650 case CB_COLOR1_SLICE:
651 case CB_COLOR2_SLICE:
652 case CB_COLOR3_SLICE:
653 case CB_COLOR4_SLICE:
654 case CB_COLOR5_SLICE:
655 case CB_COLOR6_SLICE:
656 case CB_COLOR7_SLICE:
657 tmp = (reg - CB_COLOR0_SLICE) / 0x3c;
658 track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx);
659 track->cb_color_slice_idx[tmp] = idx;
660 break;
661 case CB_COLOR8_SLICE:
662 case CB_COLOR9_SLICE:
663 case CB_COLOR10_SLICE:
664 case CB_COLOR11_SLICE:
665 tmp = ((reg - CB_COLOR8_SLICE) / 0x1c) + 8;
666 track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx);
667 track->cb_color_slice_idx[tmp] = idx;
668 break;
669 case CB_COLOR0_ATTRIB:
670 case CB_COLOR1_ATTRIB:
671 case CB_COLOR2_ATTRIB:
672 case CB_COLOR3_ATTRIB:
673 case CB_COLOR4_ATTRIB:
674 case CB_COLOR5_ATTRIB:
675 case CB_COLOR6_ATTRIB:
676 case CB_COLOR7_ATTRIB:
677 case CB_COLOR8_ATTRIB:
678 case CB_COLOR9_ATTRIB:
679 case CB_COLOR10_ATTRIB:
680 case CB_COLOR11_ATTRIB:
681 break;
682 case CB_COLOR0_DIM:
683 case CB_COLOR1_DIM:
684 case CB_COLOR2_DIM:
685 case CB_COLOR3_DIM:
686 case CB_COLOR4_DIM:
687 case CB_COLOR5_DIM:
688 case CB_COLOR6_DIM:
689 case CB_COLOR7_DIM:
690 tmp = (reg - CB_COLOR0_DIM) / 0x3c;
691 track->cb_color_dim[tmp] = radeon_get_ib_value(p, idx);
692 track->cb_color_dim_idx[tmp] = idx;
693 break;
694 case CB_COLOR8_DIM:
695 case CB_COLOR9_DIM:
696 case CB_COLOR10_DIM:
697 case CB_COLOR11_DIM:
698 tmp = ((reg - CB_COLOR8_DIM) / 0x1c) + 8;
699 track->cb_color_dim[tmp] = radeon_get_ib_value(p, idx);
700 track->cb_color_dim_idx[tmp] = idx;
701 break;
702 case CB_COLOR0_FMASK:
703 case CB_COLOR1_FMASK:
704 case CB_COLOR2_FMASK:
705 case CB_COLOR3_FMASK:
706 case CB_COLOR4_FMASK:
707 case CB_COLOR5_FMASK:
708 case CB_COLOR6_FMASK:
709 case CB_COLOR7_FMASK:
710 tmp = (reg - CB_COLOR0_FMASK) / 0x3c;
711 r = evergreen_cs_packet_next_reloc(p, &reloc);
712 if (r) {
713 dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
714 return -EINVAL;
715 }
716 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
717 track->cb_color_fmask_bo[tmp] = reloc->robj;
718 break;
719 case CB_COLOR0_CMASK:
720 case CB_COLOR1_CMASK:
721 case CB_COLOR2_CMASK:
722 case CB_COLOR3_CMASK:
723 case CB_COLOR4_CMASK:
724 case CB_COLOR5_CMASK:
725 case CB_COLOR6_CMASK:
726 case CB_COLOR7_CMASK:
727 tmp = (reg - CB_COLOR0_CMASK) / 0x3c;
728 r = evergreen_cs_packet_next_reloc(p, &reloc);
729 if (r) {
730 dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
731 return -EINVAL;
732 }
733 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
734 track->cb_color_cmask_bo[tmp] = reloc->robj;
735 break;
736 case CB_COLOR0_FMASK_SLICE:
737 case CB_COLOR1_FMASK_SLICE:
738 case CB_COLOR2_FMASK_SLICE:
739 case CB_COLOR3_FMASK_SLICE:
740 case CB_COLOR4_FMASK_SLICE:
741 case CB_COLOR5_FMASK_SLICE:
742 case CB_COLOR6_FMASK_SLICE:
743 case CB_COLOR7_FMASK_SLICE:
744 tmp = (reg - CB_COLOR0_FMASK_SLICE) / 0x3c;
745 track->cb_color_fmask_slice[tmp] = radeon_get_ib_value(p, idx);
746 break;
747 case CB_COLOR0_CMASK_SLICE:
748 case CB_COLOR1_CMASK_SLICE:
749 case CB_COLOR2_CMASK_SLICE:
750 case CB_COLOR3_CMASK_SLICE:
751 case CB_COLOR4_CMASK_SLICE:
752 case CB_COLOR5_CMASK_SLICE:
753 case CB_COLOR6_CMASK_SLICE:
754 case CB_COLOR7_CMASK_SLICE:
755 tmp = (reg - CB_COLOR0_CMASK_SLICE) / 0x3c;
756 track->cb_color_cmask_slice[tmp] = radeon_get_ib_value(p, idx);
757 break;
758 case CB_COLOR0_BASE:
759 case CB_COLOR1_BASE:
760 case CB_COLOR2_BASE:
761 case CB_COLOR3_BASE:
762 case CB_COLOR4_BASE:
763 case CB_COLOR5_BASE:
764 case CB_COLOR6_BASE:
765 case CB_COLOR7_BASE:
766 r = evergreen_cs_packet_next_reloc(p, &reloc);
767 if (r) {
768 dev_warn(p->dev, "bad SET_CONTEXT_REG "
769 "0x%04X\n", reg);
770 return -EINVAL;
771 }
772 tmp = (reg - CB_COLOR0_BASE) / 0x3c;
773 track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx);
774 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
775 track->cb_color_base_last[tmp] = ib[idx];
776 track->cb_color_bo[tmp] = reloc->robj;
777 break;
778 case CB_COLOR8_BASE:
779 case CB_COLOR9_BASE:
780 case CB_COLOR10_BASE:
781 case CB_COLOR11_BASE:
782 r = evergreen_cs_packet_next_reloc(p, &reloc);
783 if (r) {
784 dev_warn(p->dev, "bad SET_CONTEXT_REG "
785 "0x%04X\n", reg);
786 return -EINVAL;
787 }
788 tmp = ((reg - CB_COLOR8_BASE) / 0x1c) + 8;
789 track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx);
790 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
791 track->cb_color_base_last[tmp] = ib[idx];
792 track->cb_color_bo[tmp] = reloc->robj;
793 break;
794 case CB_IMMED0_BASE:
795 case CB_IMMED1_BASE:
796 case CB_IMMED2_BASE:
797 case CB_IMMED3_BASE:
798 case CB_IMMED4_BASE:
799 case CB_IMMED5_BASE:
800 case CB_IMMED6_BASE:
801 case CB_IMMED7_BASE:
802 case CB_IMMED8_BASE:
803 case CB_IMMED9_BASE:
804 case CB_IMMED10_BASE:
805 case CB_IMMED11_BASE:
806 case DB_HTILE_DATA_BASE:
807 case SQ_PGM_START_FS:
808 case SQ_PGM_START_ES:
809 case SQ_PGM_START_VS:
810 case SQ_PGM_START_GS:
811 case SQ_PGM_START_PS:
812 case SQ_PGM_START_HS:
813 case SQ_PGM_START_LS:
814 case GDS_ADDR_BASE:
815 case SQ_CONST_MEM_BASE:
816 case SQ_ALU_CONST_CACHE_GS_0:
817 case SQ_ALU_CONST_CACHE_GS_1:
818 case SQ_ALU_CONST_CACHE_GS_2:
819 case SQ_ALU_CONST_CACHE_GS_3:
820 case SQ_ALU_CONST_CACHE_GS_4:
821 case SQ_ALU_CONST_CACHE_GS_5:
822 case SQ_ALU_CONST_CACHE_GS_6:
823 case SQ_ALU_CONST_CACHE_GS_7:
824 case SQ_ALU_CONST_CACHE_GS_8:
825 case SQ_ALU_CONST_CACHE_GS_9:
826 case SQ_ALU_CONST_CACHE_GS_10:
827 case SQ_ALU_CONST_CACHE_GS_11:
828 case SQ_ALU_CONST_CACHE_GS_12:
829 case SQ_ALU_CONST_CACHE_GS_13:
830 case SQ_ALU_CONST_CACHE_GS_14:
831 case SQ_ALU_CONST_CACHE_GS_15:
832 case SQ_ALU_CONST_CACHE_PS_0:
833 case SQ_ALU_CONST_CACHE_PS_1:
834 case SQ_ALU_CONST_CACHE_PS_2:
835 case SQ_ALU_CONST_CACHE_PS_3:
836 case SQ_ALU_CONST_CACHE_PS_4:
837 case SQ_ALU_CONST_CACHE_PS_5:
838 case SQ_ALU_CONST_CACHE_PS_6:
839 case SQ_ALU_CONST_CACHE_PS_7:
840 case SQ_ALU_CONST_CACHE_PS_8:
841 case SQ_ALU_CONST_CACHE_PS_9:
842 case SQ_ALU_CONST_CACHE_PS_10:
843 case SQ_ALU_CONST_CACHE_PS_11:
844 case SQ_ALU_CONST_CACHE_PS_12:
845 case SQ_ALU_CONST_CACHE_PS_13:
846 case SQ_ALU_CONST_CACHE_PS_14:
847 case SQ_ALU_CONST_CACHE_PS_15:
848 case SQ_ALU_CONST_CACHE_VS_0:
849 case SQ_ALU_CONST_CACHE_VS_1:
850 case SQ_ALU_CONST_CACHE_VS_2:
851 case SQ_ALU_CONST_CACHE_VS_3:
852 case SQ_ALU_CONST_CACHE_VS_4:
853 case SQ_ALU_CONST_CACHE_VS_5:
854 case SQ_ALU_CONST_CACHE_VS_6:
855 case SQ_ALU_CONST_CACHE_VS_7:
856 case SQ_ALU_CONST_CACHE_VS_8:
857 case SQ_ALU_CONST_CACHE_VS_9:
858 case SQ_ALU_CONST_CACHE_VS_10:
859 case SQ_ALU_CONST_CACHE_VS_11:
860 case SQ_ALU_CONST_CACHE_VS_12:
861 case SQ_ALU_CONST_CACHE_VS_13:
862 case SQ_ALU_CONST_CACHE_VS_14:
863 case SQ_ALU_CONST_CACHE_VS_15:
864 case SQ_ALU_CONST_CACHE_HS_0:
865 case SQ_ALU_CONST_CACHE_HS_1:
866 case SQ_ALU_CONST_CACHE_HS_2:
867 case SQ_ALU_CONST_CACHE_HS_3:
868 case SQ_ALU_CONST_CACHE_HS_4:
869 case SQ_ALU_CONST_CACHE_HS_5:
870 case SQ_ALU_CONST_CACHE_HS_6:
871 case SQ_ALU_CONST_CACHE_HS_7:
872 case SQ_ALU_CONST_CACHE_HS_8:
873 case SQ_ALU_CONST_CACHE_HS_9:
874 case SQ_ALU_CONST_CACHE_HS_10:
875 case SQ_ALU_CONST_CACHE_HS_11:
876 case SQ_ALU_CONST_CACHE_HS_12:
877 case SQ_ALU_CONST_CACHE_HS_13:
878 case SQ_ALU_CONST_CACHE_HS_14:
879 case SQ_ALU_CONST_CACHE_HS_15:
880 case SQ_ALU_CONST_CACHE_LS_0:
881 case SQ_ALU_CONST_CACHE_LS_1:
882 case SQ_ALU_CONST_CACHE_LS_2:
883 case SQ_ALU_CONST_CACHE_LS_3:
884 case SQ_ALU_CONST_CACHE_LS_4:
885 case SQ_ALU_CONST_CACHE_LS_5:
886 case SQ_ALU_CONST_CACHE_LS_6:
887 case SQ_ALU_CONST_CACHE_LS_7:
888 case SQ_ALU_CONST_CACHE_LS_8:
889 case SQ_ALU_CONST_CACHE_LS_9:
890 case SQ_ALU_CONST_CACHE_LS_10:
891 case SQ_ALU_CONST_CACHE_LS_11:
892 case SQ_ALU_CONST_CACHE_LS_12:
893 case SQ_ALU_CONST_CACHE_LS_13:
894 case SQ_ALU_CONST_CACHE_LS_14:
895 case SQ_ALU_CONST_CACHE_LS_15:
896 r = evergreen_cs_packet_next_reloc(p, &reloc);
897 if (r) {
898 dev_warn(p->dev, "bad SET_CONTEXT_REG "
899 "0x%04X\n", reg);
900 return -EINVAL;
901 }
902 ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
903 break;
904 default:
905 dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
906 return -EINVAL;
907 }
908 return 0;
909}
910
911/**
912 * evergreen_check_texture_resource() - check if register is authorized or not
913 * @p: parser structure holding parsing context
914 * @idx: index into the cs buffer
915 * @texture: texture's bo structure
916 * @mipmap: mipmap's bo structure
917 *
918 * This function will check that the resource has valid field and that
919 * the texture and mipmap bo object are big enough to cover this resource.
920 */
921static inline int evergreen_check_texture_resource(struct radeon_cs_parser *p, u32 idx,
922 struct radeon_bo *texture,
923 struct radeon_bo *mipmap)
924{
925 /* XXX fill in */
926 return 0;
927}
928
929static int evergreen_packet3_check(struct radeon_cs_parser *p,
930 struct radeon_cs_packet *pkt)
931{
932 struct radeon_cs_reloc *reloc;
933 struct evergreen_cs_track *track;
934 volatile u32 *ib;
935 unsigned idx;
936 unsigned i;
937 unsigned start_reg, end_reg, reg;
938 int r;
939 u32 idx_value;
940
941 track = (struct evergreen_cs_track *)p->track;
942 ib = p->ib->ptr;
943 idx = pkt->idx + 1;
944 idx_value = radeon_get_ib_value(p, idx);
945
946 switch (pkt->opcode) {
947 case PACKET3_CONTEXT_CONTROL:
948 if (pkt->count != 1) {
949 DRM_ERROR("bad CONTEXT_CONTROL\n");
950 return -EINVAL;
951 }
952 break;
953 case PACKET3_INDEX_TYPE:
954 case PACKET3_NUM_INSTANCES:
955 case PACKET3_CLEAR_STATE:
956 if (pkt->count) {
957 DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES/CLEAR_STATE\n");
958 return -EINVAL;
959 }
960 break;
961 case PACKET3_INDEX_BASE:
962 if (pkt->count != 1) {
963 DRM_ERROR("bad INDEX_BASE\n");
964 return -EINVAL;
965 }
966 r = evergreen_cs_packet_next_reloc(p, &reloc);
967 if (r) {
968 DRM_ERROR("bad INDEX_BASE\n");
969 return -EINVAL;
970 }
971 ib[idx+0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
972 ib[idx+1] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
973 r = evergreen_cs_track_check(p);
974 if (r) {
975 dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
976 return r;
977 }
978 break;
979 case PACKET3_DRAW_INDEX:
980 if (pkt->count != 3) {
981 DRM_ERROR("bad DRAW_INDEX\n");
982 return -EINVAL;
983 }
984 r = evergreen_cs_packet_next_reloc(p, &reloc);
985 if (r) {
986 DRM_ERROR("bad DRAW_INDEX\n");
987 return -EINVAL;
988 }
989 ib[idx+0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
990 ib[idx+1] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
991 r = evergreen_cs_track_check(p);
992 if (r) {
993 dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
994 return r;
995 }
996 break;
997 case PACKET3_DRAW_INDEX_2:
998 if (pkt->count != 4) {
999 DRM_ERROR("bad DRAW_INDEX_2\n");
1000 return -EINVAL;
1001 }
1002 r = evergreen_cs_packet_next_reloc(p, &reloc);
1003 if (r) {
1004 DRM_ERROR("bad DRAW_INDEX_2\n");
1005 return -EINVAL;
1006 }
1007 ib[idx+1] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
1008 ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
1009 r = evergreen_cs_track_check(p);
1010 if (r) {
1011 dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
1012 return r;
1013 }
1014 break;
1015 case PACKET3_DRAW_INDEX_AUTO:
1016 if (pkt->count != 1) {
1017 DRM_ERROR("bad DRAW_INDEX_AUTO\n");
1018 return -EINVAL;
1019 }
1020 r = evergreen_cs_track_check(p);
1021 if (r) {
1022 dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx);
1023 return r;
1024 }
1025 break;
1026 case PACKET3_DRAW_INDEX_MULTI_AUTO:
1027 if (pkt->count != 2) {
1028 DRM_ERROR("bad DRAW_INDEX_MULTI_AUTO\n");
1029 return -EINVAL;
1030 }
1031 r = evergreen_cs_track_check(p);
1032 if (r) {
1033 dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx);
1034 return r;
1035 }
1036 break;
1037 case PACKET3_DRAW_INDEX_IMMD:
1038 if (pkt->count < 2) {
1039 DRM_ERROR("bad DRAW_INDEX_IMMD\n");
1040 return -EINVAL;
1041 }
1042 r = evergreen_cs_track_check(p);
1043 if (r) {
1044 dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
1045 return r;
1046 }
1047 break;
1048 case PACKET3_DRAW_INDEX_OFFSET:
1049 if (pkt->count != 2) {
1050 DRM_ERROR("bad DRAW_INDEX_OFFSET\n");
1051 return -EINVAL;
1052 }
1053 r = evergreen_cs_track_check(p);
1054 if (r) {
1055 dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
1056 return r;
1057 }
1058 break;
1059 case PACKET3_DRAW_INDEX_OFFSET_2:
1060 if (pkt->count != 3) {
1061 DRM_ERROR("bad DRAW_INDEX_OFFSET_2\n");
1062 return -EINVAL;
1063 }
1064 r = evergreen_cs_track_check(p);
1065 if (r) {
1066 dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
1067 return r;
1068 }
1069 break;
1070 case PACKET3_WAIT_REG_MEM:
1071 if (pkt->count != 5) {
1072 DRM_ERROR("bad WAIT_REG_MEM\n");
1073 return -EINVAL;
1074 }
1075 /* bit 4 is reg (0) or mem (1) */
1076 if (idx_value & 0x10) {
1077 r = evergreen_cs_packet_next_reloc(p, &reloc);
1078 if (r) {
1079 DRM_ERROR("bad WAIT_REG_MEM\n");
1080 return -EINVAL;
1081 }
1082 ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
1083 ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
1084 }
1085 break;
1086 case PACKET3_SURFACE_SYNC:
1087 if (pkt->count != 3) {
1088 DRM_ERROR("bad SURFACE_SYNC\n");
1089 return -EINVAL;
1090 }
1091 /* 0xffffffff/0x0 is flush all cache flag */
1092 if (radeon_get_ib_value(p, idx + 1) != 0xffffffff ||
1093 radeon_get_ib_value(p, idx + 2) != 0) {
1094 r = evergreen_cs_packet_next_reloc(p, &reloc);
1095 if (r) {
1096 DRM_ERROR("bad SURFACE_SYNC\n");
1097 return -EINVAL;
1098 }
1099 ib[idx+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1100 }
1101 break;
1102 case PACKET3_EVENT_WRITE:
1103 if (pkt->count != 2 && pkt->count != 0) {
1104 DRM_ERROR("bad EVENT_WRITE\n");
1105 return -EINVAL;
1106 }
1107 if (pkt->count) {
1108 r = evergreen_cs_packet_next_reloc(p, &reloc);
1109 if (r) {
1110 DRM_ERROR("bad EVENT_WRITE\n");
1111 return -EINVAL;
1112 }
1113 ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
1114 ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
1115 }
1116 break;
1117 case PACKET3_EVENT_WRITE_EOP:
1118 if (pkt->count != 4) {
1119 DRM_ERROR("bad EVENT_WRITE_EOP\n");
1120 return -EINVAL;
1121 }
1122 r = evergreen_cs_packet_next_reloc(p, &reloc);
1123 if (r) {
1124 DRM_ERROR("bad EVENT_WRITE_EOP\n");
1125 return -EINVAL;
1126 }
1127 ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
1128 ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
1129 break;
1130 case PACKET3_EVENT_WRITE_EOS:
1131 if (pkt->count != 3) {
1132 DRM_ERROR("bad EVENT_WRITE_EOS\n");
1133 return -EINVAL;
1134 }
1135 r = evergreen_cs_packet_next_reloc(p, &reloc);
1136 if (r) {
1137 DRM_ERROR("bad EVENT_WRITE_EOS\n");
1138 return -EINVAL;
1139 }
1140 ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
1141 ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
1142 break;
1143 case PACKET3_SET_CONFIG_REG:
1144 start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_START;
1145 end_reg = 4 * pkt->count + start_reg - 4;
1146 if ((start_reg < PACKET3_SET_CONFIG_REG_START) ||
1147 (start_reg >= PACKET3_SET_CONFIG_REG_END) ||
1148 (end_reg >= PACKET3_SET_CONFIG_REG_END)) {
1149 DRM_ERROR("bad PACKET3_SET_CONFIG_REG\n");
1150 return -EINVAL;
1151 }
1152 for (i = 0; i < pkt->count; i++) {
1153 reg = start_reg + (4 * i);
1154 r = evergreen_cs_check_reg(p, reg, idx+1+i);
1155 if (r)
1156 return r;
1157 }
1158 break;
1159 case PACKET3_SET_CONTEXT_REG:
1160 start_reg = (idx_value << 2) + PACKET3_SET_CONTEXT_REG_START;
1161 end_reg = 4 * pkt->count + start_reg - 4;
1162 if ((start_reg < PACKET3_SET_CONTEXT_REG_START) ||
1163 (start_reg >= PACKET3_SET_CONTEXT_REG_END) ||
1164 (end_reg >= PACKET3_SET_CONTEXT_REG_END)) {
1165 DRM_ERROR("bad PACKET3_SET_CONTEXT_REG\n");
1166 return -EINVAL;
1167 }
1168 for (i = 0; i < pkt->count; i++) {
1169 reg = start_reg + (4 * i);
1170 r = evergreen_cs_check_reg(p, reg, idx+1+i);
1171 if (r)
1172 return r;
1173 }
1174 break;
1175 case PACKET3_SET_RESOURCE:
1176 if (pkt->count % 8) {
1177 DRM_ERROR("bad SET_RESOURCE\n");
1178 return -EINVAL;
1179 }
1180 start_reg = (idx_value << 2) + PACKET3_SET_RESOURCE_START;
1181 end_reg = 4 * pkt->count + start_reg - 4;
1182 if ((start_reg < PACKET3_SET_RESOURCE_START) ||
1183 (start_reg >= PACKET3_SET_RESOURCE_END) ||
1184 (end_reg >= PACKET3_SET_RESOURCE_END)) {
1185 DRM_ERROR("bad SET_RESOURCE\n");
1186 return -EINVAL;
1187 }
1188 for (i = 0; i < (pkt->count / 8); i++) {
1189 struct radeon_bo *texture, *mipmap;
1190 u32 size, offset;
1191
1192 switch (G__SQ_CONSTANT_TYPE(radeon_get_ib_value(p, idx+1+(i*8)+7))) {
1193 case SQ_TEX_VTX_VALID_TEXTURE:
1194 /* tex base */
1195 r = evergreen_cs_packet_next_reloc(p, &reloc);
1196 if (r) {
1197 DRM_ERROR("bad SET_RESOURCE (tex)\n");
1198 return -EINVAL;
1199 }
1200 ib[idx+1+(i*8)+3] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1201 if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
1202 ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
1203 else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
1204 ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
1205 texture = reloc->robj;
1206 /* tex mip base */
1207 r = evergreen_cs_packet_next_reloc(p, &reloc);
1208 if (r) {
1209 DRM_ERROR("bad SET_RESOURCE (tex)\n");
1210 return -EINVAL;
1211 }
1212 ib[idx+1+(i*8)+4] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
1213 mipmap = reloc->robj;
1214 r = evergreen_check_texture_resource(p, idx+1+(i*8),
1215 texture, mipmap);
1216 if (r)
1217 return r;
1218 break;
1219 case SQ_TEX_VTX_VALID_BUFFER:
1220 /* vtx base */
1221 r = evergreen_cs_packet_next_reloc(p, &reloc);
1222 if (r) {
1223 DRM_ERROR("bad SET_RESOURCE (vtx)\n");
1224 return -EINVAL;
1225 }
1226 offset = radeon_get_ib_value(p, idx+1+(i*8)+0);
1227 size = radeon_get_ib_value(p, idx+1+(i*8)+1);
1228 if (p->rdev && (size + offset) > radeon_bo_size(reloc->robj)) {
1229 /* force size to size of the buffer */
1230 dev_warn(p->dev, "vbo resource seems too big for the bo\n");
1231 ib[idx+1+(i*8)+1] = radeon_bo_size(reloc->robj);
1232 }
1233 ib[idx+1+(i*8)+0] += (u32)((reloc->lobj.gpu_offset) & 0xffffffff);
1234 ib[idx+1+(i*8)+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
1235 break;
1236 case SQ_TEX_VTX_INVALID_TEXTURE:
1237 case SQ_TEX_VTX_INVALID_BUFFER:
1238 default:
1239 DRM_ERROR("bad SET_RESOURCE\n");
1240 return -EINVAL;
1241 }
1242 }
1243 break;
1244 case PACKET3_SET_ALU_CONST:
1245 /* XXX fix me ALU const buffers only */
1246 break;
1247 case PACKET3_SET_BOOL_CONST:
1248 start_reg = (idx_value << 2) + PACKET3_SET_BOOL_CONST_START;
1249 end_reg = 4 * pkt->count + start_reg - 4;
1250 if ((start_reg < PACKET3_SET_BOOL_CONST_START) ||
1251 (start_reg >= PACKET3_SET_BOOL_CONST_END) ||
1252 (end_reg >= PACKET3_SET_BOOL_CONST_END)) {
1253 DRM_ERROR("bad SET_BOOL_CONST\n");
1254 return -EINVAL;
1255 }
1256 break;
1257 case PACKET3_SET_LOOP_CONST:
1258 start_reg = (idx_value << 2) + PACKET3_SET_LOOP_CONST_START;
1259 end_reg = 4 * pkt->count + start_reg - 4;
1260 if ((start_reg < PACKET3_SET_LOOP_CONST_START) ||
1261 (start_reg >= PACKET3_SET_LOOP_CONST_END) ||
1262 (end_reg >= PACKET3_SET_LOOP_CONST_END)) {
1263 DRM_ERROR("bad SET_LOOP_CONST\n");
1264 return -EINVAL;
1265 }
1266 break;
1267 case PACKET3_SET_CTL_CONST:
1268 start_reg = (idx_value << 2) + PACKET3_SET_CTL_CONST_START;
1269 end_reg = 4 * pkt->count + start_reg - 4;
1270 if ((start_reg < PACKET3_SET_CTL_CONST_START) ||
1271 (start_reg >= PACKET3_SET_CTL_CONST_END) ||
1272 (end_reg >= PACKET3_SET_CTL_CONST_END)) {
1273 DRM_ERROR("bad SET_CTL_CONST\n");
1274 return -EINVAL;
1275 }
1276 break;
1277 case PACKET3_SET_SAMPLER:
1278 if (pkt->count % 3) {
1279 DRM_ERROR("bad SET_SAMPLER\n");
1280 return -EINVAL;
1281 }
1282 start_reg = (idx_value << 2) + PACKET3_SET_SAMPLER_START;
1283 end_reg = 4 * pkt->count + start_reg - 4;
1284 if ((start_reg < PACKET3_SET_SAMPLER_START) ||
1285 (start_reg >= PACKET3_SET_SAMPLER_END) ||
1286 (end_reg >= PACKET3_SET_SAMPLER_END)) {
1287 DRM_ERROR("bad SET_SAMPLER\n");
1288 return -EINVAL;
1289 }
1290 break;
1291 case PACKET3_NOP:
1292 break;
1293 default:
1294 DRM_ERROR("Packet3 opcode %x not supported\n", pkt->opcode);
1295 return -EINVAL;
1296 }
1297 return 0;
1298}
1299
1300int evergreen_cs_parse(struct radeon_cs_parser *p)
1301{
1302 struct radeon_cs_packet pkt;
1303 struct evergreen_cs_track *track;
1304 int r;
1305
1306 if (p->track == NULL) {
1307 /* initialize tracker, we are in kms */
1308 track = kzalloc(sizeof(*track), GFP_KERNEL);
1309 if (track == NULL)
1310 return -ENOMEM;
1311 evergreen_cs_track_init(track);
1312 track->npipes = p->rdev->config.evergreen.tiling_npipes;
1313 track->nbanks = p->rdev->config.evergreen.tiling_nbanks;
1314 track->group_size = p->rdev->config.evergreen.tiling_group_size;
1315 p->track = track;
1316 }
1317 do {
1318 r = evergreen_cs_packet_parse(p, &pkt, p->idx);
1319 if (r) {
1320 kfree(p->track);
1321 p->track = NULL;
1322 return r;
1323 }
1324 p->idx += pkt.count + 2;
1325 switch (pkt.type) {
1326 case PACKET_TYPE0:
1327 r = evergreen_cs_parse_packet0(p, &pkt);
1328 break;
1329 case PACKET_TYPE2:
1330 break;
1331 case PACKET_TYPE3:
1332 r = evergreen_packet3_check(p, &pkt);
1333 break;
1334 default:
1335 DRM_ERROR("Unknown packet type %d !\n", pkt.type);
1336 kfree(p->track);
1337 p->track = NULL;
1338 return -EINVAL;
1339 }
1340 if (r) {
1341 kfree(p->track);
1342 p->track = NULL;
1343 return r;
1344 }
1345 } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw);
1346#if 0
1347 for (r = 0; r < p->ib->length_dw; r++) {
1348 printk(KERN_INFO "%05d 0x%08X\n", r, p->ib->ptr[r]);
1349 mdelay(1);
1350 }
1351#endif
1352 kfree(p->track);
1353 p->track = NULL;
1354 return 0;
1355}
1356
diff --git a/drivers/gpu/drm/radeon/evergreen_reg.h b/drivers/gpu/drm/radeon/evergreen_reg.h
index af86af836f13..e028c1cd9d9b 100644
--- a/drivers/gpu/drm/radeon/evergreen_reg.h
+++ b/drivers/gpu/drm/radeon/evergreen_reg.h
@@ -151,6 +151,9 @@
151#define EVERGREEN_DATA_FORMAT 0x6b00 151#define EVERGREEN_DATA_FORMAT 0x6b00
152# define EVERGREEN_INTERLEAVE_EN (1 << 0) 152# define EVERGREEN_INTERLEAVE_EN (1 << 0)
153#define EVERGREEN_DESKTOP_HEIGHT 0x6b04 153#define EVERGREEN_DESKTOP_HEIGHT 0x6b04
154#define EVERGREEN_VLINE_START_END 0x6b08
155#define EVERGREEN_VLINE_STATUS 0x6bb8
156# define EVERGREEN_VLINE_STAT (1 << 12)
154 157
155#define EVERGREEN_VIEWPORT_START 0x6d70 158#define EVERGREEN_VIEWPORT_START 0x6d70
156#define EVERGREEN_VIEWPORT_SIZE 0x6d74 159#define EVERGREEN_VIEWPORT_SIZE 0x6d74
diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h
index 93e9e17ad54a..79683f6b4452 100644
--- a/drivers/gpu/drm/radeon/evergreend.h
+++ b/drivers/gpu/drm/radeon/evergreend.h
@@ -218,6 +218,8 @@
218#define CLIP_VTX_REORDER_ENA (1 << 0) 218#define CLIP_VTX_REORDER_ENA (1 << 0)
219#define NUM_CLIP_SEQ(x) ((x) << 1) 219#define NUM_CLIP_SEQ(x) ((x) << 1)
220#define PA_SC_AA_CONFIG 0x28C04 220#define PA_SC_AA_CONFIG 0x28C04
221#define MSAA_NUM_SAMPLES_SHIFT 0
222#define MSAA_NUM_SAMPLES_MASK 0x3
221#define PA_SC_CLIPRECT_RULE 0x2820C 223#define PA_SC_CLIPRECT_RULE 0x2820C
222#define PA_SC_EDGERULE 0x28230 224#define PA_SC_EDGERULE 0x28230
223#define PA_SC_FIFO_SIZE 0x8BCC 225#define PA_SC_FIFO_SIZE 0x8BCC
@@ -553,4 +555,466 @@
553# define DC_HPDx_RX_INT_TIMER(x) ((x) << 16) 555# define DC_HPDx_RX_INT_TIMER(x) ((x) << 16)
554# define DC_HPDx_EN (1 << 28) 556# define DC_HPDx_EN (1 << 28)
555 557
558/*
559 * PM4
560 */
561#define PACKET_TYPE0 0
562#define PACKET_TYPE1 1
563#define PACKET_TYPE2 2
564#define PACKET_TYPE3 3
565
566#define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3)
567#define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF)
568#define CP_PACKET0_GET_REG(h) (((h) & 0xFFFF) << 2)
569#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF)
570#define PACKET0(reg, n) ((PACKET_TYPE0 << 30) | \
571 (((reg) >> 2) & 0xFFFF) | \
572 ((n) & 0x3FFF) << 16)
573#define CP_PACKET2 0x80000000
574#define PACKET2_PAD_SHIFT 0
575#define PACKET2_PAD_MASK (0x3fffffff << 0)
576
577#define PACKET2(v) (CP_PACKET2 | REG_SET(PACKET2_PAD, (v)))
578
579#define PACKET3(op, n) ((PACKET_TYPE3 << 30) | \
580 (((op) & 0xFF) << 8) | \
581 ((n) & 0x3FFF) << 16)
582
583/* Packet 3 types */
584#define PACKET3_NOP 0x10
585#define PACKET3_SET_BASE 0x11
586#define PACKET3_CLEAR_STATE 0x12
587#define PACKET3_INDIRECT_BUFFER_SIZE 0x13
588#define PACKET3_DISPATCH_DIRECT 0x15
589#define PACKET3_DISPATCH_INDIRECT 0x16
590#define PACKET3_INDIRECT_BUFFER_END 0x17
591#define PACKET3_SET_PREDICATION 0x20
592#define PACKET3_REG_RMW 0x21
593#define PACKET3_COND_EXEC 0x22
594#define PACKET3_PRED_EXEC 0x23
595#define PACKET3_DRAW_INDIRECT 0x24
596#define PACKET3_DRAW_INDEX_INDIRECT 0x25
597#define PACKET3_INDEX_BASE 0x26
598#define PACKET3_DRAW_INDEX_2 0x27
599#define PACKET3_CONTEXT_CONTROL 0x28
600#define PACKET3_DRAW_INDEX_OFFSET 0x29
601#define PACKET3_INDEX_TYPE 0x2A
602#define PACKET3_DRAW_INDEX 0x2B
603#define PACKET3_DRAW_INDEX_AUTO 0x2D
604#define PACKET3_DRAW_INDEX_IMMD 0x2E
605#define PACKET3_NUM_INSTANCES 0x2F
606#define PACKET3_DRAW_INDEX_MULTI_AUTO 0x30
607#define PACKET3_STRMOUT_BUFFER_UPDATE 0x34
608#define PACKET3_DRAW_INDEX_OFFSET_2 0x35
609#define PACKET3_DRAW_INDEX_MULTI_ELEMENT 0x36
610#define PACKET3_MEM_SEMAPHORE 0x39
611#define PACKET3_MPEG_INDEX 0x3A
612#define PACKET3_WAIT_REG_MEM 0x3C
613#define PACKET3_MEM_WRITE 0x3D
614#define PACKET3_INDIRECT_BUFFER 0x32
615#define PACKET3_SURFACE_SYNC 0x43
616# define PACKET3_CB0_DEST_BASE_ENA (1 << 6)
617# define PACKET3_CB1_DEST_BASE_ENA (1 << 7)
618# define PACKET3_CB2_DEST_BASE_ENA (1 << 8)
619# define PACKET3_CB3_DEST_BASE_ENA (1 << 9)
620# define PACKET3_CB4_DEST_BASE_ENA (1 << 10)
621# define PACKET3_CB5_DEST_BASE_ENA (1 << 11)
622# define PACKET3_CB6_DEST_BASE_ENA (1 << 12)
623# define PACKET3_CB7_DEST_BASE_ENA (1 << 13)
624# define PACKET3_DB_DEST_BASE_ENA (1 << 14)
625# define PACKET3_CB8_DEST_BASE_ENA (1 << 15)
626# define PACKET3_CB9_DEST_BASE_ENA (1 << 16)
627# define PACKET3_CB10_DEST_BASE_ENA (1 << 17)
628# define PACKET3_CB11_DEST_BASE_ENA (1 << 17)
629# define PACKET3_FULL_CACHE_ENA (1 << 20)
630# define PACKET3_TC_ACTION_ENA (1 << 23)
631# define PACKET3_VC_ACTION_ENA (1 << 24)
632# define PACKET3_CB_ACTION_ENA (1 << 25)
633# define PACKET3_DB_ACTION_ENA (1 << 26)
634# define PACKET3_SH_ACTION_ENA (1 << 27)
635# define PACKET3_SMX_ACTION_ENA (1 << 28)
636#define PACKET3_ME_INITIALIZE 0x44
637#define PACKET3_ME_INITIALIZE_DEVICE_ID(x) ((x) << 16)
638#define PACKET3_COND_WRITE 0x45
639#define PACKET3_EVENT_WRITE 0x46
640#define PACKET3_EVENT_WRITE_EOP 0x47
641#define PACKET3_EVENT_WRITE_EOS 0x48
642#define PACKET3_PREAMBLE_CNTL 0x4A
643#define PACKET3_RB_OFFSET 0x4B
644#define PACKET3_ALU_PS_CONST_BUFFER_COPY 0x4C
645#define PACKET3_ALU_VS_CONST_BUFFER_COPY 0x4D
646#define PACKET3_ALU_PS_CONST_UPDATE 0x4E
647#define PACKET3_ALU_VS_CONST_UPDATE 0x4F
648#define PACKET3_ONE_REG_WRITE 0x57
649#define PACKET3_SET_CONFIG_REG 0x68
650#define PACKET3_SET_CONFIG_REG_START 0x00008000
651#define PACKET3_SET_CONFIG_REG_END 0x0000ac00
652#define PACKET3_SET_CONTEXT_REG 0x69
653#define PACKET3_SET_CONTEXT_REG_START 0x00028000
654#define PACKET3_SET_CONTEXT_REG_END 0x00029000
655#define PACKET3_SET_ALU_CONST 0x6A
656/* alu const buffers only; no reg file */
657#define PACKET3_SET_BOOL_CONST 0x6B
658#define PACKET3_SET_BOOL_CONST_START 0x0003a500
659#define PACKET3_SET_BOOL_CONST_END 0x0003a518
660#define PACKET3_SET_LOOP_CONST 0x6C
661#define PACKET3_SET_LOOP_CONST_START 0x0003a200
662#define PACKET3_SET_LOOP_CONST_END 0x0003a500
663#define PACKET3_SET_RESOURCE 0x6D
664#define PACKET3_SET_RESOURCE_START 0x00030000
665#define PACKET3_SET_RESOURCE_END 0x00038000
666#define PACKET3_SET_SAMPLER 0x6E
667#define PACKET3_SET_SAMPLER_START 0x0003c000
668#define PACKET3_SET_SAMPLER_END 0x0003c600
669#define PACKET3_SET_CTL_CONST 0x6F
670#define PACKET3_SET_CTL_CONST_START 0x0003cff0
671#define PACKET3_SET_CTL_CONST_END 0x0003ff0c
672#define PACKET3_SET_RESOURCE_OFFSET 0x70
673#define PACKET3_SET_ALU_CONST_VS 0x71
674#define PACKET3_SET_ALU_CONST_DI 0x72
675#define PACKET3_SET_CONTEXT_REG_INDIRECT 0x73
676#define PACKET3_SET_RESOURCE_INDIRECT 0x74
677#define PACKET3_SET_APPEND_CNT 0x75
678
679#define SQ_RESOURCE_CONSTANT_WORD7_0 0x3001c
680#define S__SQ_CONSTANT_TYPE(x) (((x) & 3) << 30)
681#define G__SQ_CONSTANT_TYPE(x) (((x) >> 30) & 3)
682#define SQ_TEX_VTX_INVALID_TEXTURE 0x0
683#define SQ_TEX_VTX_INVALID_BUFFER 0x1
684#define SQ_TEX_VTX_VALID_TEXTURE 0x2
685#define SQ_TEX_VTX_VALID_BUFFER 0x3
686
687#define SQ_CONST_MEM_BASE 0x8df8
688
689#define SQ_ESGS_RING_SIZE 0x8c44
690#define SQ_GSVS_RING_SIZE 0x8c4c
691#define SQ_ESTMP_RING_SIZE 0x8c54
692#define SQ_GSTMP_RING_SIZE 0x8c5c
693#define SQ_VSTMP_RING_SIZE 0x8c64
694#define SQ_PSTMP_RING_SIZE 0x8c6c
695#define SQ_LSTMP_RING_SIZE 0x8e14
696#define SQ_HSTMP_RING_SIZE 0x8e1c
697#define VGT_TF_RING_SIZE 0x8988
698
699#define SQ_ESGS_RING_ITEMSIZE 0x28900
700#define SQ_GSVS_RING_ITEMSIZE 0x28904
701#define SQ_ESTMP_RING_ITEMSIZE 0x28908
702#define SQ_GSTMP_RING_ITEMSIZE 0x2890c
703#define SQ_VSTMP_RING_ITEMSIZE 0x28910
704#define SQ_PSTMP_RING_ITEMSIZE 0x28914
705#define SQ_LSTMP_RING_ITEMSIZE 0x28830
706#define SQ_HSTMP_RING_ITEMSIZE 0x28834
707
708#define SQ_GS_VERT_ITEMSIZE 0x2891c
709#define SQ_GS_VERT_ITEMSIZE_1 0x28920
710#define SQ_GS_VERT_ITEMSIZE_2 0x28924
711#define SQ_GS_VERT_ITEMSIZE_3 0x28928
712#define SQ_GSVS_RING_OFFSET_1 0x2892c
713#define SQ_GSVS_RING_OFFSET_2 0x28930
714#define SQ_GSVS_RING_OFFSET_3 0x28934
715
716#define SQ_ALU_CONST_CACHE_PS_0 0x28940
717#define SQ_ALU_CONST_CACHE_PS_1 0x28944
718#define SQ_ALU_CONST_CACHE_PS_2 0x28948
719#define SQ_ALU_CONST_CACHE_PS_3 0x2894c
720#define SQ_ALU_CONST_CACHE_PS_4 0x28950
721#define SQ_ALU_CONST_CACHE_PS_5 0x28954
722#define SQ_ALU_CONST_CACHE_PS_6 0x28958
723#define SQ_ALU_CONST_CACHE_PS_7 0x2895c
724#define SQ_ALU_CONST_CACHE_PS_8 0x28960
725#define SQ_ALU_CONST_CACHE_PS_9 0x28964
726#define SQ_ALU_CONST_CACHE_PS_10 0x28968
727#define SQ_ALU_CONST_CACHE_PS_11 0x2896c
728#define SQ_ALU_CONST_CACHE_PS_12 0x28970
729#define SQ_ALU_CONST_CACHE_PS_13 0x28974
730#define SQ_ALU_CONST_CACHE_PS_14 0x28978
731#define SQ_ALU_CONST_CACHE_PS_15 0x2897c
732#define SQ_ALU_CONST_CACHE_VS_0 0x28980
733#define SQ_ALU_CONST_CACHE_VS_1 0x28984
734#define SQ_ALU_CONST_CACHE_VS_2 0x28988
735#define SQ_ALU_CONST_CACHE_VS_3 0x2898c
736#define SQ_ALU_CONST_CACHE_VS_4 0x28990
737#define SQ_ALU_CONST_CACHE_VS_5 0x28994
738#define SQ_ALU_CONST_CACHE_VS_6 0x28998
739#define SQ_ALU_CONST_CACHE_VS_7 0x2899c
740#define SQ_ALU_CONST_CACHE_VS_8 0x289a0
741#define SQ_ALU_CONST_CACHE_VS_9 0x289a4
742#define SQ_ALU_CONST_CACHE_VS_10 0x289a8
743#define SQ_ALU_CONST_CACHE_VS_11 0x289ac
744#define SQ_ALU_CONST_CACHE_VS_12 0x289b0
745#define SQ_ALU_CONST_CACHE_VS_13 0x289b4
746#define SQ_ALU_CONST_CACHE_VS_14 0x289b8
747#define SQ_ALU_CONST_CACHE_VS_15 0x289bc
748#define SQ_ALU_CONST_CACHE_GS_0 0x289c0
749#define SQ_ALU_CONST_CACHE_GS_1 0x289c4
750#define SQ_ALU_CONST_CACHE_GS_2 0x289c8
751#define SQ_ALU_CONST_CACHE_GS_3 0x289cc
752#define SQ_ALU_CONST_CACHE_GS_4 0x289d0
753#define SQ_ALU_CONST_CACHE_GS_5 0x289d4
754#define SQ_ALU_CONST_CACHE_GS_6 0x289d8
755#define SQ_ALU_CONST_CACHE_GS_7 0x289dc
756#define SQ_ALU_CONST_CACHE_GS_8 0x289e0
757#define SQ_ALU_CONST_CACHE_GS_9 0x289e4
758#define SQ_ALU_CONST_CACHE_GS_10 0x289e8
759#define SQ_ALU_CONST_CACHE_GS_11 0x289ec
760#define SQ_ALU_CONST_CACHE_GS_12 0x289f0
761#define SQ_ALU_CONST_CACHE_GS_13 0x289f4
762#define SQ_ALU_CONST_CACHE_GS_14 0x289f8
763#define SQ_ALU_CONST_CACHE_GS_15 0x289fc
764#define SQ_ALU_CONST_CACHE_HS_0 0x28f00
765#define SQ_ALU_CONST_CACHE_HS_1 0x28f04
766#define SQ_ALU_CONST_CACHE_HS_2 0x28f08
767#define SQ_ALU_CONST_CACHE_HS_3 0x28f0c
768#define SQ_ALU_CONST_CACHE_HS_4 0x28f10
769#define SQ_ALU_CONST_CACHE_HS_5 0x28f14
770#define SQ_ALU_CONST_CACHE_HS_6 0x28f18
771#define SQ_ALU_CONST_CACHE_HS_7 0x28f1c
772#define SQ_ALU_CONST_CACHE_HS_8 0x28f20
773#define SQ_ALU_CONST_CACHE_HS_9 0x28f24
774#define SQ_ALU_CONST_CACHE_HS_10 0x28f28
775#define SQ_ALU_CONST_CACHE_HS_11 0x28f2c
776#define SQ_ALU_CONST_CACHE_HS_12 0x28f30
777#define SQ_ALU_CONST_CACHE_HS_13 0x28f34
778#define SQ_ALU_CONST_CACHE_HS_14 0x28f38
779#define SQ_ALU_CONST_CACHE_HS_15 0x28f3c
780#define SQ_ALU_CONST_CACHE_LS_0 0x28f40
781#define SQ_ALU_CONST_CACHE_LS_1 0x28f44
782#define SQ_ALU_CONST_CACHE_LS_2 0x28f48
783#define SQ_ALU_CONST_CACHE_LS_3 0x28f4c
784#define SQ_ALU_CONST_CACHE_LS_4 0x28f50
785#define SQ_ALU_CONST_CACHE_LS_5 0x28f54
786#define SQ_ALU_CONST_CACHE_LS_6 0x28f58
787#define SQ_ALU_CONST_CACHE_LS_7 0x28f5c
788#define SQ_ALU_CONST_CACHE_LS_8 0x28f60
789#define SQ_ALU_CONST_CACHE_LS_9 0x28f64
790#define SQ_ALU_CONST_CACHE_LS_10 0x28f68
791#define SQ_ALU_CONST_CACHE_LS_11 0x28f6c
792#define SQ_ALU_CONST_CACHE_LS_12 0x28f70
793#define SQ_ALU_CONST_CACHE_LS_13 0x28f74
794#define SQ_ALU_CONST_CACHE_LS_14 0x28f78
795#define SQ_ALU_CONST_CACHE_LS_15 0x28f7c
796
797#define DB_DEPTH_CONTROL 0x28800
798#define DB_DEPTH_VIEW 0x28008
799#define DB_HTILE_DATA_BASE 0x28014
800#define DB_Z_INFO 0x28040
801# define Z_ARRAY_MODE(x) ((x) << 4)
802#define DB_STENCIL_INFO 0x28044
803#define DB_Z_READ_BASE 0x28048
804#define DB_STENCIL_READ_BASE 0x2804c
805#define DB_Z_WRITE_BASE 0x28050
806#define DB_STENCIL_WRITE_BASE 0x28054
807#define DB_DEPTH_SIZE 0x28058
808
809#define SQ_PGM_START_PS 0x28840
810#define SQ_PGM_START_VS 0x2885c
811#define SQ_PGM_START_GS 0x28874
812#define SQ_PGM_START_ES 0x2888c
813#define SQ_PGM_START_FS 0x288a4
814#define SQ_PGM_START_HS 0x288b8
815#define SQ_PGM_START_LS 0x288d0
816
817#define VGT_STRMOUT_CONFIG 0x28b94
818#define VGT_STRMOUT_BUFFER_CONFIG 0x28b98
819
820#define CB_TARGET_MASK 0x28238
821#define CB_SHADER_MASK 0x2823c
822
823#define GDS_ADDR_BASE 0x28720
824
825#define CB_IMMED0_BASE 0x28b9c
826#define CB_IMMED1_BASE 0x28ba0
827#define CB_IMMED2_BASE 0x28ba4
828#define CB_IMMED3_BASE 0x28ba8
829#define CB_IMMED4_BASE 0x28bac
830#define CB_IMMED5_BASE 0x28bb0
831#define CB_IMMED6_BASE 0x28bb4
832#define CB_IMMED7_BASE 0x28bb8
833#define CB_IMMED8_BASE 0x28bbc
834#define CB_IMMED9_BASE 0x28bc0
835#define CB_IMMED10_BASE 0x28bc4
836#define CB_IMMED11_BASE 0x28bc8
837
838/* all 12 CB blocks have these regs */
839#define CB_COLOR0_BASE 0x28c60
840#define CB_COLOR0_PITCH 0x28c64
841#define CB_COLOR0_SLICE 0x28c68
842#define CB_COLOR0_VIEW 0x28c6c
843#define CB_COLOR0_INFO 0x28c70
844# define CB_ARRAY_MODE(x) ((x) << 8)
845# define ARRAY_LINEAR_GENERAL 0
846# define ARRAY_LINEAR_ALIGNED 1
847# define ARRAY_1D_TILED_THIN1 2
848# define ARRAY_2D_TILED_THIN1 4
849#define CB_COLOR0_ATTRIB 0x28c74
850#define CB_COLOR0_DIM 0x28c78
851/* only CB0-7 blocks have these regs */
852#define CB_COLOR0_CMASK 0x28c7c
853#define CB_COLOR0_CMASK_SLICE 0x28c80
854#define CB_COLOR0_FMASK 0x28c84
855#define CB_COLOR0_FMASK_SLICE 0x28c88
856#define CB_COLOR0_CLEAR_WORD0 0x28c8c
857#define CB_COLOR0_CLEAR_WORD1 0x28c90
858#define CB_COLOR0_CLEAR_WORD2 0x28c94
859#define CB_COLOR0_CLEAR_WORD3 0x28c98
860
861#define CB_COLOR1_BASE 0x28c9c
862#define CB_COLOR2_BASE 0x28cd8
863#define CB_COLOR3_BASE 0x28d14
864#define CB_COLOR4_BASE 0x28d50
865#define CB_COLOR5_BASE 0x28d8c
866#define CB_COLOR6_BASE 0x28dc8
867#define CB_COLOR7_BASE 0x28e04
868#define CB_COLOR8_BASE 0x28e40
869#define CB_COLOR9_BASE 0x28e5c
870#define CB_COLOR10_BASE 0x28e78
871#define CB_COLOR11_BASE 0x28e94
872
873#define CB_COLOR1_PITCH 0x28ca0
874#define CB_COLOR2_PITCH 0x28cdc
875#define CB_COLOR3_PITCH 0x28d18
876#define CB_COLOR4_PITCH 0x28d54
877#define CB_COLOR5_PITCH 0x28d90
878#define CB_COLOR6_PITCH 0x28dcc
879#define CB_COLOR7_PITCH 0x28e08
880#define CB_COLOR8_PITCH 0x28e44
881#define CB_COLOR9_PITCH 0x28e60
882#define CB_COLOR10_PITCH 0x28e7c
883#define CB_COLOR11_PITCH 0x28e98
884
885#define CB_COLOR1_SLICE 0x28ca4
886#define CB_COLOR2_SLICE 0x28ce0
887#define CB_COLOR3_SLICE 0x28d1c
888#define CB_COLOR4_SLICE 0x28d58
889#define CB_COLOR5_SLICE 0x28d94
890#define CB_COLOR6_SLICE 0x28dd0
891#define CB_COLOR7_SLICE 0x28e0c
892#define CB_COLOR8_SLICE 0x28e48
893#define CB_COLOR9_SLICE 0x28e64
894#define CB_COLOR10_SLICE 0x28e80
895#define CB_COLOR11_SLICE 0x28e9c
896
897#define CB_COLOR1_VIEW 0x28ca8
898#define CB_COLOR2_VIEW 0x28ce4
899#define CB_COLOR3_VIEW 0x28d20
900#define CB_COLOR4_VIEW 0x28d5c
901#define CB_COLOR5_VIEW 0x28d98
902#define CB_COLOR6_VIEW 0x28dd4
903#define CB_COLOR7_VIEW 0x28e10
904#define CB_COLOR8_VIEW 0x28e4c
905#define CB_COLOR9_VIEW 0x28e68
906#define CB_COLOR10_VIEW 0x28e84
907#define CB_COLOR11_VIEW 0x28ea0
908
909#define CB_COLOR1_INFO 0x28cac
910#define CB_COLOR2_INFO 0x28ce8
911#define CB_COLOR3_INFO 0x28d24
912#define CB_COLOR4_INFO 0x28d60
913#define CB_COLOR5_INFO 0x28d9c
914#define CB_COLOR6_INFO 0x28dd8
915#define CB_COLOR7_INFO 0x28e14
916#define CB_COLOR8_INFO 0x28e50
917#define CB_COLOR9_INFO 0x28e6c
918#define CB_COLOR10_INFO 0x28e88
919#define CB_COLOR11_INFO 0x28ea4
920
921#define CB_COLOR1_ATTRIB 0x28cb0
922#define CB_COLOR2_ATTRIB 0x28cec
923#define CB_COLOR3_ATTRIB 0x28d28
924#define CB_COLOR4_ATTRIB 0x28d64
925#define CB_COLOR5_ATTRIB 0x28da0
926#define CB_COLOR6_ATTRIB 0x28ddc
927#define CB_COLOR7_ATTRIB 0x28e18
928#define CB_COLOR8_ATTRIB 0x28e54
929#define CB_COLOR9_ATTRIB 0x28e70
930#define CB_COLOR10_ATTRIB 0x28e8c
931#define CB_COLOR11_ATTRIB 0x28ea8
932
933#define CB_COLOR1_DIM 0x28cb4
934#define CB_COLOR2_DIM 0x28cf0
935#define CB_COLOR3_DIM 0x28d2c
936#define CB_COLOR4_DIM 0x28d68
937#define CB_COLOR5_DIM 0x28da4
938#define CB_COLOR6_DIM 0x28de0
939#define CB_COLOR7_DIM 0x28e1c
940#define CB_COLOR8_DIM 0x28e58
941#define CB_COLOR9_DIM 0x28e74
942#define CB_COLOR10_DIM 0x28e90
943#define CB_COLOR11_DIM 0x28eac
944
945#define CB_COLOR1_CMASK 0x28cb8
946#define CB_COLOR2_CMASK 0x28cf4
947#define CB_COLOR3_CMASK 0x28d30
948#define CB_COLOR4_CMASK 0x28d6c
949#define CB_COLOR5_CMASK 0x28da8
950#define CB_COLOR6_CMASK 0x28de4
951#define CB_COLOR7_CMASK 0x28e20
952
953#define CB_COLOR1_CMASK_SLICE 0x28cbc
954#define CB_COLOR2_CMASK_SLICE 0x28cf8
955#define CB_COLOR3_CMASK_SLICE 0x28d34
956#define CB_COLOR4_CMASK_SLICE 0x28d70
957#define CB_COLOR5_CMASK_SLICE 0x28dac
958#define CB_COLOR6_CMASK_SLICE 0x28de8
959#define CB_COLOR7_CMASK_SLICE 0x28e24
960
961#define CB_COLOR1_FMASK 0x28cc0
962#define CB_COLOR2_FMASK 0x28cfc
963#define CB_COLOR3_FMASK 0x28d38
964#define CB_COLOR4_FMASK 0x28d74
965#define CB_COLOR5_FMASK 0x28db0
966#define CB_COLOR6_FMASK 0x28dec
967#define CB_COLOR7_FMASK 0x28e28
968
969#define CB_COLOR1_FMASK_SLICE 0x28cc4
970#define CB_COLOR2_FMASK_SLICE 0x28d00
971#define CB_COLOR3_FMASK_SLICE 0x28d3c
972#define CB_COLOR4_FMASK_SLICE 0x28d78
973#define CB_COLOR5_FMASK_SLICE 0x28db4
974#define CB_COLOR6_FMASK_SLICE 0x28df0
975#define CB_COLOR7_FMASK_SLICE 0x28e2c
976
977#define CB_COLOR1_CLEAR_WORD0 0x28cc8
978#define CB_COLOR2_CLEAR_WORD0 0x28d04
979#define CB_COLOR3_CLEAR_WORD0 0x28d40
980#define CB_COLOR4_CLEAR_WORD0 0x28d7c
981#define CB_COLOR5_CLEAR_WORD0 0x28db8
982#define CB_COLOR6_CLEAR_WORD0 0x28df4
983#define CB_COLOR7_CLEAR_WORD0 0x28e30
984
985#define CB_COLOR1_CLEAR_WORD1 0x28ccc
986#define CB_COLOR2_CLEAR_WORD1 0x28d08
987#define CB_COLOR3_CLEAR_WORD1 0x28d44
988#define CB_COLOR4_CLEAR_WORD1 0x28d80
989#define CB_COLOR5_CLEAR_WORD1 0x28dbc
990#define CB_COLOR6_CLEAR_WORD1 0x28df8
991#define CB_COLOR7_CLEAR_WORD1 0x28e34
992
993#define CB_COLOR1_CLEAR_WORD2 0x28cd0
994#define CB_COLOR2_CLEAR_WORD2 0x28d0c
995#define CB_COLOR3_CLEAR_WORD2 0x28d48
996#define CB_COLOR4_CLEAR_WORD2 0x28d84
997#define CB_COLOR5_CLEAR_WORD2 0x28dc0
998#define CB_COLOR6_CLEAR_WORD2 0x28dfc
999#define CB_COLOR7_CLEAR_WORD2 0x28e38
1000
1001#define CB_COLOR1_CLEAR_WORD3 0x28cd4
1002#define CB_COLOR2_CLEAR_WORD3 0x28d10
1003#define CB_COLOR3_CLEAR_WORD3 0x28d4c
1004#define CB_COLOR4_CLEAR_WORD3 0x28d88
1005#define CB_COLOR5_CLEAR_WORD3 0x28dc4
1006#define CB_COLOR6_CLEAR_WORD3 0x28e00
1007#define CB_COLOR7_CLEAR_WORD3 0x28e3c
1008
1009#define SQ_TEX_RESOURCE_WORD0_0 0x30000
1010#define SQ_TEX_RESOURCE_WORD1_0 0x30004
1011# define TEX_ARRAY_MODE(x) ((x) << 28)
1012#define SQ_TEX_RESOURCE_WORD2_0 0x30008
1013#define SQ_TEX_RESOURCE_WORD3_0 0x3000C
1014#define SQ_TEX_RESOURCE_WORD4_0 0x30010
1015#define SQ_TEX_RESOURCE_WORD5_0 0x30014
1016#define SQ_TEX_RESOURCE_WORD6_0 0x30018
1017#define SQ_TEX_RESOURCE_WORD7_0 0x3001c
1018
1019
556#endif 1020#endif
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index cc004b05d63e..cf89aa2eb28c 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -162,6 +162,11 @@ void r100_pm_init_profile(struct radeon_device *rdev)
162 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 0; 162 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 0;
163 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; 163 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
164 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; 164 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
165 /* mid sh */
166 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 0;
167 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 0;
168 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
169 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0;
165 /* high sh */ 170 /* high sh */
166 rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 0; 171 rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 0;
167 rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 172 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)
172 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 177 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
173 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; 178 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
174 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; 179 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
180 /* mid mh */
181 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 0;
182 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
183 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
184 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0;
175 /* high mh */ 185 /* high mh */
176 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 0; 186 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 0;
177 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 187 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c
index 4415a5ee5871..e6c89142bb4d 100644
--- a/drivers/gpu/drm/radeon/r420.c
+++ b/drivers/gpu/drm/radeon/r420.c
@@ -45,9 +45,14 @@ void r420_pm_init_profile(struct radeon_device *rdev)
45 rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0; 45 rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0;
46 /* low sh */ 46 /* low sh */
47 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 0; 47 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 0;
48 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 1; 48 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 0;
49 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; 49 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
50 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; 50 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
51 /* mid sh */
52 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 0;
53 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 1;
54 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
55 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0;
51 /* high sh */ 56 /* high sh */
52 rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 0; 57 rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 0;
53 rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 58 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)
58 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 63 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
59 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; 64 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
60 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; 65 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
66 /* mid mh */
67 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 0;
68 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
69 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
70 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0;
61 /* high mh */ 71 /* high mh */
62 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 0; 72 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 0;
63 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 73 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index 44e96a2ae25a..0e91871f45be 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -291,6 +291,11 @@ void rs780_pm_init_profile(struct radeon_device *rdev)
291 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 0; 291 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 0;
292 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; 292 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
293 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; 293 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
294 /* mid sh */
295 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 0;
296 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 0;
297 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
298 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0;
294 /* high sh */ 299 /* high sh */
295 rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 0; 300 rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 0;
296 rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 1; 301 rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 1;
@@ -301,6 +306,11 @@ void rs780_pm_init_profile(struct radeon_device *rdev)
301 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 0; 306 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 0;
302 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; 307 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
303 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; 308 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
309 /* mid mh */
310 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 0;
311 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = 0;
312 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
313 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0;
304 /* high mh */ 314 /* high mh */
305 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 0; 315 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 0;
306 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 1; 316 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 1;
@@ -317,6 +327,11 @@ void rs780_pm_init_profile(struct radeon_device *rdev)
317 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 1; 327 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 1;
318 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; 328 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
319 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; 329 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
330 /* mid sh */
331 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 1;
332 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 1;
333 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
334 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0;
320 /* high sh */ 335 /* high sh */
321 rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 1; 336 rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 1;
322 rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 2; 337 rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 2;
@@ -327,6 +342,11 @@ void rs780_pm_init_profile(struct radeon_device *rdev)
327 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 1; 342 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 1;
328 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; 343 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
329 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; 344 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
345 /* mid mh */
346 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 1;
347 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = 1;
348 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
349 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0;
330 /* high mh */ 350 /* high mh */
331 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 1; 351 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 1;
332 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 2; 352 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 2;
@@ -343,6 +363,11 @@ void rs780_pm_init_profile(struct radeon_device *rdev)
343 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 2; 363 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 2;
344 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; 364 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
345 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; 365 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
366 /* mid sh */
367 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 2;
368 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 2;
369 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
370 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0;
346 /* high sh */ 371 /* high sh */
347 rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 2; 372 rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 2;
348 rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 3; 373 rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 3;
@@ -353,6 +378,11 @@ void rs780_pm_init_profile(struct radeon_device *rdev)
353 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 0; 378 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 0;
354 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; 379 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
355 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; 380 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
381 /* mid mh */
382 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 2;
383 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = 0;
384 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
385 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0;
356 /* high mh */ 386 /* high mh */
357 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 2; 387 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 2;
358 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 3; 388 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 3;
@@ -375,6 +405,11 @@ void r600_pm_init_profile(struct radeon_device *rdev)
375 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 405 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
376 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; 406 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
377 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; 407 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
408 /* mid sh */
409 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
410 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
411 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
412 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0;
378 /* high sh */ 413 /* high sh */
379 rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; 414 rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
380 rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 415 rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
@@ -385,6 +420,11 @@ void r600_pm_init_profile(struct radeon_device *rdev)
385 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 420 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
386 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; 421 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
387 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; 422 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
423 /* mid mh */
424 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
425 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
426 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
427 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0;
388 /* high mh */ 428 /* high mh */
389 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; 429 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
390 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 430 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
@@ -401,7 +441,12 @@ void r600_pm_init_profile(struct radeon_device *rdev)
401 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 1; 441 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 1;
402 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 1; 442 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 1;
403 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; 443 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
404 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 1; 444 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
445 /* mid sh */
446 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 1;
447 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 1;
448 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
449 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1;
405 /* high sh */ 450 /* high sh */
406 rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 1; 451 rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 1;
407 rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 1; 452 rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 1;
@@ -411,7 +456,12 @@ void r600_pm_init_profile(struct radeon_device *rdev)
411 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = 2; 456 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = 2;
412 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 2; 457 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 2;
413 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; 458 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
414 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 1; 459 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
460 /* low mh */
461 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 2;
462 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = 2;
463 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
464 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1;
415 /* high mh */ 465 /* high mh */
416 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 2; 466 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 2;
417 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 2; 467 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 2;
@@ -430,14 +480,30 @@ void r600_pm_init_profile(struct radeon_device *rdev)
430 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 480 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx =
431 r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0); 481 r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
432 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; 482 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
433 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 1; 483 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
434 } else { 484 } else {
435 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 485 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx =
436 r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); 486 r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
437 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 487 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx =
438 r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); 488 r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
439 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; 489 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
440 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 1; 490 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
491 }
492 /* mid sh */
493 if (rdev->flags & RADEON_IS_MOBILITY) {
494 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx =
495 r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
496 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx =
497 r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
498 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
499 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1;
500 } else {
501 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx =
502 r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
503 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx =
504 r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
505 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
506 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1;
441 } 507 }
442 /* high sh */ 508 /* high sh */
443 rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 509 rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx =
@@ -453,14 +519,30 @@ void r600_pm_init_profile(struct radeon_device *rdev)
453 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 519 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx =
454 r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1); 520 r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1);
455 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; 521 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
456 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 2; 522 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
457 } else { 523 } else {
458 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = 524 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx =
459 r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1); 525 r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
460 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 526 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx =
461 r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1); 527 r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
462 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; 528 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
463 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 1; 529 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
530 }
531 /* mid mh */
532 if (rdev->flags & RADEON_IS_MOBILITY) {
533 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx =
534 r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1);
535 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx =
536 r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1);
537 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
538 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1;
539 } else {
540 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx =
541 r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
542 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx =
543 r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
544 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
545 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1;
464 } 546 }
465 /* high mh */ 547 /* high mh */
466 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 548 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx =
@@ -475,7 +557,18 @@ void r600_pm_init_profile(struct radeon_device *rdev)
475 557
476void r600_pm_misc(struct radeon_device *rdev) 558void r600_pm_misc(struct radeon_device *rdev)
477{ 559{
560 int req_ps_idx = rdev->pm.requested_power_state_index;
561 int req_cm_idx = rdev->pm.requested_clock_mode_index;
562 struct radeon_power_state *ps = &rdev->pm.power_state[req_ps_idx];
563 struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage;
478 564
565 if ((voltage->type == VOLTAGE_SW) && voltage->voltage) {
566 if (voltage->voltage != rdev->pm.current_vddc) {
567 radeon_atom_set_voltage(rdev, voltage->voltage);
568 rdev->pm.current_vddc = voltage->voltage;
569 DRM_DEBUG("Setting: v: %d\n", voltage->voltage);
570 }
571 }
479} 572}
480 573
481bool r600_gui_idle(struct radeon_device *rdev) 574bool r600_gui_idle(struct radeon_device *rdev)
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 66a37fb75839..8e1d44ca26ec 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -176,6 +176,7 @@ void radeon_pm_suspend(struct radeon_device *rdev);
176void radeon_pm_resume(struct radeon_device *rdev); 176void radeon_pm_resume(struct radeon_device *rdev);
177void radeon_combios_get_power_modes(struct radeon_device *rdev); 177void radeon_combios_get_power_modes(struct radeon_device *rdev);
178void radeon_atombios_get_power_modes(struct radeon_device *rdev); 178void radeon_atombios_get_power_modes(struct radeon_device *rdev);
179void radeon_atom_set_voltage(struct radeon_device *rdev, u16 level);
179 180
180/* 181/*
181 * Fences. 182 * Fences.
@@ -576,6 +577,7 @@ typedef int (*radeon_packet3_check_t)(struct radeon_cs_parser *p,
576 */ 577 */
577int radeon_agp_init(struct radeon_device *rdev); 578int radeon_agp_init(struct radeon_device *rdev);
578void radeon_agp_resume(struct radeon_device *rdev); 579void radeon_agp_resume(struct radeon_device *rdev);
580void radeon_agp_suspend(struct radeon_device *rdev);
579void radeon_agp_fini(struct radeon_device *rdev); 581void radeon_agp_fini(struct radeon_device *rdev);
580 582
581 583
@@ -646,15 +648,18 @@ enum radeon_pm_profile_type {
646 PM_PROFILE_DEFAULT, 648 PM_PROFILE_DEFAULT,
647 PM_PROFILE_AUTO, 649 PM_PROFILE_AUTO,
648 PM_PROFILE_LOW, 650 PM_PROFILE_LOW,
651 PM_PROFILE_MID,
649 PM_PROFILE_HIGH, 652 PM_PROFILE_HIGH,
650}; 653};
651 654
652#define PM_PROFILE_DEFAULT_IDX 0 655#define PM_PROFILE_DEFAULT_IDX 0
653#define PM_PROFILE_LOW_SH_IDX 1 656#define PM_PROFILE_LOW_SH_IDX 1
654#define PM_PROFILE_HIGH_SH_IDX 2 657#define PM_PROFILE_MID_SH_IDX 2
655#define PM_PROFILE_LOW_MH_IDX 3 658#define PM_PROFILE_HIGH_SH_IDX 3
656#define PM_PROFILE_HIGH_MH_IDX 4 659#define PM_PROFILE_LOW_MH_IDX 4
657#define PM_PROFILE_MAX 5 660#define PM_PROFILE_MID_MH_IDX 5
661#define PM_PROFILE_HIGH_MH_IDX 6
662#define PM_PROFILE_MAX 7
658 663
659struct radeon_pm_profile { 664struct radeon_pm_profile {
660 int dpms_off_ps_idx; 665 int dpms_off_ps_idx;
@@ -743,6 +748,7 @@ struct radeon_pm {
743 int default_power_state_index; 748 int default_power_state_index;
744 u32 current_sclk; 749 u32 current_sclk;
745 u32 current_mclk; 750 u32 current_mclk;
751 u32 current_vddc;
746 struct radeon_i2c_chan *i2c_bus; 752 struct radeon_i2c_chan *i2c_bus;
747 /* selected pm method */ 753 /* selected pm method */
748 enum radeon_pm_method pm_method; 754 enum radeon_pm_method pm_method;
diff --git a/drivers/gpu/drm/radeon/radeon_agp.c b/drivers/gpu/drm/radeon/radeon_agp.c
index 28e473f1f56f..f40dfb77f9b1 100644
--- a/drivers/gpu/drm/radeon/radeon_agp.c
+++ b/drivers/gpu/drm/radeon/radeon_agp.c
@@ -270,3 +270,8 @@ void radeon_agp_fini(struct radeon_device *rdev)
270 } 270 }
271#endif 271#endif
272} 272}
273
274void radeon_agp_suspend(struct radeon_device *rdev)
275{
276 radeon_agp_fini(rdev);
277}
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
index e57df08d4aeb..87f7e2cc52d4 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.c
+++ b/drivers/gpu/drm/radeon/radeon_asic.c
@@ -724,8 +724,8 @@ static struct radeon_asic evergreen_asic = {
724 .irq_set = &evergreen_irq_set, 724 .irq_set = &evergreen_irq_set,
725 .irq_process = &evergreen_irq_process, 725 .irq_process = &evergreen_irq_process,
726 .get_vblank_counter = &evergreen_get_vblank_counter, 726 .get_vblank_counter = &evergreen_get_vblank_counter,
727 .fence_ring_emit = NULL, 727 .fence_ring_emit = &r600_fence_ring_emit,
728 .cs_parse = NULL, 728 .cs_parse = &evergreen_cs_parse,
729 .copy_blit = NULL, 729 .copy_blit = NULL,
730 .copy_dma = NULL, 730 .copy_dma = NULL,
731 .copy = NULL, 731 .copy = NULL,
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h
index 5c40a3dfaca2..c0bbaa64157a 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.h
+++ b/drivers/gpu/drm/radeon/radeon_asic.h
@@ -314,6 +314,7 @@ void evergreen_hpd_set_polarity(struct radeon_device *rdev,
314u32 evergreen_get_vblank_counter(struct radeon_device *rdev, int crtc); 314u32 evergreen_get_vblank_counter(struct radeon_device *rdev, int crtc);
315int evergreen_irq_set(struct radeon_device *rdev); 315int evergreen_irq_set(struct radeon_device *rdev);
316int evergreen_irq_process(struct radeon_device *rdev); 316int evergreen_irq_process(struct radeon_device *rdev);
317extern int evergreen_cs_parse(struct radeon_cs_parser *p);
317extern void evergreen_pm_misc(struct radeon_device *rdev); 318extern void evergreen_pm_misc(struct radeon_device *rdev);
318extern void evergreen_pm_prepare(struct radeon_device *rdev); 319extern void evergreen_pm_prepare(struct radeon_device *rdev);
319extern void evergreen_pm_finish(struct radeon_device *rdev); 320extern void evergreen_pm_finish(struct radeon_device *rdev);
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index 6e733fdc3349..99bd8a9c56b3 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -680,11 +680,19 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
680 uint8_t dac; 680 uint8_t dac;
681 union atom_supported_devices *supported_devices; 681 union atom_supported_devices *supported_devices;
682 int i, j, max_device; 682 int i, j, max_device;
683 struct bios_connector bios_connectors[ATOM_MAX_SUPPORTED_DEVICE]; 683 struct bios_connector *bios_connectors;
684 size_t bc_size = sizeof(*bios_connectors) * ATOM_MAX_SUPPORTED_DEVICE;
684 685
685 if (!atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset)) 686 bios_connectors = kzalloc(bc_size, GFP_KERNEL);
687 if (!bios_connectors)
686 return false; 688 return false;
687 689
690 if (!atom_parse_data_header(ctx, index, &size, &frev, &crev,
691 &data_offset)) {
692 kfree(bios_connectors);
693 return false;
694 }
695
688 supported_devices = 696 supported_devices =
689 (union atom_supported_devices *)(ctx->bios + data_offset); 697 (union atom_supported_devices *)(ctx->bios + data_offset);
690 698
@@ -851,6 +859,7 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
851 859
852 radeon_link_encoder_connector(dev); 860 radeon_link_encoder_connector(dev);
853 861
862 kfree(bios_connectors);
854 return true; 863 return true;
855} 864}
856 865
@@ -1529,7 +1538,8 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
1529 rdev->pm.power_state[state_index].pcie_lanes = 1538 rdev->pm.power_state[state_index].pcie_lanes =
1530 power_info->info.asPowerPlayInfo[i].ucNumPciELanes; 1539 power_info->info.asPowerPlayInfo[i].ucNumPciELanes;
1531 misc = le32_to_cpu(power_info->info.asPowerPlayInfo[i].ulMiscInfo); 1540 misc = le32_to_cpu(power_info->info.asPowerPlayInfo[i].ulMiscInfo);
1532 if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) { 1541 if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) ||
1542 (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) {
1533 rdev->pm.power_state[state_index].clock_info[0].voltage.type = 1543 rdev->pm.power_state[state_index].clock_info[0].voltage.type =
1534 VOLTAGE_GPIO; 1544 VOLTAGE_GPIO;
1535 rdev->pm.power_state[state_index].clock_info[0].voltage.gpio = 1545 rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
@@ -1596,7 +1606,8 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
1596 power_info->info_2.asPowerPlayInfo[i].ucNumPciELanes; 1606 power_info->info_2.asPowerPlayInfo[i].ucNumPciELanes;
1597 misc = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo); 1607 misc = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo);
1598 misc2 = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo2); 1608 misc2 = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo2);
1599 if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) { 1609 if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) ||
1610 (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) {
1600 rdev->pm.power_state[state_index].clock_info[0].voltage.type = 1611 rdev->pm.power_state[state_index].clock_info[0].voltage.type =
1601 VOLTAGE_GPIO; 1612 VOLTAGE_GPIO;
1602 rdev->pm.power_state[state_index].clock_info[0].voltage.gpio = 1613 rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
@@ -1670,7 +1681,8 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
1670 power_info->info_3.asPowerPlayInfo[i].ucNumPciELanes; 1681 power_info->info_3.asPowerPlayInfo[i].ucNumPciELanes;
1671 misc = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo); 1682 misc = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo);
1672 misc2 = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo2); 1683 misc2 = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo2);
1673 if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) { 1684 if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) ||
1685 (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) {
1674 rdev->pm.power_state[state_index].clock_info[0].voltage.type = 1686 rdev->pm.power_state[state_index].clock_info[0].voltage.type =
1675 VOLTAGE_GPIO; 1687 VOLTAGE_GPIO;
1676 rdev->pm.power_state[state_index].clock_info[0].voltage.gpio = 1688 rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
@@ -1746,9 +1758,22 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
1746 rdev->pm.power_state[state_index].misc2 = 0; 1758 rdev->pm.power_state[state_index].misc2 = 0;
1747 } 1759 }
1748 } else { 1760 } else {
1761 int fw_index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
1762 uint8_t fw_frev, fw_crev;
1763 uint16_t fw_data_offset, vddc = 0;
1764 union firmware_info *firmware_info;
1765 ATOM_PPLIB_THERMALCONTROLLER *controller = &power_info->info_4.sThermalController;
1766
1767 if (atom_parse_data_header(mode_info->atom_context, fw_index, NULL,
1768 &fw_frev, &fw_crev, &fw_data_offset)) {
1769 firmware_info =
1770 (union firmware_info *)(mode_info->atom_context->bios +
1771 fw_data_offset);
1772 vddc = firmware_info->info_14.usBootUpVDDCVoltage;
1773 }
1774
1749 /* add the i2c bus for thermal/fan chip */ 1775 /* add the i2c bus for thermal/fan chip */
1750 /* no support for internal controller yet */ 1776 /* no support for internal controller yet */
1751 ATOM_PPLIB_THERMALCONTROLLER *controller = &power_info->info_4.sThermalController;
1752 if (controller->ucType > 0) { 1777 if (controller->ucType > 0) {
1753 if ((controller->ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) || 1778 if ((controller->ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) ||
1754 (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV770) || 1779 (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV770) ||
@@ -1808,10 +1833,7 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
1808 /* skip invalid modes */ 1833 /* skip invalid modes */
1809 if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0) 1834 if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0)
1810 continue; 1835 continue;
1811 rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type = 1836 /* voltage works differently on IGPs */
1812 VOLTAGE_SW;
1813 rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage =
1814 clock_info->usVDDC;
1815 mode_index++; 1837 mode_index++;
1816 } else if (ASIC_IS_DCE4(rdev)) { 1838 } else if (ASIC_IS_DCE4(rdev)) {
1817 struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO *clock_info = 1839 struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO *clock_info =
@@ -1895,6 +1917,16 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
1895 rdev->pm.default_power_state_index = state_index; 1917 rdev->pm.default_power_state_index = state_index;
1896 rdev->pm.power_state[state_index].default_clock_mode = 1918 rdev->pm.power_state[state_index].default_clock_mode =
1897 &rdev->pm.power_state[state_index].clock_info[mode_index - 1]; 1919 &rdev->pm.power_state[state_index].clock_info[mode_index - 1];
1920 /* patch the table values with the default slck/mclk from firmware info */
1921 for (j = 0; j < mode_index; j++) {
1922 rdev->pm.power_state[state_index].clock_info[j].mclk =
1923 rdev->clock.default_mclk;
1924 rdev->pm.power_state[state_index].clock_info[j].sclk =
1925 rdev->clock.default_sclk;
1926 if (vddc)
1927 rdev->pm.power_state[state_index].clock_info[j].voltage.voltage =
1928 vddc;
1929 }
1898 } 1930 }
1899 state_index++; 1931 state_index++;
1900 } 1932 }
@@ -1934,6 +1966,7 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
1934 1966
1935 rdev->pm.current_power_state_index = rdev->pm.default_power_state_index; 1967 rdev->pm.current_power_state_index = rdev->pm.default_power_state_index;
1936 rdev->pm.current_clock_mode_index = 0; 1968 rdev->pm.current_clock_mode_index = 0;
1969 rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
1937} 1970}
1938 1971
1939void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable) 1972void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable)
@@ -1989,6 +2022,42 @@ void radeon_atom_set_memory_clock(struct radeon_device *rdev,
1989 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 2022 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
1990} 2023}
1991 2024
2025union set_voltage {
2026 struct _SET_VOLTAGE_PS_ALLOCATION alloc;
2027 struct _SET_VOLTAGE_PARAMETERS v1;
2028 struct _SET_VOLTAGE_PARAMETERS_V2 v2;
2029};
2030
2031void radeon_atom_set_voltage(struct radeon_device *rdev, u16 level)
2032{
2033 union set_voltage args;
2034 int index = GetIndexIntoMasterTable(COMMAND, SetVoltage);
2035 u8 frev, crev, volt_index = level;
2036
2037 if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
2038 return;
2039
2040 switch (crev) {
2041 case 1:
2042 args.v1.ucVoltageType = SET_VOLTAGE_TYPE_ASIC_VDDC;
2043 args.v1.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_ALL_SOURCE;
2044 args.v1.ucVoltageIndex = volt_index;
2045 break;
2046 case 2:
2047 args.v2.ucVoltageType = SET_VOLTAGE_TYPE_ASIC_VDDC;
2048 args.v2.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_SET_VOLTAGE;
2049 args.v2.usVoltageLevel = cpu_to_le16(level);
2050 break;
2051 default:
2052 DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
2053 return;
2054 }
2055
2056 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
2057}
2058
2059
2060
1992void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev) 2061void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev)
1993{ 2062{
1994 struct radeon_device *rdev = dev->dev_private; 2063 struct radeon_device *rdev = dev->dev_private;
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c
index 7b5e10d3e9c9..1bee2f9e24a5 100644
--- a/drivers/gpu/drm/radeon/radeon_combios.c
+++ b/drivers/gpu/drm/radeon/radeon_combios.c
@@ -2026,6 +2026,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
2026 combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC); 2026 combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC);
2027 break; 2027 break;
2028 default: 2028 default:
2029 ddc_i2c.valid = false;
2029 break; 2030 break;
2030 } 2031 }
2031 2032
@@ -2339,6 +2340,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
2339 if (RBIOS8(tv_info + 6) == 'T') { 2340 if (RBIOS8(tv_info + 6) == 'T') {
2340 if (radeon_apply_legacy_tv_quirks(dev)) { 2341 if (radeon_apply_legacy_tv_quirks(dev)) {
2341 hpd.hpd = RADEON_HPD_NONE; 2342 hpd.hpd = RADEON_HPD_NONE;
2343 ddc_i2c.valid = false;
2342 radeon_add_legacy_encoder(dev, 2344 radeon_add_legacy_encoder(dev,
2343 radeon_get_encoder_id 2345 radeon_get_encoder_id
2344 (dev, 2346 (dev,
@@ -2454,7 +2456,12 @@ default_mode:
2454 rdev->pm.power_state[state_index].clock_info[0].mclk = rdev->clock.default_mclk; 2456 rdev->pm.power_state[state_index].clock_info[0].mclk = rdev->clock.default_mclk;
2455 rdev->pm.power_state[state_index].clock_info[0].sclk = rdev->clock.default_sclk; 2457 rdev->pm.power_state[state_index].clock_info[0].sclk = rdev->clock.default_sclk;
2456 rdev->pm.power_state[state_index].default_clock_mode = &rdev->pm.power_state[state_index].clock_info[0]; 2458 rdev->pm.power_state[state_index].default_clock_mode = &rdev->pm.power_state[state_index].clock_info[0];
2457 rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE; 2459 if ((state_index > 0) &&
2460 (rdev->pm.power_state[0].clock_info[0].voltage.type == VOLTAGE_GPIO))
2461 rdev->pm.power_state[state_index].clock_info[0].voltage =
2462 rdev->pm.power_state[0].clock_info[0].voltage;
2463 else
2464 rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
2458 rdev->pm.power_state[state_index].pcie_lanes = 16; 2465 rdev->pm.power_state[state_index].pcie_lanes = 16;
2459 rdev->pm.power_state[state_index].flags = 0; 2466 rdev->pm.power_state[state_index].flags = 0;
2460 rdev->pm.default_power_state_index = state_index; 2467 rdev->pm.default_power_state_index = state_index;
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index a20b612ffe75..f10faed21567 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -546,8 +546,10 @@ static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero
546 /* don't suspend or resume card normally */ 546 /* don't suspend or resume card normally */
547 rdev->powered_down = false; 547 rdev->powered_down = false;
548 radeon_resume_kms(dev); 548 radeon_resume_kms(dev);
549 drm_kms_helper_poll_enable(dev);
549 } else { 550 } else {
550 printk(KERN_INFO "radeon: switched off\n"); 551 printk(KERN_INFO "radeon: switched off\n");
552 drm_kms_helper_poll_disable(dev);
551 radeon_suspend_kms(dev, pmm); 553 radeon_suspend_kms(dev, pmm);
552 /* don't suspend or resume card normally */ 554 /* don't suspend or resume card normally */
553 rdev->powered_down = true; 555 rdev->powered_down = true;
@@ -711,6 +713,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
711{ 713{
712 struct radeon_device *rdev; 714 struct radeon_device *rdev;
713 struct drm_crtc *crtc; 715 struct drm_crtc *crtc;
716 struct drm_connector *connector;
714 int r; 717 int r;
715 718
716 if (dev == NULL || dev->dev_private == NULL) { 719 if (dev == NULL || dev->dev_private == NULL) {
@@ -723,6 +726,12 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
723 726
724 if (rdev->powered_down) 727 if (rdev->powered_down)
725 return 0; 728 return 0;
729
730 /* turn off display hw */
731 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
732 drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
733 }
734
726 /* unpin the front buffers */ 735 /* unpin the front buffers */
727 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 736 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
728 struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->fb); 737 struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->fb);
@@ -754,6 +763,8 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
754 /* evict remaining vram memory */ 763 /* evict remaining vram memory */
755 radeon_bo_evict_vram(rdev); 764 radeon_bo_evict_vram(rdev);
756 765
766 radeon_agp_suspend(rdev);
767
757 pci_save_state(dev->pdev); 768 pci_save_state(dev->pdev);
758 if (state.event == PM_EVENT_SUSPEND) { 769 if (state.event == PM_EVENT_SUSPEND) {
759 /* Shut down the device */ 770 /* Shut down the device */
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 1006549d1570..8154cdf796e4 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -284,8 +284,7 @@ static const char *connector_names[15] = {
284 "eDP", 284 "eDP",
285}; 285};
286 286
287static const char *hpd_names[7] = { 287static const char *hpd_names[6] = {
288 "NONE",
289 "HPD1", 288 "HPD1",
290 "HPD2", 289 "HPD2",
291 "HPD3", 290 "HPD3",
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 902d1731a652..e166fe4d7c30 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -45,9 +45,10 @@
45 * - 2.2.0 - add r6xx/r7xx const buffer support 45 * - 2.2.0 - add r6xx/r7xx const buffer support
46 * - 2.3.0 - add MSPOS + 3D texture + r500 VAP regs 46 * - 2.3.0 - add MSPOS + 3D texture + r500 VAP regs
47 * - 2.4.0 - add crtc id query 47 * - 2.4.0 - add crtc id query
48 * - 2.5.0 - add get accel 2 to work around ddx breakage for evergreen
48 */ 49 */
49#define KMS_DRIVER_MAJOR 2 50#define KMS_DRIVER_MAJOR 2
50#define KMS_DRIVER_MINOR 4 51#define KMS_DRIVER_MINOR 5
51#define KMS_DRIVER_PATCHLEVEL 0 52#define KMS_DRIVER_PATCHLEVEL 0
52int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); 53int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
53int radeon_driver_unload_kms(struct drm_device *dev); 54int radeon_driver_unload_kms(struct drm_device *dev);
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
index e192acfbf0cd..dc1634bb0c11 100644
--- a/drivers/gpu/drm/radeon/radeon_fb.c
+++ b/drivers/gpu/drm/radeon/radeon_fb.c
@@ -363,6 +363,7 @@ int radeon_fbdev_init(struct radeon_device *rdev)
363{ 363{
364 struct radeon_fbdev *rfbdev; 364 struct radeon_fbdev *rfbdev;
365 int bpp_sel = 32; 365 int bpp_sel = 32;
366 int ret;
366 367
367 /* select 8 bpp console on RN50 or 16MB cards */ 368 /* select 8 bpp console on RN50 or 16MB cards */
368 if (ASIC_IS_RN50(rdev) || rdev->mc.real_vram_size <= (32*1024*1024)) 369 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)
376 rdev->mode_info.rfbdev = rfbdev; 377 rdev->mode_info.rfbdev = rfbdev;
377 rfbdev->helper.funcs = &radeon_fb_helper_funcs; 378 rfbdev->helper.funcs = &radeon_fb_helper_funcs;
378 379
379 drm_fb_helper_init(rdev->ddev, &rfbdev->helper, 380 ret = drm_fb_helper_init(rdev->ddev, &rfbdev->helper,
380 rdev->num_crtc, 381 rdev->num_crtc,
381 RADEONFB_CONN_LIMIT); 382 RADEONFB_CONN_LIMIT);
383 if (ret) {
384 kfree(rfbdev);
385 return ret;
386 }
387
382 drm_fb_helper_single_add_all_connectors(&rfbdev->helper); 388 drm_fb_helper_single_add_all_connectors(&rfbdev->helper);
383 drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel); 389 drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel);
384 return 0; 390 return 0;
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
index 04068352ccd2..6a70c0dc7f92 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -118,7 +118,11 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
118 value = rdev->num_z_pipes; 118 value = rdev->num_z_pipes;
119 break; 119 break;
120 case RADEON_INFO_ACCEL_WORKING: 120 case RADEON_INFO_ACCEL_WORKING:
121 value = rdev->accel_working; 121 /* xf86-video-ati 6.13.0 relies on this being false for evergreen */
122 if ((rdev->family >= CHIP_CEDAR) && (rdev->family <= CHIP_HEMLOCK))
123 value = false;
124 else
125 value = rdev->accel_working;
122 break; 126 break;
123 case RADEON_INFO_CRTC_FROM_ID: 127 case RADEON_INFO_CRTC_FROM_ID:
124 for (i = 0, found = 0; i < rdev->num_crtc; i++) { 128 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)
134 return -EINVAL; 138 return -EINVAL;
135 } 139 }
136 break; 140 break;
141 case RADEON_INFO_ACCEL_WORKING2:
142 value = rdev->accel_working;
143 break;
137 default: 144 default:
138 DRM_DEBUG("Invalid request %d\n", info->request); 145 DRM_DEBUG("Invalid request %d\n", info->request);
139 return -EINVAL; 146 return -EINVAL;
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
index 5a13b3eeef19..5b07b8848e09 100644
--- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
+++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
@@ -1168,6 +1168,17 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder
1168 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 1168 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
1169 struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv; 1169 struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
1170 bool color = true; 1170 bool color = true;
1171 struct drm_crtc *crtc;
1172
1173 /* find out if crtc2 is in use or if this encoder is using it */
1174 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
1175 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
1176 if ((radeon_crtc->crtc_id == 1) && crtc->enabled) {
1177 if (encoder->crtc != crtc) {
1178 return connector_status_disconnected;
1179 }
1180 }
1181 }
1171 1182
1172 if (connector->connector_type == DRM_MODE_CONNECTOR_SVIDEO || 1183 if (connector->connector_type == DRM_MODE_CONNECTOR_SVIDEO ||
1173 connector->connector_type == DRM_MODE_CONNECTOR_Composite || 1184 connector->connector_type == DRM_MODE_CONNECTOR_Composite ||
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c
index a8d162c6f829..63f679a04b25 100644
--- a/drivers/gpu/drm/radeon/radeon_pm.c
+++ b/drivers/gpu/drm/radeon/radeon_pm.c
@@ -33,6 +33,14 @@
33#define RADEON_WAIT_VBLANK_TIMEOUT 200 33#define RADEON_WAIT_VBLANK_TIMEOUT 200
34#define RADEON_WAIT_IDLE_TIMEOUT 200 34#define RADEON_WAIT_IDLE_TIMEOUT 200
35 35
36static const char *radeon_pm_state_type_name[5] = {
37 "Default",
38 "Powersave",
39 "Battery",
40 "Balanced",
41 "Performance",
42};
43
36static void radeon_dynpm_idle_work_handler(struct work_struct *work); 44static void radeon_dynpm_idle_work_handler(struct work_struct *work);
37static int radeon_debugfs_pm_init(struct radeon_device *rdev); 45static int radeon_debugfs_pm_init(struct radeon_device *rdev);
38static bool radeon_pm_in_vbl(struct radeon_device *rdev); 46static bool radeon_pm_in_vbl(struct radeon_device *rdev);
@@ -84,9 +92,9 @@ static void radeon_pm_update_profile(struct radeon_device *rdev)
84 rdev->pm.profile_index = PM_PROFILE_HIGH_SH_IDX; 92 rdev->pm.profile_index = PM_PROFILE_HIGH_SH_IDX;
85 } else { 93 } else {
86 if (rdev->pm.active_crtc_count > 1) 94 if (rdev->pm.active_crtc_count > 1)
87 rdev->pm.profile_index = PM_PROFILE_LOW_MH_IDX; 95 rdev->pm.profile_index = PM_PROFILE_MID_MH_IDX;
88 else 96 else
89 rdev->pm.profile_index = PM_PROFILE_LOW_SH_IDX; 97 rdev->pm.profile_index = PM_PROFILE_MID_SH_IDX;
90 } 98 }
91 break; 99 break;
92 case PM_PROFILE_LOW: 100 case PM_PROFILE_LOW:
@@ -95,6 +103,12 @@ static void radeon_pm_update_profile(struct radeon_device *rdev)
95 else 103 else
96 rdev->pm.profile_index = PM_PROFILE_LOW_SH_IDX; 104 rdev->pm.profile_index = PM_PROFILE_LOW_SH_IDX;
97 break; 105 break;
106 case PM_PROFILE_MID:
107 if (rdev->pm.active_crtc_count > 1)
108 rdev->pm.profile_index = PM_PROFILE_MID_MH_IDX;
109 else
110 rdev->pm.profile_index = PM_PROFILE_MID_SH_IDX;
111 break;
98 case PM_PROFILE_HIGH: 112 case PM_PROFILE_HIGH:
99 if (rdev->pm.active_crtc_count > 1) 113 if (rdev->pm.active_crtc_count > 1)
100 rdev->pm.profile_index = PM_PROFILE_HIGH_MH_IDX; 114 rdev->pm.profile_index = PM_PROFILE_HIGH_MH_IDX;
@@ -127,15 +141,6 @@ static void radeon_unmap_vram_bos(struct radeon_device *rdev)
127 if (bo->tbo.mem.mem_type == TTM_PL_VRAM) 141 if (bo->tbo.mem.mem_type == TTM_PL_VRAM)
128 ttm_bo_unmap_virtual(&bo->tbo); 142 ttm_bo_unmap_virtual(&bo->tbo);
129 } 143 }
130
131 if (rdev->gart.table.vram.robj)
132 ttm_bo_unmap_virtual(&rdev->gart.table.vram.robj->tbo);
133
134 if (rdev->stollen_vga_memory)
135 ttm_bo_unmap_virtual(&rdev->stollen_vga_memory->tbo);
136
137 if (rdev->r600_blit.shader_obj)
138 ttm_bo_unmap_virtual(&rdev->r600_blit.shader_obj->tbo);
139} 144}
140 145
141static void radeon_sync_with_vblank(struct radeon_device *rdev) 146static void radeon_sync_with_vblank(struct radeon_device *rdev)
@@ -151,6 +156,7 @@ static void radeon_sync_with_vblank(struct radeon_device *rdev)
151static void radeon_set_power_state(struct radeon_device *rdev) 156static void radeon_set_power_state(struct radeon_device *rdev)
152{ 157{
153 u32 sclk, mclk; 158 u32 sclk, mclk;
159 bool misc_after = false;
154 160
155 if ((rdev->pm.requested_clock_mode_index == rdev->pm.current_clock_mode_index) && 161 if ((rdev->pm.requested_clock_mode_index == rdev->pm.current_clock_mode_index) &&
156 (rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index)) 162 (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)
167 if (mclk > rdev->clock.default_mclk) 173 if (mclk > rdev->clock.default_mclk)
168 mclk = rdev->clock.default_mclk; 174 mclk = rdev->clock.default_mclk;
169 175
170 /* voltage, pcie lanes, etc.*/ 176 /* upvolt before raising clocks, downvolt after lowering clocks */
171 radeon_pm_misc(rdev); 177 if (sclk < rdev->pm.current_sclk)
178 misc_after = true;
172 179
173 if (rdev->pm.pm_method == PM_METHOD_DYNPM) { 180 radeon_sync_with_vblank(rdev);
174 radeon_sync_with_vblank(rdev);
175 181
182 if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
176 if (!radeon_pm_in_vbl(rdev)) 183 if (!radeon_pm_in_vbl(rdev))
177 return; 184 return;
185 }
178 186
179 radeon_pm_prepare(rdev); 187 radeon_pm_prepare(rdev);
180 /* set engine clock */
181 if (sclk != rdev->pm.current_sclk) {
182 radeon_pm_debug_check_in_vbl(rdev, false);
183 radeon_set_engine_clock(rdev, sclk);
184 radeon_pm_debug_check_in_vbl(rdev, true);
185 rdev->pm.current_sclk = sclk;
186 DRM_DEBUG("Setting: e: %d\n", sclk);
187 }
188 188
189 /* set memory clock */ 189 if (!misc_after)
190 if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) { 190 /* voltage, pcie lanes, etc.*/
191 radeon_pm_debug_check_in_vbl(rdev, false); 191 radeon_pm_misc(rdev);
192 radeon_set_memory_clock(rdev, mclk); 192
193 radeon_pm_debug_check_in_vbl(rdev, true); 193 /* set engine clock */
194 rdev->pm.current_mclk = mclk; 194 if (sclk != rdev->pm.current_sclk) {
195 DRM_DEBUG("Setting: m: %d\n", mclk); 195 radeon_pm_debug_check_in_vbl(rdev, false);
196 } 196 radeon_set_engine_clock(rdev, sclk);
197 radeon_pm_finish(rdev); 197 radeon_pm_debug_check_in_vbl(rdev, true);
198 } else { 198 rdev->pm.current_sclk = sclk;
199 /* set engine clock */ 199 DRM_DEBUG("Setting: e: %d\n", sclk);
200 if (sclk != rdev->pm.current_sclk) {
201 radeon_sync_with_vblank(rdev);
202 radeon_pm_prepare(rdev);
203 radeon_set_engine_clock(rdev, sclk);
204 radeon_pm_finish(rdev);
205 rdev->pm.current_sclk = sclk;
206 DRM_DEBUG("Setting: e: %d\n", sclk);
207 }
208 /* set memory clock */
209 if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) {
210 radeon_sync_with_vblank(rdev);
211 radeon_pm_prepare(rdev);
212 radeon_set_memory_clock(rdev, mclk);
213 radeon_pm_finish(rdev);
214 rdev->pm.current_mclk = mclk;
215 DRM_DEBUG("Setting: m: %d\n", mclk);
216 }
217 } 200 }
218 201
202 /* set memory clock */
203 if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) {
204 radeon_pm_debug_check_in_vbl(rdev, false);
205 radeon_set_memory_clock(rdev, mclk);
206 radeon_pm_debug_check_in_vbl(rdev, true);
207 rdev->pm.current_mclk = mclk;
208 DRM_DEBUG("Setting: m: %d\n", mclk);
209 }
210
211 if (misc_after)
212 /* voltage, pcie lanes, etc.*/
213 radeon_pm_misc(rdev);
214
215 radeon_pm_finish(rdev);
216
219 rdev->pm.current_power_state_index = rdev->pm.requested_power_state_index; 217 rdev->pm.current_power_state_index = rdev->pm.requested_power_state_index;
220 rdev->pm.current_clock_mode_index = rdev->pm.requested_clock_mode_index; 218 rdev->pm.current_clock_mode_index = rdev->pm.requested_clock_mode_index;
221 } else 219 } else
@@ -288,6 +286,42 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev)
288 mutex_unlock(&rdev->ddev->struct_mutex); 286 mutex_unlock(&rdev->ddev->struct_mutex);
289} 287}
290 288
289static void radeon_pm_print_states(struct radeon_device *rdev)
290{
291 int i, j;
292 struct radeon_power_state *power_state;
293 struct radeon_pm_clock_info *clock_info;
294
295 DRM_DEBUG("%d Power State(s)\n", rdev->pm.num_power_states);
296 for (i = 0; i < rdev->pm.num_power_states; i++) {
297 power_state = &rdev->pm.power_state[i];
298 DRM_DEBUG("State %d: %s\n", i,
299 radeon_pm_state_type_name[power_state->type]);
300 if (i == rdev->pm.default_power_state_index)
301 DRM_DEBUG("\tDefault");
302 if ((rdev->flags & RADEON_IS_PCIE) && !(rdev->flags & RADEON_IS_IGP))
303 DRM_DEBUG("\t%d PCIE Lanes\n", power_state->pcie_lanes);
304 if (power_state->flags & RADEON_PM_STATE_SINGLE_DISPLAY_ONLY)
305 DRM_DEBUG("\tSingle display only\n");
306 DRM_DEBUG("\t%d Clock Mode(s)\n", power_state->num_clock_modes);
307 for (j = 0; j < power_state->num_clock_modes; j++) {
308 clock_info = &(power_state->clock_info[j]);
309 if (rdev->flags & RADEON_IS_IGP)
310 DRM_DEBUG("\t\t%d e: %d%s\n",
311 j,
312 clock_info->sclk * 10,
313 clock_info->flags & RADEON_PM_MODE_NO_DISPLAY ? "\tNo display only" : "");
314 else
315 DRM_DEBUG("\t\t%d e: %d\tm: %d\tv: %d%s\n",
316 j,
317 clock_info->sclk * 10,
318 clock_info->mclk * 10,
319 clock_info->voltage.voltage,
320 clock_info->flags & RADEON_PM_MODE_NO_DISPLAY ? "\tNo display only" : "");
321 }
322 }
323}
324
291static ssize_t radeon_get_pm_profile(struct device *dev, 325static ssize_t radeon_get_pm_profile(struct device *dev,
292 struct device_attribute *attr, 326 struct device_attribute *attr,
293 char *buf) 327 char *buf)
@@ -318,6 +352,8 @@ static ssize_t radeon_set_pm_profile(struct device *dev,
318 rdev->pm.profile = PM_PROFILE_AUTO; 352 rdev->pm.profile = PM_PROFILE_AUTO;
319 else if (strncmp("low", buf, strlen("low")) == 0) 353 else if (strncmp("low", buf, strlen("low")) == 0)
320 rdev->pm.profile = PM_PROFILE_LOW; 354 rdev->pm.profile = PM_PROFILE_LOW;
355 else if (strncmp("mid", buf, strlen("mid")) == 0)
356 rdev->pm.profile = PM_PROFILE_MID;
321 else if (strncmp("high", buf, strlen("high")) == 0) 357 else if (strncmp("high", buf, strlen("high")) == 0)
322 rdev->pm.profile = PM_PROFILE_HIGH; 358 rdev->pm.profile = PM_PROFILE_HIGH;
323 else { 359 else {
@@ -384,15 +420,19 @@ void radeon_pm_suspend(struct radeon_device *rdev)
384{ 420{
385 mutex_lock(&rdev->pm.mutex); 421 mutex_lock(&rdev->pm.mutex);
386 cancel_delayed_work(&rdev->pm.dynpm_idle_work); 422 cancel_delayed_work(&rdev->pm.dynpm_idle_work);
387 rdev->pm.current_power_state_index = -1;
388 rdev->pm.current_clock_mode_index = -1;
389 rdev->pm.current_sclk = 0;
390 rdev->pm.current_mclk = 0;
391 mutex_unlock(&rdev->pm.mutex); 423 mutex_unlock(&rdev->pm.mutex);
392} 424}
393 425
394void radeon_pm_resume(struct radeon_device *rdev) 426void radeon_pm_resume(struct radeon_device *rdev)
395{ 427{
428 /* asic init will reset the default power state */
429 mutex_lock(&rdev->pm.mutex);
430 rdev->pm.current_power_state_index = rdev->pm.default_power_state_index;
431 rdev->pm.current_clock_mode_index = 0;
432 rdev->pm.current_sclk = rdev->clock.default_sclk;
433 rdev->pm.current_mclk = rdev->clock.default_mclk;
434 rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
435 mutex_unlock(&rdev->pm.mutex);
396 radeon_pm_compute_clocks(rdev); 436 radeon_pm_compute_clocks(rdev);
397} 437}
398 438
@@ -401,32 +441,24 @@ int radeon_pm_init(struct radeon_device *rdev)
401 int ret; 441 int ret;
402 /* default to profile method */ 442 /* default to profile method */
403 rdev->pm.pm_method = PM_METHOD_PROFILE; 443 rdev->pm.pm_method = PM_METHOD_PROFILE;
444 rdev->pm.profile = PM_PROFILE_DEFAULT;
404 rdev->pm.dynpm_state = DYNPM_STATE_DISABLED; 445 rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
405 rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE; 446 rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE;
406 rdev->pm.dynpm_can_upclock = true; 447 rdev->pm.dynpm_can_upclock = true;
407 rdev->pm.dynpm_can_downclock = true; 448 rdev->pm.dynpm_can_downclock = true;
408 rdev->pm.current_sclk = 0; 449 rdev->pm.current_sclk = rdev->clock.default_sclk;
409 rdev->pm.current_mclk = 0; 450 rdev->pm.current_mclk = rdev->clock.default_mclk;
410 451
411 if (rdev->bios) { 452 if (rdev->bios) {
412 if (rdev->is_atom_bios) 453 if (rdev->is_atom_bios)
413 radeon_atombios_get_power_modes(rdev); 454 radeon_atombios_get_power_modes(rdev);
414 else 455 else
415 radeon_combios_get_power_modes(rdev); 456 radeon_combios_get_power_modes(rdev);
457 radeon_pm_print_states(rdev);
416 radeon_pm_init_profile(rdev); 458 radeon_pm_init_profile(rdev);
417 rdev->pm.current_power_state_index = -1;
418 rdev->pm.current_clock_mode_index = -1;
419 } 459 }
420 460
421 if (rdev->pm.num_power_states > 1) { 461 if (rdev->pm.num_power_states > 1) {
422 if (rdev->pm.pm_method == PM_METHOD_PROFILE) {
423 mutex_lock(&rdev->pm.mutex);
424 rdev->pm.profile = PM_PROFILE_DEFAULT;
425 radeon_pm_update_profile(rdev);
426 radeon_pm_set_clocks(rdev);
427 mutex_unlock(&rdev->pm.mutex);
428 }
429
430 /* where's the best place to put these? */ 462 /* where's the best place to put these? */
431 ret = device_create_file(rdev->dev, &dev_attr_power_profile); 463 ret = device_create_file(rdev->dev, &dev_attr_power_profile);
432 if (ret) 464 if (ret)
@@ -712,6 +744,8 @@ static int radeon_debugfs_pm_info(struct seq_file *m, void *data)
712 seq_printf(m, "default memory clock: %u0 kHz\n", rdev->clock.default_mclk); 744 seq_printf(m, "default memory clock: %u0 kHz\n", rdev->clock.default_mclk);
713 if (rdev->asic->get_memory_clock) 745 if (rdev->asic->get_memory_clock)
714 seq_printf(m, "current memory clock: %u0 kHz\n", radeon_get_memory_clock(rdev)); 746 seq_printf(m, "current memory clock: %u0 kHz\n", radeon_get_memory_clock(rdev));
747 if (rdev->pm.current_vddc)
748 seq_printf(m, "voltage: %u mV\n", rdev->pm.current_vddc);
715 if (rdev->asic->get_pcie_lanes) 749 if (rdev->asic->get_pcie_lanes)
716 seq_printf(m, "PCIE lanes: %d\n", radeon_get_pcie_lanes(rdev)); 750 seq_printf(m, "PCIE lanes: %d\n", radeon_get_pcie_lanes(rdev));
717 751
diff --git a/drivers/gpu/drm/radeon/radeon_state.c b/drivers/gpu/drm/radeon/radeon_state.c
index cc5316dcf580..b3ba44c0a818 100644
--- a/drivers/gpu/drm/radeon/radeon_state.c
+++ b/drivers/gpu/drm/radeon/radeon_state.c
@@ -900,9 +900,10 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev,
900 flags |= RADEON_FRONT; 900 flags |= RADEON_FRONT;
901 } 901 }
902 if (flags & (RADEON_DEPTH|RADEON_STENCIL)) { 902 if (flags & (RADEON_DEPTH|RADEON_STENCIL)) {
903 if (!dev_priv->have_z_offset) 903 if (!dev_priv->have_z_offset) {
904 printk_once(KERN_ERR "radeon: illegal depth clear request. Buggy mesa detected - please update.\n"); 904 printk_once(KERN_ERR "radeon: illegal depth clear request. Buggy mesa detected - please update.\n");
905 flags &= ~(RADEON_DEPTH | RADEON_STENCIL); 905 flags &= ~(RADEON_DEPTH | RADEON_STENCIL);
906 }
906 } 907 }
907 908
908 if (flags & (RADEON_FRONT | RADEON_BACK)) { 909 if (flags & (RADEON_FRONT | RADEON_BACK)) {
diff --git a/drivers/gpu/drm/radeon/reg_srcs/evergreen b/drivers/gpu/drm/radeon/reg_srcs/evergreen
new file mode 100644
index 000000000000..b5c757f68d3c
--- /dev/null
+++ b/drivers/gpu/drm/radeon/reg_srcs/evergreen
@@ -0,0 +1,611 @@
1evergreen 0x9400
20x00008040 WAIT_UNTIL
30x00008044 WAIT_UNTIL_POLL_CNTL
40x00008048 WAIT_UNTIL_POLL_MASK
50x0000804c WAIT_UNTIL_POLL_REFDATA
60x000088B0 VGT_VTX_VECT_EJECT_REG
70x000088C4 VGT_CACHE_INVALIDATION
80x000088D4 VGT_GS_VERTEX_REUSE
90x00008958 VGT_PRIMITIVE_TYPE
100x0000895C VGT_INDEX_TYPE
110x00008970 VGT_NUM_INDICES
120x00008974 VGT_NUM_INSTANCES
130x00008990 VGT_COMPUTE_DIM_X
140x00008994 VGT_COMPUTE_DIM_Y
150x00008998 VGT_COMPUTE_DIM_Z
160x0000899C VGT_COMPUTE_START_X
170x000089A0 VGT_COMPUTE_START_Y
180x000089A4 VGT_COMPUTE_START_Z
190x000089AC VGT_COMPUTE_THREAD_GOURP_SIZE
200x00008A14 PA_CL_ENHANCE
210x00008A60 PA_SC_LINE_STIPPLE_VALUE
220x00008B10 PA_SC_LINE_STIPPLE_STATE
230x00008BF0 PA_SC_ENHANCE
240x00008D8C SQ_DYN_GPR_CNTL_PS_FLUSH_REQ
250x00008C00 SQ_CONFIG
260x00008C04 SQ_GPR_RESOURCE_MGMT_1
270x00008C08 SQ_GPR_RESOURCE_MGMT_2
280x00008C0C SQ_GPR_RESOURCE_MGMT_3
290x00008C10 SQ_GLOBAL_GPR_RESOURCE_MGMT_1
300x00008C14 SQ_GLOBAL_GPR_RESOURCE_MGMT_2
310x00008C18 SQ_THREAD_RESOURCE_MGMT
320x00008C1C SQ_THREAD_RESOURCE_MGMT_2
330x00008C20 SQ_STACK_RESOURCE_MGMT_1
340x00008C24 SQ_STACK_RESOURCE_MGMT_2
350x00008C28 SQ_STACK_RESOURCE_MGMT_3
360x00008DF8 SQ_CONST_MEM_BASE
370x00008E48 SQ_EX_ALLOC_TABLE_SLOTS
380x00009100 SPI_CONFIG_CNTL
390x0000913C SPI_CONFIG_CNTL_1
400x00009700 VC_CNTL
410x00009714 VC_ENHANCE
420x00009830 DB_DEBUG
430x00009834 DB_DEBUG2
440x00009838 DB_DEBUG3
450x0000983C DB_DEBUG4
460x00009854 DB_WATERMARKS
470x0000A400 TD_PS_BORDER_COLOR_INDEX
480x0000A404 TD_PS_BORDER_COLOR_RED
490x0000A408 TD_PS_BORDER_COLOR_GREEN
500x0000A40C TD_PS_BORDER_COLOR_BLUE
510x0000A410 TD_PS_BORDER_COLOR_ALPHA
520x0000A414 TD_VS_BORDER_COLOR_INDEX
530x0000A418 TD_VS_BORDER_COLOR_RED
540x0000A41C TD_VS_BORDER_COLOR_GREEN
550x0000A420 TD_VS_BORDER_COLOR_BLUE
560x0000A424 TD_VS_BORDER_COLOR_ALPHA
570x0000A428 TD_GS_BORDER_COLOR_INDEX
580x0000A42C TD_GS_BORDER_COLOR_RED
590x0000A430 TD_GS_BORDER_COLOR_GREEN
600x0000A434 TD_GS_BORDER_COLOR_BLUE
610x0000A438 TD_GS_BORDER_COLOR_ALPHA
620x0000A43C TD_HS_BORDER_COLOR_INDEX
630x0000A440 TD_HS_BORDER_COLOR_RED
640x0000A444 TD_HS_BORDER_COLOR_GREEN
650x0000A448 TD_HS_BORDER_COLOR_BLUE
660x0000A44C TD_HS_BORDER_COLOR_ALPHA
670x0000A450 TD_LS_BORDER_COLOR_INDEX
680x0000A454 TD_LS_BORDER_COLOR_RED
690x0000A458 TD_LS_BORDER_COLOR_GREEN
700x0000A45C TD_LS_BORDER_COLOR_BLUE
710x0000A460 TD_LS_BORDER_COLOR_ALPHA
720x0000A464 TD_CS_BORDER_COLOR_INDEX
730x0000A468 TD_CS_BORDER_COLOR_RED
740x0000A46C TD_CS_BORDER_COLOR_GREEN
750x0000A470 TD_CS_BORDER_COLOR_BLUE
760x0000A474 TD_CS_BORDER_COLOR_ALPHA
770x00028000 DB_RENDER_CONTROL
780x00028004 DB_COUNT_CONTROL
790x0002800C DB_RENDER_OVERRIDE
800x00028010 DB_RENDER_OVERRIDE2
810x00028028 DB_STENCIL_CLEAR
820x0002802C DB_DEPTH_CLEAR
830x00028034 PA_SC_SCREEN_SCISSOR_BR
840x00028030 PA_SC_SCREEN_SCISSOR_TL
850x0002805C DB_DEPTH_SLICE
860x00028140 SQ_ALU_CONST_BUFFER_SIZE_PS_0
870x00028144 SQ_ALU_CONST_BUFFER_SIZE_PS_1
880x00028148 SQ_ALU_CONST_BUFFER_SIZE_PS_2
890x0002814C SQ_ALU_CONST_BUFFER_SIZE_PS_3
900x00028150 SQ_ALU_CONST_BUFFER_SIZE_PS_4
910x00028154 SQ_ALU_CONST_BUFFER_SIZE_PS_5
920x00028158 SQ_ALU_CONST_BUFFER_SIZE_PS_6
930x0002815C SQ_ALU_CONST_BUFFER_SIZE_PS_7
940x00028160 SQ_ALU_CONST_BUFFER_SIZE_PS_8
950x00028164 SQ_ALU_CONST_BUFFER_SIZE_PS_9
960x00028168 SQ_ALU_CONST_BUFFER_SIZE_PS_10
970x0002816C SQ_ALU_CONST_BUFFER_SIZE_PS_11
980x00028170 SQ_ALU_CONST_BUFFER_SIZE_PS_12
990x00028174 SQ_ALU_CONST_BUFFER_SIZE_PS_13
1000x00028178 SQ_ALU_CONST_BUFFER_SIZE_PS_14
1010x0002817C SQ_ALU_CONST_BUFFER_SIZE_PS_15
1020x00028180 SQ_ALU_CONST_BUFFER_SIZE_VS_0
1030x00028184 SQ_ALU_CONST_BUFFER_SIZE_VS_1
1040x00028188 SQ_ALU_CONST_BUFFER_SIZE_VS_2
1050x0002818C SQ_ALU_CONST_BUFFER_SIZE_VS_3
1060x00028190 SQ_ALU_CONST_BUFFER_SIZE_VS_4
1070x00028194 SQ_ALU_CONST_BUFFER_SIZE_VS_5
1080x00028198 SQ_ALU_CONST_BUFFER_SIZE_VS_6
1090x0002819C SQ_ALU_CONST_BUFFER_SIZE_VS_7
1100x000281A0 SQ_ALU_CONST_BUFFER_SIZE_VS_8
1110x000281A4 SQ_ALU_CONST_BUFFER_SIZE_VS_9
1120x000281A8 SQ_ALU_CONST_BUFFER_SIZE_VS_10
1130x000281AC SQ_ALU_CONST_BUFFER_SIZE_VS_11
1140x000281B0 SQ_ALU_CONST_BUFFER_SIZE_VS_12
1150x000281B4 SQ_ALU_CONST_BUFFER_SIZE_VS_13
1160x000281B8 SQ_ALU_CONST_BUFFER_SIZE_VS_14
1170x000281BC SQ_ALU_CONST_BUFFER_SIZE_VS_15
1180x000281C0 SQ_ALU_CONST_BUFFER_SIZE_GS_0
1190x000281C4 SQ_ALU_CONST_BUFFER_SIZE_GS_1
1200x000281C8 SQ_ALU_CONST_BUFFER_SIZE_GS_2
1210x000281CC SQ_ALU_CONST_BUFFER_SIZE_GS_3
1220x000281D0 SQ_ALU_CONST_BUFFER_SIZE_GS_4
1230x000281D4 SQ_ALU_CONST_BUFFER_SIZE_GS_5
1240x000281D8 SQ_ALU_CONST_BUFFER_SIZE_GS_6
1250x000281DC SQ_ALU_CONST_BUFFER_SIZE_GS_7
1260x000281E0 SQ_ALU_CONST_BUFFER_SIZE_GS_8
1270x000281E4 SQ_ALU_CONST_BUFFER_SIZE_GS_9
1280x000281E8 SQ_ALU_CONST_BUFFER_SIZE_GS_10
1290x000281EC SQ_ALU_CONST_BUFFER_SIZE_GS_11
1300x000281F0 SQ_ALU_CONST_BUFFER_SIZE_GS_12
1310x000281F4 SQ_ALU_CONST_BUFFER_SIZE_GS_13
1320x000281F8 SQ_ALU_CONST_BUFFER_SIZE_GS_14
1330x000281FC SQ_ALU_CONST_BUFFER_SIZE_GS_15
1340x00028200 PA_SC_WINDOW_OFFSET
1350x00028204 PA_SC_WINDOW_SCISSOR_TL
1360x00028208 PA_SC_WINDOW_SCISSOR_BR
1370x0002820C PA_SC_CLIPRECT_RULE
1380x00028210 PA_SC_CLIPRECT_0_TL
1390x00028214 PA_SC_CLIPRECT_0_BR
1400x00028218 PA_SC_CLIPRECT_1_TL
1410x0002821C PA_SC_CLIPRECT_1_BR
1420x00028220 PA_SC_CLIPRECT_2_TL
1430x00028224 PA_SC_CLIPRECT_2_BR
1440x00028228 PA_SC_CLIPRECT_3_TL
1450x0002822C PA_SC_CLIPRECT_3_BR
1460x00028230 PA_SC_EDGERULE
1470x00028234 PA_SU_HARDWARE_SCREEN_OFFSET
1480x00028240 PA_SC_GENERIC_SCISSOR_TL
1490x00028244 PA_SC_GENERIC_SCISSOR_BR
1500x00028250 PA_SC_VPORT_SCISSOR_0_TL
1510x00028254 PA_SC_VPORT_SCISSOR_0_BR
1520x00028258 PA_SC_VPORT_SCISSOR_1_TL
1530x0002825C PA_SC_VPORT_SCISSOR_1_BR
1540x00028260 PA_SC_VPORT_SCISSOR_2_TL
1550x00028264 PA_SC_VPORT_SCISSOR_2_BR
1560x00028268 PA_SC_VPORT_SCISSOR_3_TL
1570x0002826C PA_SC_VPORT_SCISSOR_3_BR
1580x00028270 PA_SC_VPORT_SCISSOR_4_TL
1590x00028274 PA_SC_VPORT_SCISSOR_4_BR
1600x00028278 PA_SC_VPORT_SCISSOR_5_TL
1610x0002827C PA_SC_VPORT_SCISSOR_5_BR
1620x00028280 PA_SC_VPORT_SCISSOR_6_TL
1630x00028284 PA_SC_VPORT_SCISSOR_6_BR
1640x00028288 PA_SC_VPORT_SCISSOR_7_TL
1650x0002828C PA_SC_VPORT_SCISSOR_7_BR
1660x00028290 PA_SC_VPORT_SCISSOR_8_TL
1670x00028294 PA_SC_VPORT_SCISSOR_8_BR
1680x00028298 PA_SC_VPORT_SCISSOR_9_TL
1690x0002829C PA_SC_VPORT_SCISSOR_9_BR
1700x000282A0 PA_SC_VPORT_SCISSOR_10_TL
1710x000282A4 PA_SC_VPORT_SCISSOR_10_BR
1720x000282A8 PA_SC_VPORT_SCISSOR_11_TL
1730x000282AC PA_SC_VPORT_SCISSOR_11_BR
1740x000282B0 PA_SC_VPORT_SCISSOR_12_TL
1750x000282B4 PA_SC_VPORT_SCISSOR_12_BR
1760x000282B8 PA_SC_VPORT_SCISSOR_13_TL
1770x000282BC PA_SC_VPORT_SCISSOR_13_BR
1780x000282C0 PA_SC_VPORT_SCISSOR_14_TL
1790x000282C4 PA_SC_VPORT_SCISSOR_14_BR
1800x000282C8 PA_SC_VPORT_SCISSOR_15_TL
1810x000282CC PA_SC_VPORT_SCISSOR_15_BR
1820x000282D0 PA_SC_VPORT_ZMIN_0
1830x000282D4 PA_SC_VPORT_ZMAX_0
1840x000282D8 PA_SC_VPORT_ZMIN_1
1850x000282DC PA_SC_VPORT_ZMAX_1
1860x000282E0 PA_SC_VPORT_ZMIN_2
1870x000282E4 PA_SC_VPORT_ZMAX_2
1880x000282E8 PA_SC_VPORT_ZMIN_3
1890x000282EC PA_SC_VPORT_ZMAX_3
1900x000282F0 PA_SC_VPORT_ZMIN_4
1910x000282F4 PA_SC_VPORT_ZMAX_4
1920x000282F8 PA_SC_VPORT_ZMIN_5
1930x000282FC PA_SC_VPORT_ZMAX_5
1940x00028300 PA_SC_VPORT_ZMIN_6
1950x00028304 PA_SC_VPORT_ZMAX_6
1960x00028308 PA_SC_VPORT_ZMIN_7
1970x0002830C PA_SC_VPORT_ZMAX_7
1980x00028310 PA_SC_VPORT_ZMIN_8
1990x00028314 PA_SC_VPORT_ZMAX_8
2000x00028318 PA_SC_VPORT_ZMIN_9
2010x0002831C PA_SC_VPORT_ZMAX_9
2020x00028320 PA_SC_VPORT_ZMIN_10
2030x00028324 PA_SC_VPORT_ZMAX_10
2040x00028328 PA_SC_VPORT_ZMIN_11
2050x0002832C PA_SC_VPORT_ZMAX_11
2060x00028330 PA_SC_VPORT_ZMIN_12
2070x00028334 PA_SC_VPORT_ZMAX_12
2080x00028338 PA_SC_VPORT_ZMIN_13
2090x0002833C PA_SC_VPORT_ZMAX_13
2100x00028340 PA_SC_VPORT_ZMIN_14
2110x00028344 PA_SC_VPORT_ZMAX_14
2120x00028348 PA_SC_VPORT_ZMIN_15
2130x0002834C PA_SC_VPORT_ZMAX_15
2140x00028350 SX_MISC
2150x00028380 SQ_VTX_SEMANTIC_0
2160x00028384 SQ_VTX_SEMANTIC_1
2170x00028388 SQ_VTX_SEMANTIC_2
2180x0002838C SQ_VTX_SEMANTIC_3
2190x00028390 SQ_VTX_SEMANTIC_4
2200x00028394 SQ_VTX_SEMANTIC_5
2210x00028398 SQ_VTX_SEMANTIC_6
2220x0002839C SQ_VTX_SEMANTIC_7
2230x000283A0 SQ_VTX_SEMANTIC_8
2240x000283A4 SQ_VTX_SEMANTIC_9
2250x000283A8 SQ_VTX_SEMANTIC_10
2260x000283AC SQ_VTX_SEMANTIC_11
2270x000283B0 SQ_VTX_SEMANTIC_12
2280x000283B4 SQ_VTX_SEMANTIC_13
2290x000283B8 SQ_VTX_SEMANTIC_14
2300x000283BC SQ_VTX_SEMANTIC_15
2310x000283C0 SQ_VTX_SEMANTIC_16
2320x000283C4 SQ_VTX_SEMANTIC_17
2330x000283C8 SQ_VTX_SEMANTIC_18
2340x000283CC SQ_VTX_SEMANTIC_19
2350x000283D0 SQ_VTX_SEMANTIC_20
2360x000283D4 SQ_VTX_SEMANTIC_21
2370x000283D8 SQ_VTX_SEMANTIC_22
2380x000283DC SQ_VTX_SEMANTIC_23
2390x000283E0 SQ_VTX_SEMANTIC_24
2400x000283E4 SQ_VTX_SEMANTIC_25
2410x000283E8 SQ_VTX_SEMANTIC_26
2420x000283EC SQ_VTX_SEMANTIC_27
2430x000283F0 SQ_VTX_SEMANTIC_28
2440x000283F4 SQ_VTX_SEMANTIC_29
2450x000283F8 SQ_VTX_SEMANTIC_30
2460x000283FC SQ_VTX_SEMANTIC_31
2470x00028400 VGT_MAX_VTX_INDX
2480x00028404 VGT_MIN_VTX_INDX
2490x00028408 VGT_INDX_OFFSET
2500x0002840C VGT_MULTI_PRIM_IB_RESET_INDX
2510x00028410 SX_ALPHA_TEST_CONTROL
2520x00028414 CB_BLEND_RED
2530x00028418 CB_BLEND_GREEN
2540x0002841C CB_BLEND_BLUE
2550x00028420 CB_BLEND_ALPHA
2560x00028430 DB_STENCILREFMASK
2570x00028434 DB_STENCILREFMASK_BF
2580x00028438 SX_ALPHA_REF
2590x0002843C PA_CL_VPORT_XSCALE_0
2600x00028440 PA_CL_VPORT_XOFFSET_0
2610x00028444 PA_CL_VPORT_YSCALE_0
2620x00028448 PA_CL_VPORT_YOFFSET_0
2630x0002844C PA_CL_VPORT_ZSCALE_0
2640x00028450 PA_CL_VPORT_ZOFFSET_0
2650x00028454 PA_CL_VPORT_XSCALE_1
2660x00028458 PA_CL_VPORT_XOFFSET_1
2670x0002845C PA_CL_VPORT_YSCALE_1
2680x00028460 PA_CL_VPORT_YOFFSET_1
2690x00028464 PA_CL_VPORT_ZSCALE_1
2700x00028468 PA_CL_VPORT_ZOFFSET_1
2710x0002846C PA_CL_VPORT_XSCALE_2
2720x00028470 PA_CL_VPORT_XOFFSET_2
2730x00028474 PA_CL_VPORT_YSCALE_2
2740x00028478 PA_CL_VPORT_YOFFSET_2
2750x0002847C PA_CL_VPORT_ZSCALE_2
2760x00028480 PA_CL_VPORT_ZOFFSET_2
2770x00028484 PA_CL_VPORT_XSCALE_3
2780x00028488 PA_CL_VPORT_XOFFSET_3
2790x0002848C PA_CL_VPORT_YSCALE_3
2800x00028490 PA_CL_VPORT_YOFFSET_3
2810x00028494 PA_CL_VPORT_ZSCALE_3
2820x00028498 PA_CL_VPORT_ZOFFSET_3
2830x0002849C PA_CL_VPORT_XSCALE_4
2840x000284A0 PA_CL_VPORT_XOFFSET_4
2850x000284A4 PA_CL_VPORT_YSCALE_4
2860x000284A8 PA_CL_VPORT_YOFFSET_4
2870x000284AC PA_CL_VPORT_ZSCALE_4
2880x000284B0 PA_CL_VPORT_ZOFFSET_4
2890x000284B4 PA_CL_VPORT_XSCALE_5
2900x000284B8 PA_CL_VPORT_XOFFSET_5
2910x000284BC PA_CL_VPORT_YSCALE_5
2920x000284C0 PA_CL_VPORT_YOFFSET_5
2930x000284C4 PA_CL_VPORT_ZSCALE_5
2940x000284C8 PA_CL_VPORT_ZOFFSET_5
2950x000284CC PA_CL_VPORT_XSCALE_6
2960x000284D0 PA_CL_VPORT_XOFFSET_6
2970x000284D4 PA_CL_VPORT_YSCALE_6
2980x000284D8 PA_CL_VPORT_YOFFSET_6
2990x000284DC PA_CL_VPORT_ZSCALE_6
3000x000284E0 PA_CL_VPORT_ZOFFSET_6
3010x000284E4 PA_CL_VPORT_XSCALE_7
3020x000284E8 PA_CL_VPORT_XOFFSET_7
3030x000284EC PA_CL_VPORT_YSCALE_7
3040x000284F0 PA_CL_VPORT_YOFFSET_7
3050x000284F4 PA_CL_VPORT_ZSCALE_7
3060x000284F8 PA_CL_VPORT_ZOFFSET_7
3070x000284FC PA_CL_VPORT_XSCALE_8
3080x00028500 PA_CL_VPORT_XOFFSET_8
3090x00028504 PA_CL_VPORT_YSCALE_8
3100x00028508 PA_CL_VPORT_YOFFSET_8
3110x0002850C PA_CL_VPORT_ZSCALE_8
3120x00028510 PA_CL_VPORT_ZOFFSET_8
3130x00028514 PA_CL_VPORT_XSCALE_9
3140x00028518 PA_CL_VPORT_XOFFSET_9
3150x0002851C PA_CL_VPORT_YSCALE_9
3160x00028520 PA_CL_VPORT_YOFFSET_9
3170x00028524 PA_CL_VPORT_ZSCALE_9
3180x00028528 PA_CL_VPORT_ZOFFSET_9
3190x0002852C PA_CL_VPORT_XSCALE_10
3200x00028530 PA_CL_VPORT_XOFFSET_10
3210x00028534 PA_CL_VPORT_YSCALE_10
3220x00028538 PA_CL_VPORT_YOFFSET_10
3230x0002853C PA_CL_VPORT_ZSCALE_10
3240x00028540 PA_CL_VPORT_ZOFFSET_10
3250x00028544 PA_CL_VPORT_XSCALE_11
3260x00028548 PA_CL_VPORT_XOFFSET_11
3270x0002854C PA_CL_VPORT_YSCALE_11
3280x00028550 PA_CL_VPORT_YOFFSET_11
3290x00028554 PA_CL_VPORT_ZSCALE_11
3300x00028558 PA_CL_VPORT_ZOFFSET_11
3310x0002855C PA_CL_VPORT_XSCALE_12
3320x00028560 PA_CL_VPORT_XOFFSET_12
3330x00028564 PA_CL_VPORT_YSCALE_12
3340x00028568 PA_CL_VPORT_YOFFSET_12
3350x0002856C PA_CL_VPORT_ZSCALE_12
3360x00028570 PA_CL_VPORT_ZOFFSET_12
3370x00028574 PA_CL_VPORT_XSCALE_13
3380x00028578 PA_CL_VPORT_XOFFSET_13
3390x0002857C PA_CL_VPORT_YSCALE_13
3400x00028580 PA_CL_VPORT_YOFFSET_13
3410x00028584 PA_CL_VPORT_ZSCALE_13
3420x00028588 PA_CL_VPORT_ZOFFSET_13
3430x0002858C PA_CL_VPORT_XSCALE_14
3440x00028590 PA_CL_VPORT_XOFFSET_14
3450x00028594 PA_CL_VPORT_YSCALE_14
3460x00028598 PA_CL_VPORT_YOFFSET_14
3470x0002859C PA_CL_VPORT_ZSCALE_14
3480x000285A0 PA_CL_VPORT_ZOFFSET_14
3490x000285A4 PA_CL_VPORT_XSCALE_15
3500x000285A8 PA_CL_VPORT_XOFFSET_15
3510x000285AC PA_CL_VPORT_YSCALE_15
3520x000285B0 PA_CL_VPORT_YOFFSET_15
3530x000285B4 PA_CL_VPORT_ZSCALE_15
3540x000285B8 PA_CL_VPORT_ZOFFSET_15
3550x000285BC PA_CL_UCP_0_X
3560x000285C0 PA_CL_UCP_0_Y
3570x000285C4 PA_CL_UCP_0_Z
3580x000285C8 PA_CL_UCP_0_W
3590x000285CC PA_CL_UCP_1_X
3600x000285D0 PA_CL_UCP_1_Y
3610x000285D4 PA_CL_UCP_1_Z
3620x000285D8 PA_CL_UCP_1_W
3630x000285DC PA_CL_UCP_2_X
3640x000285E0 PA_CL_UCP_2_Y
3650x000285E4 PA_CL_UCP_2_Z
3660x000285E8 PA_CL_UCP_2_W
3670x000285EC PA_CL_UCP_3_X
3680x000285F0 PA_CL_UCP_3_Y
3690x000285F4 PA_CL_UCP_3_Z
3700x000285F8 PA_CL_UCP_3_W
3710x000285FC PA_CL_UCP_4_X
3720x00028600 PA_CL_UCP_4_Y
3730x00028604 PA_CL_UCP_4_Z
3740x00028608 PA_CL_UCP_4_W
3750x0002860C PA_CL_UCP_5_X
3760x00028610 PA_CL_UCP_5_Y
3770x00028614 PA_CL_UCP_5_Z
3780x00028618 PA_CL_UCP_5_W
3790x0002861C SPI_VS_OUT_ID_0
3800x00028620 SPI_VS_OUT_ID_1
3810x00028624 SPI_VS_OUT_ID_2
3820x00028628 SPI_VS_OUT_ID_3
3830x0002862C SPI_VS_OUT_ID_4
3840x00028630 SPI_VS_OUT_ID_5
3850x00028634 SPI_VS_OUT_ID_6
3860x00028638 SPI_VS_OUT_ID_7
3870x0002863C SPI_VS_OUT_ID_8
3880x00028640 SPI_VS_OUT_ID_9
3890x00028644 SPI_PS_INPUT_CNTL_0
3900x00028648 SPI_PS_INPUT_CNTL_1
3910x0002864C SPI_PS_INPUT_CNTL_2
3920x00028650 SPI_PS_INPUT_CNTL_3
3930x00028654 SPI_PS_INPUT_CNTL_4
3940x00028658 SPI_PS_INPUT_CNTL_5
3950x0002865C SPI_PS_INPUT_CNTL_6
3960x00028660 SPI_PS_INPUT_CNTL_7
3970x00028664 SPI_PS_INPUT_CNTL_8
3980x00028668 SPI_PS_INPUT_CNTL_9
3990x0002866C SPI_PS_INPUT_CNTL_10
4000x00028670 SPI_PS_INPUT_CNTL_11
4010x00028674 SPI_PS_INPUT_CNTL_12
4020x00028678 SPI_PS_INPUT_CNTL_13
4030x0002867C SPI_PS_INPUT_CNTL_14
4040x00028680 SPI_PS_INPUT_CNTL_15
4050x00028684 SPI_PS_INPUT_CNTL_16
4060x00028688 SPI_PS_INPUT_CNTL_17
4070x0002868C SPI_PS_INPUT_CNTL_18
4080x00028690 SPI_PS_INPUT_CNTL_19
4090x00028694 SPI_PS_INPUT_CNTL_20
4100x00028698 SPI_PS_INPUT_CNTL_21
4110x0002869C SPI_PS_INPUT_CNTL_22
4120x000286A0 SPI_PS_INPUT_CNTL_23
4130x000286A4 SPI_PS_INPUT_CNTL_24
4140x000286A8 SPI_PS_INPUT_CNTL_25
4150x000286AC SPI_PS_INPUT_CNTL_26
4160x000286B0 SPI_PS_INPUT_CNTL_27
4170x000286B4 SPI_PS_INPUT_CNTL_28
4180x000286B8 SPI_PS_INPUT_CNTL_29
4190x000286BC SPI_PS_INPUT_CNTL_30
4200x000286C0 SPI_PS_INPUT_CNTL_31
4210x000286C4 SPI_VS_OUT_CONFIG
4220x000286C8 SPI_THREAD_GROUPING
4230x000286CC SPI_PS_IN_CONTROL_0
4240x000286D0 SPI_PS_IN_CONTROL_1
4250x000286D4 SPI_INTERP_CONTROL_0
4260x000286D8 SPI_INPUT_Z
4270x000286DC SPI_FOG_CNTL
4280x000286E0 SPI_BARYC_CNTL
4290x000286E4 SPI_PS_IN_CONTROL_2
4300x000286E8 SPI_COMPUTE_INPUT_CNTL
4310x000286EC SPI_COMPUTE_NUM_THREAD_X
4320x000286F0 SPI_COMPUTE_NUM_THREAD_Y
4330x000286F4 SPI_COMPUTE_NUM_THREAD_Z
4340x000286F8 GDS_ADDR_SIZE
4350x00028780 CB_BLEND0_CONTROL
4360x00028784 CB_BLEND1_CONTROL
4370x00028788 CB_BLEND2_CONTROL
4380x0002878C CB_BLEND3_CONTROL
4390x00028790 CB_BLEND4_CONTROL
4400x00028794 CB_BLEND5_CONTROL
4410x00028798 CB_BLEND6_CONTROL
4420x0002879C CB_BLEND7_CONTROL
4430x000287CC CS_COPY_STATE
4440x000287D0 GFX_COPY_STATE
4450x000287D4 PA_CL_POINT_X_RAD
4460x000287D8 PA_CL_POINT_Y_RAD
4470x000287DC PA_CL_POINT_SIZE
4480x000287E0 PA_CL_POINT_CULL_RAD
4490x00028808 CB_COLOR_CONTROL
4500x0002880C DB_SHADER_CONTROL
4510x00028810 PA_CL_CLIP_CNTL
4520x00028814 PA_SU_SC_MODE_CNTL
4530x00028818 PA_CL_VTE_CNTL
4540x0002881C PA_CL_VS_OUT_CNTL
4550x00028820 PA_CL_NANINF_CNTL
4560x00028824 PA_SU_LINE_STIPPLE_CNTL
4570x00028828 PA_SU_LINE_STIPPLE_SCALE
4580x0002882C PA_SU_PRIM_FILTER_CNTL
4590x00028838 SQ_DYN_GPR_RESOURCE_LIMIT_1
4600x00028844 SQ_PGM_RESOURCES_PS
4610x00028848 SQ_PGM_RESOURCES_2_PS
4620x0002884C SQ_PGM_EXPORTS_PS
4630x0002885C SQ_PGM_RESOURCES_VS
4640x00028860 SQ_PGM_RESOURCES_2_VS
4650x00028878 SQ_PGM_RESOURCES_GS
4660x0002887C SQ_PGM_RESOURCES_2_GS
4670x00028890 SQ_PGM_RESOURCES_ES
4680x00028894 SQ_PGM_RESOURCES_2_ES
4690x000288A8 SQ_PGM_RESOURCES_FS
4700x000288BC SQ_PGM_RESOURCES_HS
4710x000288C0 SQ_PGM_RESOURCES_2_HS
4720x000288D0 SQ_PGM_RESOURCES_LS
4730x000288D4 SQ_PGM_RESOURCES_2_LS
4740x000288E8 SQ_LDS_ALLOC
4750x000288EC SQ_LDS_ALLOC_PS
4760x000288F0 SQ_VTX_SEMANTIC_CLEAR
4770x00028A00 PA_SU_POINT_SIZE
4780x00028A04 PA_SU_POINT_MINMAX
4790x00028A08 PA_SU_LINE_CNTL
4800x00028A0C PA_SC_LINE_STIPPLE
4810x00028A10 VGT_OUTPUT_PATH_CNTL
4820x00028A14 VGT_HOS_CNTL
4830x00028A18 VGT_HOS_MAX_TESS_LEVEL
4840x00028A1C VGT_HOS_MIN_TESS_LEVEL
4850x00028A20 VGT_HOS_REUSE_DEPTH
4860x00028A24 VGT_GROUP_PRIM_TYPE
4870x00028A28 VGT_GROUP_FIRST_DECR
4880x00028A2C VGT_GROUP_DECR
4890x00028A30 VGT_GROUP_VECT_0_CNTL
4900x00028A34 VGT_GROUP_VECT_1_CNTL
4910x00028A38 VGT_GROUP_VECT_0_FMT_CNTL
4920x00028A3C VGT_GROUP_VECT_1_FMT_CNTL
4930x00028A40 VGT_GS_MODE
4940x00028A48 PA_SC_MODE_CNTL_0
4950x00028A4C PA_SC_MODE_CNTL_1
4960x00028A50 VGT_ENHANCE
4970x00028A54 VGT_GS_PER_ES
4980x00028A58 VGT_ES_PER_GS
4990x00028A5C VGT_GS_PER_VS
5000x00028A6C VGT_GS_OUT_PRIM_TYPE
5010x00028A84 VGT_PRIMITIVEID_EN
5020x00028A94 VGT_MULTI_PRIM_IB_RESET_EN
5030x00028AA0 VGT_INSTANCE_STEP_RATE_0
5040x00028AA4 VGT_INSTANCE_STEP_RATE_1
5050x00028AB4 VGT_REUSE_OFF
5060x00028AB8 VGT_VTX_CNT_EN
5070x00028ABC DB_HTILE_SURFACE
5080x00028AC0 DB_SRESULTS_COMPARE_STATE0
5090x00028AC4 DB_SRESULTS_COMPARE_STATE1
5100x00028AC8 DB_PRELOAD_CONTROL
5110x00028B38 VGT_GS_MAX_VERT_OUT
5120x00028B54 VGT_SHADER_STAGES_EN
5130x00028B58 VGT_LS_HS_CONFIG
5140x00028B5C VGT_LS_SIZE
5150x00028B60 VGT_HS_SIZE
5160x00028B64 VGT_LS_HS_ALLOC
5170x00028B68 VGT_HS_PATCH_CONST
5180x00028B6C VGT_TF_PARAM
5190x00028B70 DB_ALPHA_TO_MASK
5200x00028B74 VGT_DISPATCH_INITIATOR
5210x00028B78 PA_SU_POLY_OFFSET_DB_FMT_CNTL
5220x00028B7C PA_SU_POLY_OFFSET_CLAMP
5230x00028B80 PA_SU_POLY_OFFSET_FRONT_SCALE
5240x00028B84 PA_SU_POLY_OFFSET_FRONT_OFFSET
5250x00028B88 PA_SU_POLY_OFFSET_BACK_SCALE
5260x00028B8C PA_SU_POLY_OFFSET_BACK_OFFSET
5270x00028B74 VGT_GS_INSTANCE_CNT
5280x00028C00 PA_SC_LINE_CNTL
5290x00028C08 PA_SU_VTX_CNTL
5300x00028C0C PA_CL_GB_VERT_CLIP_ADJ
5310x00028C10 PA_CL_GB_VERT_DISC_ADJ
5320x00028C14 PA_CL_GB_HORZ_CLIP_ADJ
5330x00028C18 PA_CL_GB_HORZ_DISC_ADJ
5340x00028C1C PA_SC_AA_SAMPLE_LOCS_0
5350x00028C20 PA_SC_AA_SAMPLE_LOCS_1
5360x00028C24 PA_SC_AA_SAMPLE_LOCS_2
5370x00028C28 PA_SC_AA_SAMPLE_LOCS_3
5380x00028C2C PA_SC_AA_SAMPLE_LOCS_4
5390x00028C30 PA_SC_AA_SAMPLE_LOCS_5
5400x00028C34 PA_SC_AA_SAMPLE_LOCS_6
5410x00028C38 PA_SC_AA_SAMPLE_LOCS_7
5420x00028C3C PA_SC_AA_MASK
5430x00028C8C CB_COLOR0_CLEAR_WORD0
5440x00028C90 CB_COLOR0_CLEAR_WORD1
5450x00028C94 CB_COLOR0_CLEAR_WORD2
5460x00028C98 CB_COLOR0_CLEAR_WORD3
5470x00028CC8 CB_COLOR1_CLEAR_WORD0
5480x00028CCC CB_COLOR1_CLEAR_WORD1
5490x00028CD0 CB_COLOR1_CLEAR_WORD2
5500x00028CD4 CB_COLOR1_CLEAR_WORD3
5510x00028D04 CB_COLOR2_CLEAR_WORD0
5520x00028D08 CB_COLOR2_CLEAR_WORD1
5530x00028D0C CB_COLOR2_CLEAR_WORD2
5540x00028D10 CB_COLOR2_CLEAR_WORD3
5550x00028D40 CB_COLOR3_CLEAR_WORD0
5560x00028D44 CB_COLOR3_CLEAR_WORD1
5570x00028D48 CB_COLOR3_CLEAR_WORD2
5580x00028D4C CB_COLOR3_CLEAR_WORD3
5590x00028D7C CB_COLOR4_CLEAR_WORD0
5600x00028D80 CB_COLOR4_CLEAR_WORD1
5610x00028D84 CB_COLOR4_CLEAR_WORD2
5620x00028D88 CB_COLOR4_CLEAR_WORD3
5630x00028DB8 CB_COLOR5_CLEAR_WORD0
5640x00028DBC CB_COLOR5_CLEAR_WORD1
5650x00028DC0 CB_COLOR5_CLEAR_WORD2
5660x00028DC4 CB_COLOR5_CLEAR_WORD3
5670x00028DF4 CB_COLOR6_CLEAR_WORD0
5680x00028DF8 CB_COLOR6_CLEAR_WORD1
5690x00028DFC CB_COLOR6_CLEAR_WORD2
5700x00028E00 CB_COLOR6_CLEAR_WORD3
5710x00028E30 CB_COLOR7_CLEAR_WORD0
5720x00028E34 CB_COLOR7_CLEAR_WORD1
5730x00028E38 CB_COLOR7_CLEAR_WORD2
5740x00028E3C CB_COLOR7_CLEAR_WORD3
5750x00028F80 SQ_ALU_CONST_BUFFER_SIZE_HS_0
5760x00028F84 SQ_ALU_CONST_BUFFER_SIZE_HS_1
5770x00028F88 SQ_ALU_CONST_BUFFER_SIZE_HS_2
5780x00028F8C SQ_ALU_CONST_BUFFER_SIZE_HS_3
5790x00028F90 SQ_ALU_CONST_BUFFER_SIZE_HS_4
5800x00028F94 SQ_ALU_CONST_BUFFER_SIZE_HS_5
5810x00028F98 SQ_ALU_CONST_BUFFER_SIZE_HS_6
5820x00028F9C SQ_ALU_CONST_BUFFER_SIZE_HS_7
5830x00028FA0 SQ_ALU_CONST_BUFFER_SIZE_HS_8
5840x00028FA4 SQ_ALU_CONST_BUFFER_SIZE_HS_9
5850x00028FA8 SQ_ALU_CONST_BUFFER_SIZE_HS_10
5860x00028FAC SQ_ALU_CONST_BUFFER_SIZE_HS_11
5870x00028FB0 SQ_ALU_CONST_BUFFER_SIZE_HS_12
5880x00028FB4 SQ_ALU_CONST_BUFFER_SIZE_HS_13
5890x00028FB8 SQ_ALU_CONST_BUFFER_SIZE_HS_14
5900x00028FBC SQ_ALU_CONST_BUFFER_SIZE_HS_15
5910x00028FC0 SQ_ALU_CONST_BUFFER_SIZE_LS_0
5920x00028FC4 SQ_ALU_CONST_BUFFER_SIZE_LS_1
5930x00028FC8 SQ_ALU_CONST_BUFFER_SIZE_LS_2
5940x00028FCC SQ_ALU_CONST_BUFFER_SIZE_LS_3
5950x00028FD0 SQ_ALU_CONST_BUFFER_SIZE_LS_4
5960x00028FD4 SQ_ALU_CONST_BUFFER_SIZE_LS_5
5970x00028FD8 SQ_ALU_CONST_BUFFER_SIZE_LS_6
5980x00028FDC SQ_ALU_CONST_BUFFER_SIZE_LS_7
5990x00028FE0 SQ_ALU_CONST_BUFFER_SIZE_LS_8
6000x00028FE4 SQ_ALU_CONST_BUFFER_SIZE_LS_9
6010x00028FE8 SQ_ALU_CONST_BUFFER_SIZE_LS_10
6020x00028FEC SQ_ALU_CONST_BUFFER_SIZE_LS_11
6030x00028FF0 SQ_ALU_CONST_BUFFER_SIZE_LS_12
6040x00028FF4 SQ_ALU_CONST_BUFFER_SIZE_LS_13
6050x00028FF8 SQ_ALU_CONST_BUFFER_SIZE_LS_14
6060x00028FFC SQ_ALU_CONST_BUFFER_SIZE_LS_15
6070x0003CFF0 SQ_VTX_BASE_VTX_LOC
6080x0003CFF4 SQ_VTX_START_INST_LOC
6090x0003FF00 SQ_TEX_SAMPLER_CLEAR
6100x0003FF04 SQ_TEX_RESOURCE_CLEAR
6110x0003FF08 SQ_LOOP_BOOL_CLEAR
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c
index 79887cac5b54..7bb4c3e52f3b 100644
--- a/drivers/gpu/drm/radeon/rs600.c
+++ b/drivers/gpu/drm/radeon/rs600.c
@@ -74,7 +74,8 @@ void rs600_pm_misc(struct radeon_device *rdev)
74 if (voltage->delay) 74 if (voltage->delay)
75 udelay(voltage->delay); 75 udelay(voltage->delay);
76 } 76 }
77 } 77 } else if (voltage->type == VOLTAGE_VDDC)
78 radeon_atom_set_voltage(rdev, voltage->vddc_id);
78 79
79 dyn_pwrmgt_sclk_length = RREG32_PLL(DYN_PWRMGT_SCLK_LENGTH); 80 dyn_pwrmgt_sclk_length = RREG32_PLL(DYN_PWRMGT_SCLK_LENGTH);
80 dyn_pwrmgt_sclk_length &= ~REDUCED_POWER_SCLK_HILEN(0xf); 81 dyn_pwrmgt_sclk_length &= ~REDUCED_POWER_SCLK_HILEN(0xf);
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index 253f24aec031..cec536c222c5 100644
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -44,7 +44,18 @@ void rv770_fini(struct radeon_device *rdev);
44 44
45void rv770_pm_misc(struct radeon_device *rdev) 45void rv770_pm_misc(struct radeon_device *rdev)
46{ 46{
47 47 int req_ps_idx = rdev->pm.requested_power_state_index;
48 int req_cm_idx = rdev->pm.requested_clock_mode_index;
49 struct radeon_power_state *ps = &rdev->pm.power_state[req_ps_idx];
50 struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage;
51
52 if ((voltage->type == VOLTAGE_SW) && voltage->voltage) {
53 if (voltage->voltage != rdev->pm.current_vddc) {
54 radeon_atom_set_voltage(rdev, voltage->voltage);
55 rdev->pm.current_vddc = voltage->voltage;
56 DRM_DEBUG("Setting: v: %d\n", voltage->voltage);
57 }
58 }
48} 59}
49 60
50/* 61/*
diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c
index 0d9a42c2394f..ef910694bd63 100644
--- a/drivers/gpu/drm/ttm/ttm_page_alloc.c
+++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c
@@ -77,7 +77,7 @@ struct ttm_page_pool {
77/** 77/**
78 * Limits for the pool. They are handled without locks because only place where 78 * Limits for the pool. They are handled without locks because only place where
79 * they may change is in sysfs store. They won't have immediate effect anyway 79 * they may change is in sysfs store. They won't have immediate effect anyway
80 * so forcing serialiazation to access them is pointless. 80 * so forcing serialization to access them is pointless.
81 */ 81 */
82 82
83struct ttm_pool_opts { 83struct ttm_pool_opts {
@@ -165,16 +165,18 @@ static ssize_t ttm_pool_store(struct kobject *kobj,
165 m->options.small = val; 165 m->options.small = val;
166 else if (attr == &ttm_page_pool_alloc_size) { 166 else if (attr == &ttm_page_pool_alloc_size) {
167 if (val > NUM_PAGES_TO_ALLOC*8) { 167 if (val > NUM_PAGES_TO_ALLOC*8) {
168 printk(KERN_ERR "[ttm] Setting allocation size to %lu " 168 printk(KERN_ERR TTM_PFX
169 "is not allowed. Recomended size is " 169 "Setting allocation size to %lu "
170 "%lu\n", 170 "is not allowed. Recommended size is "
171 NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 7), 171 "%lu\n",
172 NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 10)); 172 NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 7),
173 NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 10));
173 return size; 174 return size;
174 } else if (val > NUM_PAGES_TO_ALLOC) { 175 } else if (val > NUM_PAGES_TO_ALLOC) {
175 printk(KERN_WARNING "[ttm] Setting allocation size to " 176 printk(KERN_WARNING TTM_PFX
176 "larger than %lu is not recomended.\n", 177 "Setting allocation size to "
177 NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 10)); 178 "larger than %lu is not recommended.\n",
179 NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 10));
178 } 180 }
179 m->options.alloc_size = val; 181 m->options.alloc_size = val;
180 } 182 }
@@ -277,7 +279,7 @@ static void ttm_pages_put(struct page *pages[], unsigned npages)
277{ 279{
278 unsigned i; 280 unsigned i;
279 if (set_pages_array_wb(pages, npages)) 281 if (set_pages_array_wb(pages, npages))
280 printk(KERN_ERR "[ttm] Failed to set %d pages to wb!\n", 282 printk(KERN_ERR TTM_PFX "Failed to set %d pages to wb!\n",
281 npages); 283 npages);
282 for (i = 0; i < npages; ++i) 284 for (i = 0; i < npages; ++i)
283 __free_page(pages[i]); 285 __free_page(pages[i]);
@@ -313,7 +315,8 @@ static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free)
313 pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), 315 pages_to_free = kmalloc(npages_to_free * sizeof(struct page *),
314 GFP_KERNEL); 316 GFP_KERNEL);
315 if (!pages_to_free) { 317 if (!pages_to_free) {
316 printk(KERN_ERR "Failed to allocate memory for pool free operation.\n"); 318 printk(KERN_ERR TTM_PFX
319 "Failed to allocate memory for pool free operation.\n");
317 return 0; 320 return 0;
318 } 321 }
319 322
@@ -390,7 +393,7 @@ static int ttm_pool_get_num_unused_pages(void)
390} 393}
391 394
392/** 395/**
393 * Calback for mm to request pool to reduce number of page held. 396 * Callback for mm to request pool to reduce number of page held.
394 */ 397 */
395static int ttm_pool_mm_shrink(int shrink_pages, gfp_t gfp_mask) 398static int ttm_pool_mm_shrink(int shrink_pages, gfp_t gfp_mask)
396{ 399{
@@ -433,14 +436,16 @@ static int ttm_set_pages_caching(struct page **pages,
433 case tt_uncached: 436 case tt_uncached:
434 r = set_pages_array_uc(pages, cpages); 437 r = set_pages_array_uc(pages, cpages);
435 if (r) 438 if (r)
436 printk(KERN_ERR "[ttm] Failed to set %d pages to uc!\n", 439 printk(KERN_ERR TTM_PFX
437 cpages); 440 "Failed to set %d pages to uc!\n",
441 cpages);
438 break; 442 break;
439 case tt_wc: 443 case tt_wc:
440 r = set_pages_array_wc(pages, cpages); 444 r = set_pages_array_wc(pages, cpages);
441 if (r) 445 if (r)
442 printk(KERN_ERR "[ttm] Failed to set %d pages to wc!\n", 446 printk(KERN_ERR TTM_PFX
443 cpages); 447 "Failed to set %d pages to wc!\n",
448 cpages);
444 break; 449 break;
445 default: 450 default:
446 break; 451 break;
@@ -458,7 +463,7 @@ static void ttm_handle_caching_state_failure(struct list_head *pages,
458 struct page **failed_pages, unsigned cpages) 463 struct page **failed_pages, unsigned cpages)
459{ 464{
460 unsigned i; 465 unsigned i;
461 /* Failed pages has to be reed */ 466 /* Failed pages have to be freed */
462 for (i = 0; i < cpages; ++i) { 467 for (i = 0; i < cpages; ++i) {
463 list_del(&failed_pages[i]->lru); 468 list_del(&failed_pages[i]->lru);
464 __free_page(failed_pages[i]); 469 __free_page(failed_pages[i]);
@@ -485,7 +490,8 @@ static int ttm_alloc_new_pages(struct list_head *pages, int gfp_flags,
485 caching_array = kmalloc(max_cpages*sizeof(struct page *), GFP_KERNEL); 490 caching_array = kmalloc(max_cpages*sizeof(struct page *), GFP_KERNEL);
486 491
487 if (!caching_array) { 492 if (!caching_array) {
488 printk(KERN_ERR "[ttm] unable to allocate table for new pages."); 493 printk(KERN_ERR TTM_PFX
494 "Unable to allocate table for new pages.");
489 return -ENOMEM; 495 return -ENOMEM;
490 } 496 }
491 497
@@ -493,12 +499,13 @@ static int ttm_alloc_new_pages(struct list_head *pages, int gfp_flags,
493 p = alloc_page(gfp_flags); 499 p = alloc_page(gfp_flags);
494 500
495 if (!p) { 501 if (!p) {
496 printk(KERN_ERR "[ttm] unable to get page %u\n", i); 502 printk(KERN_ERR TTM_PFX "Unable to get page %u.\n", i);
497 503
498 /* store already allocated pages in the pool after 504 /* store already allocated pages in the pool after
499 * setting the caching state */ 505 * setting the caching state */
500 if (cpages) { 506 if (cpages) {
501 r = ttm_set_pages_caching(caching_array, cstate, cpages); 507 r = ttm_set_pages_caching(caching_array,
508 cstate, cpages);
502 if (r) 509 if (r)
503 ttm_handle_caching_state_failure(pages, 510 ttm_handle_caching_state_failure(pages,
504 ttm_flags, cstate, 511 ttm_flags, cstate,
@@ -590,7 +597,8 @@ static void ttm_page_pool_fill_locked(struct ttm_page_pool *pool,
590 ++pool->nrefills; 597 ++pool->nrefills;
591 pool->npages += alloc_size; 598 pool->npages += alloc_size;
592 } else { 599 } else {
593 printk(KERN_ERR "[ttm] Failed to fill pool (%p).", pool); 600 printk(KERN_ERR TTM_PFX
601 "Failed to fill pool (%p).", pool);
594 /* If we have any pages left put them to the pool. */ 602 /* If we have any pages left put them to the pool. */
595 list_for_each_entry(p, &pool->list, lru) { 603 list_for_each_entry(p, &pool->list, lru) {
596 ++cpages; 604 ++cpages;
@@ -671,13 +679,14 @@ int ttm_get_pages(struct list_head *pages, int flags,
671 if (flags & TTM_PAGE_FLAG_DMA32) 679 if (flags & TTM_PAGE_FLAG_DMA32)
672 gfp_flags |= GFP_DMA32; 680 gfp_flags |= GFP_DMA32;
673 else 681 else
674 gfp_flags |= __GFP_HIGHMEM; 682 gfp_flags |= GFP_HIGHUSER;
675 683
676 for (r = 0; r < count; ++r) { 684 for (r = 0; r < count; ++r) {
677 p = alloc_page(gfp_flags); 685 p = alloc_page(gfp_flags);
678 if (!p) { 686 if (!p) {
679 687
680 printk(KERN_ERR "[ttm] unable to allocate page."); 688 printk(KERN_ERR TTM_PFX
689 "Unable to allocate page.");
681 return -ENOMEM; 690 return -ENOMEM;
682 } 691 }
683 692
@@ -709,8 +718,9 @@ int ttm_get_pages(struct list_head *pages, int flags,
709 if (r) { 718 if (r) {
710 /* If there is any pages in the list put them back to 719 /* If there is any pages in the list put them back to
711 * the pool. */ 720 * the pool. */
712 printk(KERN_ERR "[ttm] Failed to allocate extra pages " 721 printk(KERN_ERR TTM_PFX
713 "for large request."); 722 "Failed to allocate extra pages "
723 "for large request.");
714 ttm_put_pages(pages, 0, flags, cstate); 724 ttm_put_pages(pages, 0, flags, cstate);
715 return r; 725 return r;
716 } 726 }
@@ -778,7 +788,7 @@ int ttm_page_alloc_init(struct ttm_mem_global *glob, unsigned max_pages)
778 if (atomic_add_return(1, &_manager.page_alloc_inited) > 1) 788 if (atomic_add_return(1, &_manager.page_alloc_inited) > 1)
779 return 0; 789 return 0;
780 790
781 printk(KERN_INFO "[ttm] Initializing pool allocator.\n"); 791 printk(KERN_INFO TTM_PFX "Initializing pool allocator.\n");
782 792
783 ttm_page_pool_init_locked(&_manager.wc_pool, GFP_HIGHUSER, "wc"); 793 ttm_page_pool_init_locked(&_manager.wc_pool, GFP_HIGHUSER, "wc");
784 794
@@ -813,7 +823,7 @@ void ttm_page_alloc_fini()
813 if (atomic_sub_return(1, &_manager.page_alloc_inited) > 0) 823 if (atomic_sub_return(1, &_manager.page_alloc_inited) > 0)
814 return; 824 return;
815 825
816 printk(KERN_INFO "[ttm] Finilizing pool allocator.\n"); 826 printk(KERN_INFO TTM_PFX "Finalizing pool allocator.\n");
817 ttm_pool_mm_shrink_fini(&_manager); 827 ttm_pool_mm_shrink_fini(&_manager);
818 828
819 for (i = 0; i < NUM_POOLS; ++i) 829 for (i = 0; i < NUM_POOLS; ++i)
diff --git a/drivers/gpu/drm/vmwgfx/Makefile b/drivers/gpu/drm/vmwgfx/Makefile
index 1a3cb6816d1c..4505e17df3f5 100644
--- a/drivers/gpu/drm/vmwgfx/Makefile
+++ b/drivers/gpu/drm/vmwgfx/Makefile
@@ -4,6 +4,6 @@ ccflags-y := -Iinclude/drm
4vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \ 4vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \
5 vmwgfx_fb.o vmwgfx_ioctl.o vmwgfx_resource.o vmwgfx_buffer.o \ 5 vmwgfx_fb.o vmwgfx_ioctl.o vmwgfx_resource.o vmwgfx_buffer.o \
6 vmwgfx_fifo.o vmwgfx_irq.o vmwgfx_ldu.o vmwgfx_ttm_glue.o \ 6 vmwgfx_fifo.o vmwgfx_irq.o vmwgfx_ldu.o vmwgfx_ttm_glue.o \
7 vmwgfx_overlay.o 7 vmwgfx_overlay.o vmwgfx_fence.o
8 8
9obj-$(CONFIG_DRM_VMWGFX) := vmwgfx.o 9obj-$(CONFIG_DRM_VMWGFX) := vmwgfx.o
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 0c9c0811f42d..b793c8c9acb3 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -88,6 +88,9 @@
88#define DRM_IOCTL_VMW_FENCE_WAIT \ 88#define DRM_IOCTL_VMW_FENCE_WAIT \
89 DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_FENCE_WAIT, \ 89 DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_FENCE_WAIT, \
90 struct drm_vmw_fence_wait_arg) 90 struct drm_vmw_fence_wait_arg)
91#define DRM_IOCTL_VMW_UPDATE_LAYOUT \
92 DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_UPDATE_LAYOUT, \
93 struct drm_vmw_update_layout_arg)
91 94
92 95
93/** 96/**
@@ -135,7 +138,9 @@ static struct drm_ioctl_desc vmw_ioctls[] = {
135 VMW_IOCTL_DEF(DRM_IOCTL_VMW_FIFO_DEBUG, vmw_fifo_debug_ioctl, 138 VMW_IOCTL_DEF(DRM_IOCTL_VMW_FIFO_DEBUG, vmw_fifo_debug_ioctl,
136 DRM_AUTH | DRM_ROOT_ONLY | DRM_MASTER | DRM_UNLOCKED), 139 DRM_AUTH | DRM_ROOT_ONLY | DRM_MASTER | DRM_UNLOCKED),
137 VMW_IOCTL_DEF(DRM_IOCTL_VMW_FENCE_WAIT, vmw_fence_wait_ioctl, 140 VMW_IOCTL_DEF(DRM_IOCTL_VMW_FENCE_WAIT, vmw_fence_wait_ioctl,
138 DRM_AUTH | DRM_UNLOCKED) 141 DRM_AUTH | DRM_UNLOCKED),
142 VMW_IOCTL_DEF(DRM_IOCTL_VMW_UPDATE_LAYOUT, vmw_kms_update_layout_ioctl,
143 DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED)
139}; 144};
140 145
141static struct pci_device_id vmw_pci_id_list[] = { 146static struct pci_device_id vmw_pci_id_list[] = {
@@ -318,6 +323,15 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
318 goto out_err3; 323 goto out_err3;
319 } 324 }
320 325
326 /* Need mmio memory to check for fifo pitchlock cap. */
327 if (!(dev_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) &&
328 !(dev_priv->capabilities & SVGA_CAP_PITCHLOCK) &&
329 !vmw_fifo_have_pitchlock(dev_priv)) {
330 ret = -ENOSYS;
331 DRM_ERROR("Hardware has no pitchlock\n");
332 goto out_err4;
333 }
334
321 dev_priv->tdev = ttm_object_device_init 335 dev_priv->tdev = ttm_object_device_init
322 (dev_priv->mem_global_ref.object, 12); 336 (dev_priv->mem_global_ref.object, 12);
323 337
@@ -399,8 +413,6 @@ static int vmw_driver_unload(struct drm_device *dev)
399{ 413{
400 struct vmw_private *dev_priv = vmw_priv(dev); 414 struct vmw_private *dev_priv = vmw_priv(dev);
401 415
402 DRM_INFO(VMWGFX_DRIVER_NAME " unload.\n");
403
404 unregister_pm_notifier(&dev_priv->pm_nb); 416 unregister_pm_notifier(&dev_priv->pm_nb);
405 417
406 vmw_fb_close(dev_priv); 418 vmw_fb_close(dev_priv);
@@ -546,7 +558,6 @@ static int vmw_master_create(struct drm_device *dev,
546{ 558{
547 struct vmw_master *vmaster; 559 struct vmw_master *vmaster;
548 560
549 DRM_INFO("Master create.\n");
550 vmaster = kzalloc(sizeof(*vmaster), GFP_KERNEL); 561 vmaster = kzalloc(sizeof(*vmaster), GFP_KERNEL);
551 if (unlikely(vmaster == NULL)) 562 if (unlikely(vmaster == NULL))
552 return -ENOMEM; 563 return -ENOMEM;
@@ -563,7 +574,6 @@ static void vmw_master_destroy(struct drm_device *dev,
563{ 574{
564 struct vmw_master *vmaster = vmw_master(master); 575 struct vmw_master *vmaster = vmw_master(master);
565 576
566 DRM_INFO("Master destroy.\n");
567 master->driver_priv = NULL; 577 master->driver_priv = NULL;
568 kfree(vmaster); 578 kfree(vmaster);
569} 579}
@@ -579,8 +589,6 @@ static int vmw_master_set(struct drm_device *dev,
579 struct vmw_master *vmaster = vmw_master(file_priv->master); 589 struct vmw_master *vmaster = vmw_master(file_priv->master);
580 int ret = 0; 590 int ret = 0;
581 591
582 DRM_INFO("Master set.\n");
583
584 if (active) { 592 if (active) {
585 BUG_ON(active != &dev_priv->fbdev_master); 593 BUG_ON(active != &dev_priv->fbdev_master);
586 ret = ttm_vt_lock(&active->lock, false, vmw_fp->tfile); 594 ret = ttm_vt_lock(&active->lock, false, vmw_fp->tfile);
@@ -622,8 +630,6 @@ static void vmw_master_drop(struct drm_device *dev,
622 struct vmw_master *vmaster = vmw_master(file_priv->master); 630 struct vmw_master *vmaster = vmw_master(file_priv->master);
623 int ret; 631 int ret;
624 632
625 DRM_INFO("Master drop.\n");
626
627 /** 633 /**
628 * Make sure the master doesn't disappear while we have 634 * Make sure the master doesn't disappear while we have
629 * it locked. 635 * it locked.
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index 356dc935ec13..eaad52095339 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -41,12 +41,13 @@
41 41
42#define VMWGFX_DRIVER_DATE "20100209" 42#define VMWGFX_DRIVER_DATE "20100209"
43#define VMWGFX_DRIVER_MAJOR 1 43#define VMWGFX_DRIVER_MAJOR 1
44#define VMWGFX_DRIVER_MINOR 0 44#define VMWGFX_DRIVER_MINOR 2
45#define VMWGFX_DRIVER_PATCHLEVEL 0 45#define VMWGFX_DRIVER_PATCHLEVEL 0
46#define VMWGFX_FILE_PAGE_OFFSET 0x00100000 46#define VMWGFX_FILE_PAGE_OFFSET 0x00100000
47#define VMWGFX_FIFO_STATIC_SIZE (1024*1024) 47#define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
48#define VMWGFX_MAX_RELOCATIONS 2048 48#define VMWGFX_MAX_RELOCATIONS 2048
49#define VMWGFX_MAX_GMRS 2048 49#define VMWGFX_MAX_GMRS 2048
50#define VMWGFX_MAX_DISPLAYS 16
50 51
51struct vmw_fpriv { 52struct vmw_fpriv {
52 struct drm_master *locked_master; 53 struct drm_master *locked_master;
@@ -102,6 +103,13 @@ struct vmw_surface {
102 struct vmw_cursor_snooper snooper; 103 struct vmw_cursor_snooper snooper;
103}; 104};
104 105
106struct vmw_fence_queue {
107 struct list_head head;
108 struct timespec lag;
109 struct timespec lag_time;
110 spinlock_t lock;
111};
112
105struct vmw_fifo_state { 113struct vmw_fifo_state {
106 unsigned long reserved_size; 114 unsigned long reserved_size;
107 __le32 *dynamic_buffer; 115 __le32 *dynamic_buffer;
@@ -115,6 +123,7 @@ struct vmw_fifo_state {
115 uint32_t capabilities; 123 uint32_t capabilities;
116 struct mutex fifo_mutex; 124 struct mutex fifo_mutex;
117 struct rw_semaphore rwsem; 125 struct rw_semaphore rwsem;
126 struct vmw_fence_queue fence_queue;
118}; 127};
119 128
120struct vmw_relocation { 129struct vmw_relocation {
@@ -144,6 +153,14 @@ struct vmw_master {
144 struct ttm_lock lock; 153 struct ttm_lock lock;
145}; 154};
146 155
156struct vmw_vga_topology_state {
157 uint32_t width;
158 uint32_t height;
159 uint32_t primary;
160 uint32_t pos_x;
161 uint32_t pos_y;
162};
163
147struct vmw_private { 164struct vmw_private {
148 struct ttm_bo_device bdev; 165 struct ttm_bo_device bdev;
149 struct ttm_bo_global_ref bo_global_ref; 166 struct ttm_bo_global_ref bo_global_ref;
@@ -171,14 +188,19 @@ struct vmw_private {
171 * VGA registers. 188 * VGA registers.
172 */ 189 */
173 190
191 struct vmw_vga_topology_state vga_save[VMWGFX_MAX_DISPLAYS];
174 uint32_t vga_width; 192 uint32_t vga_width;
175 uint32_t vga_height; 193 uint32_t vga_height;
176 uint32_t vga_depth; 194 uint32_t vga_depth;
177 uint32_t vga_bpp; 195 uint32_t vga_bpp;
178 uint32_t vga_pseudo; 196 uint32_t vga_pseudo;
179 uint32_t vga_red_mask; 197 uint32_t vga_red_mask;
180 uint32_t vga_blue_mask;
181 uint32_t vga_green_mask; 198 uint32_t vga_green_mask;
199 uint32_t vga_blue_mask;
200 uint32_t vga_bpl;
201 uint32_t vga_pitchlock;
202
203 uint32_t num_displays;
182 204
183 /* 205 /*
184 * Framebuffer info. 206 * Framebuffer info.
@@ -393,6 +415,7 @@ extern int vmw_fifo_send_fence(struct vmw_private *dev_priv,
393extern void vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason); 415extern void vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason);
394extern int vmw_fifo_mmap(struct file *filp, struct vm_area_struct *vma); 416extern int vmw_fifo_mmap(struct file *filp, struct vm_area_struct *vma);
395extern bool vmw_fifo_have_3d(struct vmw_private *dev_priv); 417extern bool vmw_fifo_have_3d(struct vmw_private *dev_priv);
418extern bool vmw_fifo_have_pitchlock(struct vmw_private *dev_priv);
396 419
397/** 420/**
398 * TTM glue - vmwgfx_ttm_glue.c 421 * TTM glue - vmwgfx_ttm_glue.c
@@ -441,6 +464,23 @@ extern int vmw_fallback_wait(struct vmw_private *dev_priv,
441 uint32_t sequence, 464 uint32_t sequence,
442 bool interruptible, 465 bool interruptible,
443 unsigned long timeout); 466 unsigned long timeout);
467extern void vmw_update_sequence(struct vmw_private *dev_priv,
468 struct vmw_fifo_state *fifo_state);
469
470
471/**
472 * Rudimentary fence objects currently used only for throttling -
473 * vmwgfx_fence.c
474 */
475
476extern void vmw_fence_queue_init(struct vmw_fence_queue *queue);
477extern void vmw_fence_queue_takedown(struct vmw_fence_queue *queue);
478extern int vmw_fence_push(struct vmw_fence_queue *queue,
479 uint32_t sequence);
480extern int vmw_fence_pull(struct vmw_fence_queue *queue,
481 uint32_t signaled_sequence);
482extern int vmw_wait_lag(struct vmw_private *dev_priv,
483 struct vmw_fence_queue *queue, uint32_t us);
444 484
445/** 485/**
446 * Kernel framebuffer - vmwgfx_fb.c 486 * Kernel framebuffer - vmwgfx_fb.c
@@ -466,6 +506,11 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf,
466 struct ttm_object_file *tfile, 506 struct ttm_object_file *tfile,
467 struct ttm_buffer_object *bo, 507 struct ttm_buffer_object *bo,
468 SVGA3dCmdHeader *header); 508 SVGA3dCmdHeader *header);
509void vmw_kms_write_svga(struct vmw_private *vmw_priv,
510 unsigned width, unsigned height, unsigned pitch,
511 unsigned bbp, unsigned depth);
512int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
513 struct drm_file *file_priv);
469 514
470/** 515/**
471 * Overlay control - vmwgfx_overlay.c 516 * Overlay control - vmwgfx_overlay.c
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
index dbd36b8910cf..8e396850513c 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -644,6 +644,7 @@ int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
644 ret = copy_from_user(cmd, user_cmd, arg->command_size); 644 ret = copy_from_user(cmd, user_cmd, arg->command_size);
645 645
646 if (unlikely(ret != 0)) { 646 if (unlikely(ret != 0)) {
647 ret = -EFAULT;
647 DRM_ERROR("Failed copying commands.\n"); 648 DRM_ERROR("Failed copying commands.\n");
648 goto out_commit; 649 goto out_commit;
649 } 650 }
@@ -669,6 +670,15 @@ int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
669 goto out_err; 670 goto out_err;
670 671
671 vmw_apply_relocations(sw_context); 672 vmw_apply_relocations(sw_context);
673
674 if (arg->throttle_us) {
675 ret = vmw_wait_lag(dev_priv, &dev_priv->fifo.fence_queue,
676 arg->throttle_us);
677
678 if (unlikely(ret != 0))
679 goto out_err;
680 }
681
672 vmw_fifo_commit(dev_priv, arg->command_size); 682 vmw_fifo_commit(dev_priv, arg->command_size);
673 683
674 ret = vmw_fifo_send_fence(dev_priv, &sequence); 684 ret = vmw_fifo_send_fence(dev_priv, &sequence);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
index 7421aaad8d09..b0866f04ec76 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
@@ -132,16 +132,14 @@ static int vmw_fb_check_var(struct fb_var_screeninfo *var,
132 return -EINVAL; 132 return -EINVAL;
133 } 133 }
134 134
135 /* without multimon its hard to resize */ 135 if (!(vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) &&
136 if (!(vmw_priv->capabilities & SVGA_CAP_MULTIMON) && 136 (var->xoffset != 0 || var->yoffset != 0)) {
137 (var->xres != par->max_width || 137 DRM_ERROR("Can not handle panning without display topology\n");
138 var->yres != par->max_height)) {
139 DRM_ERROR("Tried to resize, but we don't have multimon\n");
140 return -EINVAL; 138 return -EINVAL;
141 } 139 }
142 140
143 if (var->xres > par->max_width || 141 if ((var->xoffset + var->xres) > par->max_width ||
144 var->yres > par->max_height) { 142 (var->yoffset + var->yres) > par->max_height) {
145 DRM_ERROR("Requested geom can not fit in framebuffer\n"); 143 DRM_ERROR("Requested geom can not fit in framebuffer\n");
146 return -EINVAL; 144 return -EINVAL;
147 } 145 }
@@ -154,27 +152,11 @@ static int vmw_fb_set_par(struct fb_info *info)
154 struct vmw_fb_par *par = info->par; 152 struct vmw_fb_par *par = info->par;
155 struct vmw_private *vmw_priv = par->vmw_priv; 153 struct vmw_private *vmw_priv = par->vmw_priv;
156 154
157 if (vmw_priv->capabilities & SVGA_CAP_MULTIMON) { 155 vmw_kms_write_svga(vmw_priv, info->var.xres, info->var.yres,
158 vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1); 156 info->fix.line_length,
159 vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0); 157 par->bpp, par->depth);
160 vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true); 158 if (vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) {
161 vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, 0);
162 vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_Y, 0);
163 vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, 0);
164 vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, 0);
165 vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
166
167 vmw_write(vmw_priv, SVGA_REG_ENABLE, 1);
168 vmw_write(vmw_priv, SVGA_REG_WIDTH, par->max_width);
169 vmw_write(vmw_priv, SVGA_REG_HEIGHT, par->max_height);
170 vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, par->bpp);
171 vmw_write(vmw_priv, SVGA_REG_DEPTH, par->depth);
172 vmw_write(vmw_priv, SVGA_REG_RED_MASK, 0x00ff0000);
173 vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
174 vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
175
176 /* TODO check if pitch and offset changes */ 159 /* TODO check if pitch and offset changes */
177
178 vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1); 160 vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
179 vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0); 161 vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0);
180 vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true); 162 vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
@@ -183,13 +165,13 @@ static int vmw_fb_set_par(struct fb_info *info)
183 vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, info->var.xres); 165 vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, info->var.xres);
184 vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, info->var.yres); 166 vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, info->var.yres);
185 vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID); 167 vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
186 } else {
187 vmw_write(vmw_priv, SVGA_REG_WIDTH, info->var.xres);
188 vmw_write(vmw_priv, SVGA_REG_HEIGHT, info->var.yres);
189
190 /* TODO check if pitch and offset changes */
191 } 168 }
192 169
170 /* This is really helpful since if this fails the user
171 * can probably not see anything on the screen.
172 */
173 WARN_ON(vmw_read(vmw_priv, SVGA_REG_FB_OFFSET) != 0);
174
193 return 0; 175 return 0;
194} 176}
195 177
@@ -416,48 +398,23 @@ int vmw_fb_init(struct vmw_private *vmw_priv)
416 unsigned fb_bbp, fb_depth, fb_offset, fb_pitch, fb_size; 398 unsigned fb_bbp, fb_depth, fb_offset, fb_pitch, fb_size;
417 int ret; 399 int ret;
418 400
401 /* XXX These shouldn't be hardcoded. */
419 initial_width = 800; 402 initial_width = 800;
420 initial_height = 600; 403 initial_height = 600;
421 404
422 fb_bbp = 32; 405 fb_bbp = 32;
423 fb_depth = 24; 406 fb_depth = 24;
424 407
425 if (vmw_priv->capabilities & SVGA_CAP_MULTIMON) { 408 /* XXX As shouldn't these be as well. */
426 fb_width = min(vmw_priv->fb_max_width, (unsigned)2048); 409 fb_width = min(vmw_priv->fb_max_width, (unsigned)2048);
427 fb_height = min(vmw_priv->fb_max_height, (unsigned)2048); 410 fb_height = min(vmw_priv->fb_max_height, (unsigned)2048);
428 } else {
429 fb_width = min(vmw_priv->fb_max_width, initial_width);
430 fb_height = min(vmw_priv->fb_max_height, initial_height);
431 }
432 411
433 initial_width = min(fb_width, initial_width); 412 initial_width = min(fb_width, initial_width);
434 initial_height = min(fb_height, initial_height); 413 initial_height = min(fb_height, initial_height);
435 414
436 vmw_write(vmw_priv, SVGA_REG_WIDTH, fb_width); 415 fb_pitch = fb_width * fb_bbp / 8;
437 vmw_write(vmw_priv, SVGA_REG_HEIGHT, fb_height); 416 fb_size = fb_pitch * fb_height;
438 vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, fb_bbp);
439 vmw_write(vmw_priv, SVGA_REG_DEPTH, fb_depth);
440 vmw_write(vmw_priv, SVGA_REG_RED_MASK, 0x00ff0000);
441 vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
442 vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
443
444 fb_size = vmw_read(vmw_priv, SVGA_REG_FB_SIZE);
445 fb_offset = vmw_read(vmw_priv, SVGA_REG_FB_OFFSET); 417 fb_offset = vmw_read(vmw_priv, SVGA_REG_FB_OFFSET);
446 fb_pitch = vmw_read(vmw_priv, SVGA_REG_BYTES_PER_LINE);
447
448 DRM_DEBUG("width %u\n", vmw_read(vmw_priv, SVGA_REG_MAX_WIDTH));
449 DRM_DEBUG("height %u\n", vmw_read(vmw_priv, SVGA_REG_MAX_HEIGHT));
450 DRM_DEBUG("width %u\n", vmw_read(vmw_priv, SVGA_REG_WIDTH));
451 DRM_DEBUG("height %u\n", vmw_read(vmw_priv, SVGA_REG_HEIGHT));
452 DRM_DEBUG("bpp %u\n", vmw_read(vmw_priv, SVGA_REG_BITS_PER_PIXEL));
453 DRM_DEBUG("depth %u\n", vmw_read(vmw_priv, SVGA_REG_DEPTH));
454 DRM_DEBUG("bpl %u\n", vmw_read(vmw_priv, SVGA_REG_BYTES_PER_LINE));
455 DRM_DEBUG("r mask %08x\n", vmw_read(vmw_priv, SVGA_REG_RED_MASK));
456 DRM_DEBUG("g mask %08x\n", vmw_read(vmw_priv, SVGA_REG_GREEN_MASK));
457 DRM_DEBUG("b mask %08x\n", vmw_read(vmw_priv, SVGA_REG_BLUE_MASK));
458 DRM_DEBUG("fb_offset 0x%08x\n", fb_offset);
459 DRM_DEBUG("fb_pitch %u\n", fb_pitch);
460 DRM_DEBUG("fb_size %u kiB\n", fb_size / 1024);
461 418
462 info = framebuffer_alloc(sizeof(*par), device); 419 info = framebuffer_alloc(sizeof(*par), device);
463 if (!info) 420 if (!info)
@@ -659,6 +616,10 @@ int vmw_dmabuf_to_start_of_vram(struct vmw_private *vmw_priv,
659 goto err_unlock; 616 goto err_unlock;
660 617
661 ret = ttm_bo_validate(bo, &ne_placement, false, false, false); 618 ret = ttm_bo_validate(bo, &ne_placement, false, false, false);
619
620 /* Could probably bug on */
621 WARN_ON(bo->offset != 0);
622
662 ttm_bo_unreserve(bo); 623 ttm_bo_unreserve(bo);
663err_unlock: 624err_unlock:
664 ttm_write_unlock(&vmw_priv->active_master->lock); 625 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
index 000000000000..61eacc1b5ca3
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
@@ -0,0 +1,173 @@
1/**************************************************************************
2 *
3 * Copyright (C) 2010 VMware, Inc., Palo Alto, CA., USA
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 * USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28
29#include "vmwgfx_drv.h"
30
31struct vmw_fence {
32 struct list_head head;
33 uint32_t sequence;
34 struct timespec submitted;
35};
36
37void vmw_fence_queue_init(struct vmw_fence_queue *queue)
38{
39 INIT_LIST_HEAD(&queue->head);
40 queue->lag = ns_to_timespec(0);
41 getrawmonotonic(&queue->lag_time);
42 spin_lock_init(&queue->lock);
43}
44
45void vmw_fence_queue_takedown(struct vmw_fence_queue *queue)
46{
47 struct vmw_fence *fence, *next;
48
49 spin_lock(&queue->lock);
50 list_for_each_entry_safe(fence, next, &queue->head, head) {
51 kfree(fence);
52 }
53 spin_unlock(&queue->lock);
54}
55
56int vmw_fence_push(struct vmw_fence_queue *queue,
57 uint32_t sequence)
58{
59 struct vmw_fence *fence = kmalloc(sizeof(*fence), GFP_KERNEL);
60
61 if (unlikely(!fence))
62 return -ENOMEM;
63
64 fence->sequence = sequence;
65 getrawmonotonic(&fence->submitted);
66 spin_lock(&queue->lock);
67 list_add_tail(&fence->head, &queue->head);
68 spin_unlock(&queue->lock);
69
70 return 0;
71}
72
73int vmw_fence_pull(struct vmw_fence_queue *queue,
74 uint32_t signaled_sequence)
75{
76 struct vmw_fence *fence, *next;
77 struct timespec now;
78 bool updated = false;
79
80 spin_lock(&queue->lock);
81 getrawmonotonic(&now);
82
83 if (list_empty(&queue->head)) {
84 queue->lag = ns_to_timespec(0);
85 queue->lag_time = now;
86 updated = true;
87 goto out_unlock;
88 }
89
90 list_for_each_entry_safe(fence, next, &queue->head, head) {
91 if (signaled_sequence - fence->sequence > (1 << 30))
92 continue;
93
94 queue->lag = timespec_sub(now, fence->submitted);
95 queue->lag_time = now;
96 updated = true;
97 list_del(&fence->head);
98 kfree(fence);
99 }
100
101out_unlock:
102 spin_unlock(&queue->lock);
103
104 return (updated) ? 0 : -EBUSY;
105}
106
107static struct timespec vmw_timespec_add(struct timespec t1,
108 struct timespec t2)
109{
110 t1.tv_sec += t2.tv_sec;
111 t1.tv_nsec += t2.tv_nsec;
112 if (t1.tv_nsec >= 1000000000L) {
113 t1.tv_sec += 1;
114 t1.tv_nsec -= 1000000000L;
115 }
116
117 return t1;
118}
119
120static struct timespec vmw_fifo_lag(struct vmw_fence_queue *queue)
121{
122 struct timespec now;
123
124 spin_lock(&queue->lock);
125 getrawmonotonic(&now);
126 queue->lag = vmw_timespec_add(queue->lag,
127 timespec_sub(now, queue->lag_time));
128 queue->lag_time = now;
129 spin_unlock(&queue->lock);
130 return queue->lag;
131}
132
133
134static bool vmw_lag_lt(struct vmw_fence_queue *queue,
135 uint32_t us)
136{
137 struct timespec lag, cond;
138
139 cond = ns_to_timespec((s64) us * 1000);
140 lag = vmw_fifo_lag(queue);
141 return (timespec_compare(&lag, &cond) < 1);
142}
143
144int vmw_wait_lag(struct vmw_private *dev_priv,
145 struct vmw_fence_queue *queue, uint32_t us)
146{
147 struct vmw_fence *fence;
148 uint32_t sequence;
149 int ret;
150
151 while (!vmw_lag_lt(queue, us)) {
152 spin_lock(&queue->lock);
153 if (list_empty(&queue->head))
154 sequence = atomic_read(&dev_priv->fence_seq);
155 else {
156 fence = list_first_entry(&queue->head,
157 struct vmw_fence, head);
158 sequence = fence->sequence;
159 }
160 spin_unlock(&queue->lock);
161
162 ret = vmw_wait_fence(dev_priv, false, sequence, true,
163 3*HZ);
164
165 if (unlikely(ret != 0))
166 return ret;
167
168 (void) vmw_fence_pull(queue, sequence);
169 }
170 return 0;
171}
172
173
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
index 39d43a01d846..e6a1eb7ea954 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
@@ -34,6 +34,9 @@ bool vmw_fifo_have_3d(struct vmw_private *dev_priv)
34 __le32 __iomem *fifo_mem = dev_priv->mmio_virt; 34 __le32 __iomem *fifo_mem = dev_priv->mmio_virt;
35 uint32_t fifo_min, hwversion; 35 uint32_t fifo_min, hwversion;
36 36
37 if (!(dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO))
38 return false;
39
37 fifo_min = ioread32(fifo_mem + SVGA_FIFO_MIN); 40 fifo_min = ioread32(fifo_mem + SVGA_FIFO_MIN);
38 if (fifo_min <= SVGA_FIFO_3D_HWVERSION * sizeof(unsigned int)) 41 if (fifo_min <= SVGA_FIFO_3D_HWVERSION * sizeof(unsigned int))
39 return false; 42 return false;
@@ -48,6 +51,21 @@ bool vmw_fifo_have_3d(struct vmw_private *dev_priv)
48 return true; 51 return true;
49} 52}
50 53
54bool vmw_fifo_have_pitchlock(struct vmw_private *dev_priv)
55{
56 __le32 __iomem *fifo_mem = dev_priv->mmio_virt;
57 uint32_t caps;
58
59 if (!(dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO))
60 return false;
61
62 caps = ioread32(fifo_mem + SVGA_FIFO_CAPABILITIES);
63 if (caps & SVGA_FIFO_CAP_PITCHLOCK)
64 return true;
65
66 return false;
67}
68
51int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo) 69int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
52{ 70{
53 __le32 __iomem *fifo_mem = dev_priv->mmio_virt; 71 __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)
120 138
121 atomic_set(&dev_priv->fence_seq, dev_priv->last_read_sequence); 139 atomic_set(&dev_priv->fence_seq, dev_priv->last_read_sequence);
122 iowrite32(dev_priv->last_read_sequence, fifo_mem + SVGA_FIFO_FENCE); 140 iowrite32(dev_priv->last_read_sequence, fifo_mem + SVGA_FIFO_FENCE);
123 141 vmw_fence_queue_init(&fifo->fence_queue);
124 return vmw_fifo_send_fence(dev_priv, &dummy); 142 return vmw_fifo_send_fence(dev_priv, &dummy);
125out_err: 143out_err:
126 vfree(fifo->static_buffer); 144 vfree(fifo->static_buffer);
@@ -159,6 +177,7 @@ void vmw_fifo_release(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
159 dev_priv->enable_state); 177 dev_priv->enable_state);
160 178
161 mutex_unlock(&dev_priv->hw_mutex); 179 mutex_unlock(&dev_priv->hw_mutex);
180 vmw_fence_queue_takedown(&fifo->fence_queue);
162 181
163 if (likely(fifo->last_buffer != NULL)) { 182 if (likely(fifo->last_buffer != NULL)) {
164 vfree(fifo->last_buffer); 183 vfree(fifo->last_buffer);
@@ -484,6 +503,8 @@ int vmw_fifo_send_fence(struct vmw_private *dev_priv, uint32_t *sequence)
484 fifo_state->last_buffer_add = true; 503 fifo_state->last_buffer_add = true;
485 vmw_fifo_commit(dev_priv, bytes); 504 vmw_fifo_commit(dev_priv, bytes);
486 fifo_state->last_buffer_add = false; 505 fifo_state->last_buffer_add = false;
506 (void) vmw_fence_push(&fifo_state->fence_queue, *sequence);
507 vmw_update_sequence(dev_priv, fifo_state);
487 508
488out_err: 509out_err:
489 return ret; 510 return ret;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
index 4d7cb5393860..e92298a6a383 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
@@ -64,22 +64,33 @@ static bool vmw_fifo_idle(struct vmw_private *dev_priv, uint32_t sequence)
64 return (busy == 0); 64 return (busy == 0);
65} 65}
66 66
67void vmw_update_sequence(struct vmw_private *dev_priv,
68 struct vmw_fifo_state *fifo_state)
69{
70 __le32 __iomem *fifo_mem = dev_priv->mmio_virt;
71
72 uint32_t sequence = ioread32(fifo_mem + SVGA_FIFO_FENCE);
73
74 if (dev_priv->last_read_sequence != sequence) {
75 dev_priv->last_read_sequence = sequence;
76 vmw_fence_pull(&fifo_state->fence_queue, sequence);
77 }
78}
67 79
68bool vmw_fence_signaled(struct vmw_private *dev_priv, 80bool vmw_fence_signaled(struct vmw_private *dev_priv,
69 uint32_t sequence) 81 uint32_t sequence)
70{ 82{
71 __le32 __iomem *fifo_mem = dev_priv->mmio_virt;
72 struct vmw_fifo_state *fifo_state; 83 struct vmw_fifo_state *fifo_state;
73 bool ret; 84 bool ret;
74 85
75 if (likely(dev_priv->last_read_sequence - sequence < VMW_FENCE_WRAP)) 86 if (likely(dev_priv->last_read_sequence - sequence < VMW_FENCE_WRAP))
76 return true; 87 return true;
77 88
78 dev_priv->last_read_sequence = ioread32(fifo_mem + SVGA_FIFO_FENCE); 89 fifo_state = &dev_priv->fifo;
90 vmw_update_sequence(dev_priv, fifo_state);
79 if (likely(dev_priv->last_read_sequence - sequence < VMW_FENCE_WRAP)) 91 if (likely(dev_priv->last_read_sequence - sequence < VMW_FENCE_WRAP))
80 return true; 92 return true;
81 93
82 fifo_state = &dev_priv->fifo;
83 if (!(fifo_state->capabilities & SVGA_FIFO_CAP_FENCE) && 94 if (!(fifo_state->capabilities & SVGA_FIFO_CAP_FENCE) &&
84 vmw_fifo_idle(dev_priv, sequence)) 95 vmw_fifo_idle(dev_priv, sequence))
85 return true; 96 return true;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index bbc7c4c30bc7..f1d626112415 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -30,6 +30,8 @@
30/* Might need a hrtimer here? */ 30/* Might need a hrtimer here? */
31#define VMWGFX_PRESENT_RATE ((HZ / 60 > 0) ? HZ / 60 : 1) 31#define VMWGFX_PRESENT_RATE ((HZ / 60 > 0) ? HZ / 60 : 1)
32 32
33static int vmw_surface_dmabuf_pin(struct vmw_framebuffer *vfb);
34static int vmw_surface_dmabuf_unpin(struct vmw_framebuffer *vfb);
33 35
34void vmw_display_unit_cleanup(struct vmw_display_unit *du) 36void vmw_display_unit_cleanup(struct vmw_display_unit *du)
35{ 37{
@@ -326,6 +328,7 @@ int vmw_framebuffer_create_handle(struct drm_framebuffer *fb,
326struct vmw_framebuffer_surface { 328struct vmw_framebuffer_surface {
327 struct vmw_framebuffer base; 329 struct vmw_framebuffer base;
328 struct vmw_surface *surface; 330 struct vmw_surface *surface;
331 struct vmw_dma_buffer *buffer;
329 struct delayed_work d_work; 332 struct delayed_work d_work;
330 struct mutex work_lock; 333 struct mutex work_lock;
331 bool present_fs; 334 bool present_fs;
@@ -500,8 +503,8 @@ int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv,
500 vfbs->base.base.depth = 24; 503 vfbs->base.base.depth = 24;
501 vfbs->base.base.width = width; 504 vfbs->base.base.width = width;
502 vfbs->base.base.height = height; 505 vfbs->base.base.height = height;
503 vfbs->base.pin = NULL; 506 vfbs->base.pin = &vmw_surface_dmabuf_pin;
504 vfbs->base.unpin = NULL; 507 vfbs->base.unpin = &vmw_surface_dmabuf_unpin;
505 vfbs->surface = surface; 508 vfbs->surface = surface;
506 mutex_init(&vfbs->work_lock); 509 mutex_init(&vfbs->work_lock);
507 INIT_DELAYED_WORK(&vfbs->d_work, &vmw_framebuffer_present_fs_callback); 510 INIT_DELAYED_WORK(&vfbs->d_work, &vmw_framebuffer_present_fs_callback);
@@ -589,6 +592,40 @@ static struct drm_framebuffer_funcs vmw_framebuffer_dmabuf_funcs = {
589 .create_handle = vmw_framebuffer_create_handle, 592 .create_handle = vmw_framebuffer_create_handle,
590}; 593};
591 594
595static int vmw_surface_dmabuf_pin(struct vmw_framebuffer *vfb)
596{
597 struct vmw_private *dev_priv = vmw_priv(vfb->base.dev);
598 struct vmw_framebuffer_surface *vfbs =
599 vmw_framebuffer_to_vfbs(&vfb->base);
600 unsigned long size = vfbs->base.base.pitch * vfbs->base.base.height;
601 int ret;
602
603 vfbs->buffer = kzalloc(sizeof(*vfbs->buffer), GFP_KERNEL);
604 if (unlikely(vfbs->buffer == NULL))
605 return -ENOMEM;
606
607 vmw_overlay_pause_all(dev_priv);
608 ret = vmw_dmabuf_init(dev_priv, vfbs->buffer, size,
609 &vmw_vram_ne_placement,
610 false, &vmw_dmabuf_bo_free);
611 vmw_overlay_resume_all(dev_priv);
612
613 return ret;
614}
615
616static int vmw_surface_dmabuf_unpin(struct vmw_framebuffer *vfb)
617{
618 struct ttm_buffer_object *bo;
619 struct vmw_framebuffer_surface *vfbs =
620 vmw_framebuffer_to_vfbs(&vfb->base);
621
622 bo = &vfbs->buffer->base;
623 ttm_bo_unref(&bo);
624 vfbs->buffer = NULL;
625
626 return 0;
627}
628
592static int vmw_framebuffer_dmabuf_pin(struct vmw_framebuffer *vfb) 629static int vmw_framebuffer_dmabuf_pin(struct vmw_framebuffer *vfb)
593{ 630{
594 struct vmw_private *dev_priv = vmw_priv(vfb->base.dev); 631 struct vmw_private *dev_priv = vmw_priv(vfb->base.dev);
@@ -596,33 +633,15 @@ static int vmw_framebuffer_dmabuf_pin(struct vmw_framebuffer *vfb)
596 vmw_framebuffer_to_vfbd(&vfb->base); 633 vmw_framebuffer_to_vfbd(&vfb->base);
597 int ret; 634 int ret;
598 635
636
599 vmw_overlay_pause_all(dev_priv); 637 vmw_overlay_pause_all(dev_priv);
600 638
601 ret = vmw_dmabuf_to_start_of_vram(dev_priv, vfbd->buffer); 639 ret = vmw_dmabuf_to_start_of_vram(dev_priv, vfbd->buffer);
602 640
603 if (dev_priv->capabilities & SVGA_CAP_MULTIMON) {
604 vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
605 vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, 0);
606 vmw_write(dev_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
607 vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_X, 0);
608 vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_Y, 0);
609 vmw_write(dev_priv, SVGA_REG_DISPLAY_WIDTH, 0);
610 vmw_write(dev_priv, SVGA_REG_DISPLAY_HEIGHT, 0);
611 vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
612
613 vmw_write(dev_priv, SVGA_REG_ENABLE, 1);
614 vmw_write(dev_priv, SVGA_REG_WIDTH, vfb->base.width);
615 vmw_write(dev_priv, SVGA_REG_HEIGHT, vfb->base.height);
616 vmw_write(dev_priv, SVGA_REG_BITS_PER_PIXEL, vfb->base.bits_per_pixel);
617 vmw_write(dev_priv, SVGA_REG_DEPTH, vfb->base.depth);
618 vmw_write(dev_priv, SVGA_REG_RED_MASK, 0x00ff0000);
619 vmw_write(dev_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
620 vmw_write(dev_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
621 } else
622 WARN_ON(true);
623
624 vmw_overlay_resume_all(dev_priv); 641 vmw_overlay_resume_all(dev_priv);
625 642
643 WARN_ON(ret != 0);
644
626 return 0; 645 return 0;
627} 646}
628 647
@@ -668,7 +687,7 @@ int vmw_kms_new_framebuffer_dmabuf(struct vmw_private *dev_priv,
668 687
669 /* XXX get the first 3 from the surface info */ 688 /* XXX get the first 3 from the surface info */
670 vfbd->base.base.bits_per_pixel = 32; 689 vfbd->base.base.bits_per_pixel = 32;
671 vfbd->base.base.pitch = width * 32 / 4; 690 vfbd->base.base.pitch = width * vfbd->base.base.bits_per_pixel / 8;
672 vfbd->base.base.depth = 24; 691 vfbd->base.base.depth = 24;
673 vfbd->base.base.width = width; 692 vfbd->base.base.width = width;
674 vfbd->base.base.height = height; 693 vfbd->base.base.height = height;
@@ -765,8 +784,9 @@ int vmw_kms_init(struct vmw_private *dev_priv)
765 dev->mode_config.funcs = &vmw_kms_funcs; 784 dev->mode_config.funcs = &vmw_kms_funcs;
766 dev->mode_config.min_width = 1; 785 dev->mode_config.min_width = 1;
767 dev->mode_config.min_height = 1; 786 dev->mode_config.min_height = 1;
768 dev->mode_config.max_width = dev_priv->fb_max_width; 787 /* assumed largest fb size */
769 dev->mode_config.max_height = dev_priv->fb_max_height; 788 dev->mode_config.max_width = 8192;
789 dev->mode_config.max_height = 8192;
770 790
771 ret = vmw_kms_init_legacy_display_system(dev_priv); 791 ret = vmw_kms_init_legacy_display_system(dev_priv);
772 792
@@ -826,49 +846,140 @@ out:
826 return ret; 846 return ret;
827} 847}
828 848
849void vmw_kms_write_svga(struct vmw_private *vmw_priv,
850 unsigned width, unsigned height, unsigned pitch,
851 unsigned bbp, unsigned depth)
852{
853 if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK)
854 vmw_write(vmw_priv, SVGA_REG_PITCHLOCK, pitch);
855 else if (vmw_fifo_have_pitchlock(vmw_priv))
856 iowrite32(pitch, vmw_priv->mmio_virt + SVGA_FIFO_PITCHLOCK);
857 vmw_write(vmw_priv, SVGA_REG_WIDTH, width);
858 vmw_write(vmw_priv, SVGA_REG_HEIGHT, height);
859 vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, bbp);
860 vmw_write(vmw_priv, SVGA_REG_DEPTH, depth);
861 vmw_write(vmw_priv, SVGA_REG_RED_MASK, 0x00ff0000);
862 vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
863 vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
864}
865
829int vmw_kms_save_vga(struct vmw_private *vmw_priv) 866int vmw_kms_save_vga(struct vmw_private *vmw_priv)
830{ 867{
831 /* 868 struct vmw_vga_topology_state *save;
832 * setup a single multimon monitor with the size 869 uint32_t i;
833 * of 0x0, this stops the UI from resizing when we
834 * change the framebuffer size
835 */
836 if (vmw_priv->capabilities & SVGA_CAP_MULTIMON) {
837 vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
838 vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0);
839 vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
840 vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, 0);
841 vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_Y, 0);
842 vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, 0);
843 vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, 0);
844 vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
845 }
846 870
847 vmw_priv->vga_width = vmw_read(vmw_priv, SVGA_REG_WIDTH); 871 vmw_priv->vga_width = vmw_read(vmw_priv, SVGA_REG_WIDTH);
848 vmw_priv->vga_height = vmw_read(vmw_priv, SVGA_REG_HEIGHT); 872 vmw_priv->vga_height = vmw_read(vmw_priv, SVGA_REG_HEIGHT);
849 vmw_priv->vga_bpp = vmw_read(vmw_priv, SVGA_REG_BITS_PER_PIXEL);
850 vmw_priv->vga_depth = vmw_read(vmw_priv, SVGA_REG_DEPTH); 873 vmw_priv->vga_depth = vmw_read(vmw_priv, SVGA_REG_DEPTH);
874 vmw_priv->vga_bpp = vmw_read(vmw_priv, SVGA_REG_BITS_PER_PIXEL);
851 vmw_priv->vga_pseudo = vmw_read(vmw_priv, SVGA_REG_PSEUDOCOLOR); 875 vmw_priv->vga_pseudo = vmw_read(vmw_priv, SVGA_REG_PSEUDOCOLOR);
852 vmw_priv->vga_red_mask = vmw_read(vmw_priv, SVGA_REG_RED_MASK); 876 vmw_priv->vga_red_mask = vmw_read(vmw_priv, SVGA_REG_RED_MASK);
853 vmw_priv->vga_green_mask = vmw_read(vmw_priv, SVGA_REG_GREEN_MASK);
854 vmw_priv->vga_blue_mask = vmw_read(vmw_priv, SVGA_REG_BLUE_MASK); 877 vmw_priv->vga_blue_mask = vmw_read(vmw_priv, SVGA_REG_BLUE_MASK);
878 vmw_priv->vga_green_mask = vmw_read(vmw_priv, SVGA_REG_GREEN_MASK);
879 if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK)
880 vmw_priv->vga_pitchlock =
881 vmw_read(vmw_priv, SVGA_REG_PITCHLOCK);
882 else if (vmw_fifo_have_pitchlock(vmw_priv))
883 vmw_priv->vga_pitchlock = ioread32(vmw_priv->mmio_virt +
884 SVGA_FIFO_PITCHLOCK);
885
886 if (!(vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY))
887 return 0;
855 888
889 vmw_priv->num_displays = vmw_read(vmw_priv,
890 SVGA_REG_NUM_GUEST_DISPLAYS);
891
892 for (i = 0; i < vmw_priv->num_displays; ++i) {
893 save = &vmw_priv->vga_save[i];
894 vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, i);
895 save->primary = vmw_read(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY);
896 save->pos_x = vmw_read(vmw_priv, SVGA_REG_DISPLAY_POSITION_X);
897 save->pos_y = vmw_read(vmw_priv, SVGA_REG_DISPLAY_POSITION_Y);
898 save->width = vmw_read(vmw_priv, SVGA_REG_DISPLAY_WIDTH);
899 save->height = vmw_read(vmw_priv, SVGA_REG_DISPLAY_HEIGHT);
900 vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
901 }
856 return 0; 902 return 0;
857} 903}
858 904
859int vmw_kms_restore_vga(struct vmw_private *vmw_priv) 905int vmw_kms_restore_vga(struct vmw_private *vmw_priv)
860{ 906{
907 struct vmw_vga_topology_state *save;
908 uint32_t i;
909
861 vmw_write(vmw_priv, SVGA_REG_WIDTH, vmw_priv->vga_width); 910 vmw_write(vmw_priv, SVGA_REG_WIDTH, vmw_priv->vga_width);
862 vmw_write(vmw_priv, SVGA_REG_HEIGHT, vmw_priv->vga_height); 911 vmw_write(vmw_priv, SVGA_REG_HEIGHT, vmw_priv->vga_height);
863 vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, vmw_priv->vga_bpp);
864 vmw_write(vmw_priv, SVGA_REG_DEPTH, vmw_priv->vga_depth); 912 vmw_write(vmw_priv, SVGA_REG_DEPTH, vmw_priv->vga_depth);
913 vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, vmw_priv->vga_bpp);
865 vmw_write(vmw_priv, SVGA_REG_PSEUDOCOLOR, vmw_priv->vga_pseudo); 914 vmw_write(vmw_priv, SVGA_REG_PSEUDOCOLOR, vmw_priv->vga_pseudo);
866 vmw_write(vmw_priv, SVGA_REG_RED_MASK, vmw_priv->vga_red_mask); 915 vmw_write(vmw_priv, SVGA_REG_RED_MASK, vmw_priv->vga_red_mask);
867 vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, vmw_priv->vga_green_mask); 916 vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, vmw_priv->vga_green_mask);
868 vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, vmw_priv->vga_blue_mask); 917 vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, vmw_priv->vga_blue_mask);
918 if (vmw_priv->capabilities & SVGA_CAP_PITCHLOCK)
919 vmw_write(vmw_priv, SVGA_REG_PITCHLOCK,
920 vmw_priv->vga_pitchlock);
921 else if (vmw_fifo_have_pitchlock(vmw_priv))
922 iowrite32(vmw_priv->vga_pitchlock,
923 vmw_priv->mmio_virt + SVGA_FIFO_PITCHLOCK);
924
925 if (!(vmw_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY))
926 return 0;
869 927
870 /* TODO check for multimon */ 928 for (i = 0; i < vmw_priv->num_displays; ++i) {
871 vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 0); 929 save = &vmw_priv->vga_save[i];
930 vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, i);
931 vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, save->primary);
932 vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, save->pos_x);
933 vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_Y, save->pos_y);
934 vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, save->width);
935 vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, save->height);
936 vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
937 }
872 938
873 return 0; 939 return 0;
874} 940}
941
942int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
943 struct drm_file *file_priv)
944{
945 struct vmw_private *dev_priv = vmw_priv(dev);
946 struct drm_vmw_update_layout_arg *arg =
947 (struct drm_vmw_update_layout_arg *)data;
948 struct vmw_master *vmaster = vmw_master(file_priv->master);
949 void __user *user_rects;
950 struct drm_vmw_rect *rects;
951 unsigned rects_size;
952 int ret;
953
954 ret = ttm_read_lock(&vmaster->lock, true);
955 if (unlikely(ret != 0))
956 return ret;
957
958 if (!arg->num_outputs) {
959 struct drm_vmw_rect def_rect = {0, 0, 800, 600};
960 vmw_kms_ldu_update_layout(dev_priv, 1, &def_rect);
961 goto out_unlock;
962 }
963
964 rects_size = arg->num_outputs * sizeof(struct drm_vmw_rect);
965 rects = kzalloc(rects_size, GFP_KERNEL);
966 if (unlikely(!rects)) {
967 ret = -ENOMEM;
968 goto out_unlock;
969 }
970
971 user_rects = (void __user *)(unsigned long)arg->rects;
972 ret = copy_from_user(rects, user_rects, rects_size);
973 if (unlikely(ret != 0)) {
974 DRM_ERROR("Failed to get rects.\n");
975 goto out_free;
976 }
977
978 vmw_kms_ldu_update_layout(dev_priv, arg->num_outputs, rects);
979
980out_free:
981 kfree(rects);
982out_unlock:
983 ttm_read_unlock(&vmaster->lock);
984 return ret;
985}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
index 8b95249f0531..8a398a0339b6 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
@@ -94,9 +94,11 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
94int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y); 94int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y);
95 95
96/* 96/*
97 * Legacy display unit functions - vmwgfx_ldu.h 97 * Legacy display unit functions - vmwgfx_ldu.c
98 */ 98 */
99int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv); 99int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv);
100int vmw_kms_close_legacy_display_system(struct vmw_private *dev_priv); 100int vmw_kms_close_legacy_display_system(struct vmw_private *dev_priv);
101int vmw_kms_ldu_update_layout(struct vmw_private *dev_priv, unsigned num,
102 struct drm_vmw_rect *rects);
101 103
102#endif 104#endif
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index 90891593bf6c..cfaf690a5b2f 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -38,6 +38,7 @@ struct vmw_legacy_display {
38 struct list_head active; 38 struct list_head active;
39 39
40 unsigned num_active; 40 unsigned num_active;
41 unsigned last_num_active;
41 42
42 struct vmw_framebuffer *fb; 43 struct vmw_framebuffer *fb;
43}; 44};
@@ -48,9 +49,12 @@ struct vmw_legacy_display {
48struct vmw_legacy_display_unit { 49struct vmw_legacy_display_unit {
49 struct vmw_display_unit base; 50 struct vmw_display_unit base;
50 51
51 struct list_head active; 52 unsigned pref_width;
53 unsigned pref_height;
54 bool pref_active;
55 struct drm_display_mode *pref_mode;
52 56
53 unsigned unit; 57 struct list_head active;
54}; 58};
55 59
56static void vmw_ldu_destroy(struct vmw_legacy_display_unit *ldu) 60static 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)
88{ 92{
89 struct vmw_legacy_display *lds = dev_priv->ldu_priv; 93 struct vmw_legacy_display *lds = dev_priv->ldu_priv;
90 struct vmw_legacy_display_unit *entry; 94 struct vmw_legacy_display_unit *entry;
91 struct drm_crtc *crtc; 95 struct drm_framebuffer *fb = NULL;
96 struct drm_crtc *crtc = NULL;
92 int i = 0; 97 int i = 0;
93 98
94 /* to stop the screen from changing size on resize */ 99 /* If there is no display topology the host just assumes
95 vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 0); 100 * that the guest will set the same layout as the host.
96 for (i = 0; i < lds->num_active; i++) { 101 */
97 vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, i); 102 if (!(dev_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY)) {
98 vmw_write(dev_priv, SVGA_REG_DISPLAY_IS_PRIMARY, !i); 103 int w = 0, h = 0;
99 vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_X, 0); 104 list_for_each_entry(entry, &lds->active, active) {
100 vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_Y, 0); 105 crtc = &entry->base.crtc;
101 vmw_write(dev_priv, SVGA_REG_DISPLAY_WIDTH, 0); 106 w = max(w, crtc->x + crtc->mode.hdisplay);
102 vmw_write(dev_priv, SVGA_REG_DISPLAY_HEIGHT, 0); 107 h = max(h, crtc->y + crtc->mode.vdisplay);
103 vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID); 108 i++;
109 }
110
111 if (crtc == NULL)
112 return 0;
113 fb = entry->base.crtc.fb;
114
115 vmw_kms_write_svga(dev_priv, w, h, fb->pitch,
116 fb->bits_per_pixel, fb->depth);
117
118 return 0;
104 } 119 }
105 120
106 /* Now set the mode */ 121 if (!list_empty(&lds->active)) {
107 vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, lds->num_active); 122 entry = list_entry(lds->active.next, typeof(*entry), active);
123 fb = entry->base.crtc.fb;
124
125 vmw_kms_write_svga(dev_priv, fb->width, fb->height, fb->pitch,
126 fb->bits_per_pixel, fb->depth);
127 }
128
129 /* Make sure we always show something. */
130 vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS,
131 lds->num_active ? lds->num_active : 1);
132
108 i = 0; 133 i = 0;
109 list_for_each_entry(entry, &lds->active, active) { 134 list_for_each_entry(entry, &lds->active, active) {
110 crtc = &entry->base.crtc; 135 crtc = &entry->base.crtc;
@@ -120,6 +145,10 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
120 i++; 145 i++;
121 } 146 }
122 147
148 BUG_ON(i != lds->num_active);
149
150 lds->last_num_active = lds->num_active;
151
123 return 0; 152 return 0;
124} 153}
125 154
@@ -130,6 +159,7 @@ static int vmw_ldu_del_active(struct vmw_private *vmw_priv,
130 if (list_empty(&ldu->active)) 159 if (list_empty(&ldu->active))
131 return 0; 160 return 0;
132 161
162 /* Must init otherwise list_empty(&ldu->active) will not work. */
133 list_del_init(&ldu->active); 163 list_del_init(&ldu->active);
134 if (--(ld->num_active) == 0) { 164 if (--(ld->num_active) == 0) {
135 BUG_ON(!ld->fb); 165 BUG_ON(!ld->fb);
@@ -149,24 +179,29 @@ static int vmw_ldu_add_active(struct vmw_private *vmw_priv,
149 struct vmw_legacy_display_unit *entry; 179 struct vmw_legacy_display_unit *entry;
150 struct list_head *at; 180 struct list_head *at;
151 181
182 BUG_ON(!ld->num_active && ld->fb);
183 if (vfb != ld->fb) {
184 if (ld->fb && ld->fb->unpin)
185 ld->fb->unpin(ld->fb);
186 if (vfb->pin)
187 vfb->pin(vfb);
188 ld->fb = vfb;
189 }
190
152 if (!list_empty(&ldu->active)) 191 if (!list_empty(&ldu->active))
153 return 0; 192 return 0;
154 193
155 at = &ld->active; 194 at = &ld->active;
156 list_for_each_entry(entry, &ld->active, active) { 195 list_for_each_entry(entry, &ld->active, active) {
157 if (entry->unit > ldu->unit) 196 if (entry->base.unit > ldu->base.unit)
158 break; 197 break;
159 198
160 at = &entry->active; 199 at = &entry->active;
161 } 200 }
162 201
163 list_add(&ldu->active, at); 202 list_add(&ldu->active, at);
164 if (ld->num_active++ == 0) { 203
165 BUG_ON(ld->fb); 204 ld->num_active++;
166 if (vfb->pin)
167 vfb->pin(vfb);
168 ld->fb = vfb;
169 }
170 205
171 return 0; 206 return 0;
172} 207}
@@ -208,6 +243,8 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
208 243
209 /* ldu only supports one fb active at the time */ 244 /* ldu only supports one fb active at the time */
210 if (dev_priv->ldu_priv->fb && vfb && 245 if (dev_priv->ldu_priv->fb && vfb &&
246 !(dev_priv->ldu_priv->num_active == 1 &&
247 !list_empty(&ldu->active)) &&
211 dev_priv->ldu_priv->fb != vfb) { 248 dev_priv->ldu_priv->fb != vfb) {
212 DRM_ERROR("Multiple framebuffers not supported\n"); 249 DRM_ERROR("Multiple framebuffers not supported\n");
213 return -EINVAL; 250 return -EINVAL;
@@ -300,8 +337,7 @@ static void vmw_ldu_connector_restore(struct drm_connector *connector)
300static enum drm_connector_status 337static enum drm_connector_status
301 vmw_ldu_connector_detect(struct drm_connector *connector) 338 vmw_ldu_connector_detect(struct drm_connector *connector)
302{ 339{
303 /* XXX vmwctrl should control connection status */ 340 if (vmw_connector_to_ldu(connector)->pref_active)
304 if (vmw_connector_to_ldu(connector)->base.unit == 0)
305 return connector_status_connected; 341 return connector_status_connected;
306 return connector_status_disconnected; 342 return connector_status_disconnected;
307} 343}
@@ -312,10 +348,9 @@ static struct drm_display_mode vmw_ldu_connector_builtin[] = {
312 752, 800, 0, 480, 489, 492, 525, 0, 348 752, 800, 0, 480, 489, 492, 525, 0,
313 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, 349 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
314 /* 800x600@60Hz */ 350 /* 800x600@60Hz */
315 { DRM_MODE("800x600", 351 { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840,
316 DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, 352 968, 1056, 0, 600, 601, 605, 628, 0,
317 40000, 800, 840, 968, 1056, 0, 600, 601, 605, 628, 353 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
318 0, DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
319 /* 1024x768@60Hz */ 354 /* 1024x768@60Hz */
320 { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048, 355 { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048,
321 1184, 1344, 0, 768, 771, 777, 806, 0, 356 1184, 1344, 0, 768, 771, 777, 806, 0,
@@ -387,10 +422,34 @@ static struct drm_display_mode vmw_ldu_connector_builtin[] = {
387static int vmw_ldu_connector_fill_modes(struct drm_connector *connector, 422static int vmw_ldu_connector_fill_modes(struct drm_connector *connector,
388 uint32_t max_width, uint32_t max_height) 423 uint32_t max_width, uint32_t max_height)
389{ 424{
425 struct vmw_legacy_display_unit *ldu = vmw_connector_to_ldu(connector);
390 struct drm_device *dev = connector->dev; 426 struct drm_device *dev = connector->dev;
391 struct drm_display_mode *mode = NULL; 427 struct drm_display_mode *mode = NULL;
428 struct drm_display_mode prefmode = { DRM_MODE("preferred",
429 DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
430 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
431 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC)
432 };
392 int i; 433 int i;
393 434
435 /* Add preferred mode */
436 {
437 mode = drm_mode_duplicate(dev, &prefmode);
438 if (!mode)
439 return 0;
440 mode->hdisplay = ldu->pref_width;
441 mode->vdisplay = ldu->pref_height;
442 mode->vrefresh = drm_mode_vrefresh(mode);
443 drm_mode_probed_add(connector, mode);
444
445 if (ldu->pref_mode) {
446 list_del_init(&ldu->pref_mode->head);
447 drm_mode_destroy(dev, ldu->pref_mode);
448 }
449
450 ldu->pref_mode = mode;
451 }
452
394 for (i = 0; vmw_ldu_connector_builtin[i].type != 0; i++) { 453 for (i = 0; vmw_ldu_connector_builtin[i].type != 0; i++) {
395 if (vmw_ldu_connector_builtin[i].hdisplay > max_width || 454 if (vmw_ldu_connector_builtin[i].hdisplay > max_width ||
396 vmw_ldu_connector_builtin[i].vdisplay > max_height) 455 vmw_ldu_connector_builtin[i].vdisplay > max_height)
@@ -443,18 +502,21 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
443 if (!ldu) 502 if (!ldu)
444 return -ENOMEM; 503 return -ENOMEM;
445 504
446 ldu->unit = unit; 505 ldu->base.unit = unit;
447 crtc = &ldu->base.crtc; 506 crtc = &ldu->base.crtc;
448 encoder = &ldu->base.encoder; 507 encoder = &ldu->base.encoder;
449 connector = &ldu->base.connector; 508 connector = &ldu->base.connector;
450 509
510 INIT_LIST_HEAD(&ldu->active);
511
512 ldu->pref_active = (unit == 0);
513 ldu->pref_width = 800;
514 ldu->pref_height = 600;
515 ldu->pref_mode = NULL;
516
451 drm_connector_init(dev, connector, &vmw_legacy_connector_funcs, 517 drm_connector_init(dev, connector, &vmw_legacy_connector_funcs,
452 DRM_MODE_CONNECTOR_LVDS); 518 DRM_MODE_CONNECTOR_LVDS);
453 /* Initial status */ 519 connector->status = vmw_ldu_connector_detect(connector);
454 if (unit == 0)
455 connector->status = connector_status_connected;
456 else
457 connector->status = connector_status_disconnected;
458 520
459 drm_encoder_init(dev, encoder, &vmw_legacy_encoder_funcs, 521 drm_encoder_init(dev, encoder, &vmw_legacy_encoder_funcs,
460 DRM_MODE_ENCODER_LVDS); 522 DRM_MODE_ENCODER_LVDS);
@@ -462,8 +524,6 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
462 encoder->possible_crtcs = (1 << unit); 524 encoder->possible_crtcs = (1 << unit);
463 encoder->possible_clones = 0; 525 encoder->possible_clones = 0;
464 526
465 INIT_LIST_HEAD(&ldu->active);
466
467 drm_crtc_init(dev, crtc, &vmw_legacy_crtc_funcs); 527 drm_crtc_init(dev, crtc, &vmw_legacy_crtc_funcs);
468 528
469 drm_connector_attach_property(connector, 529 drm_connector_attach_property(connector,
@@ -487,18 +547,22 @@ int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv)
487 547
488 INIT_LIST_HEAD(&dev_priv->ldu_priv->active); 548 INIT_LIST_HEAD(&dev_priv->ldu_priv->active);
489 dev_priv->ldu_priv->num_active = 0; 549 dev_priv->ldu_priv->num_active = 0;
550 dev_priv->ldu_priv->last_num_active = 0;
490 dev_priv->ldu_priv->fb = NULL; 551 dev_priv->ldu_priv->fb = NULL;
491 552
492 drm_mode_create_dirty_info_property(dev_priv->dev); 553 drm_mode_create_dirty_info_property(dev_priv->dev);
493 554
494 vmw_ldu_init(dev_priv, 0); 555 vmw_ldu_init(dev_priv, 0);
495 vmw_ldu_init(dev_priv, 1); 556 /* for old hardware without multimon only enable one display */
496 vmw_ldu_init(dev_priv, 2); 557 if (dev_priv->capabilities & SVGA_CAP_MULTIMON) {
497 vmw_ldu_init(dev_priv, 3); 558 vmw_ldu_init(dev_priv, 1);
498 vmw_ldu_init(dev_priv, 4); 559 vmw_ldu_init(dev_priv, 2);
499 vmw_ldu_init(dev_priv, 5); 560 vmw_ldu_init(dev_priv, 3);
500 vmw_ldu_init(dev_priv, 6); 561 vmw_ldu_init(dev_priv, 4);
501 vmw_ldu_init(dev_priv, 7); 562 vmw_ldu_init(dev_priv, 5);
563 vmw_ldu_init(dev_priv, 6);
564 vmw_ldu_init(dev_priv, 7);
565 }
502 566
503 return 0; 567 return 0;
504} 568}
@@ -514,3 +578,42 @@ int vmw_kms_close_legacy_display_system(struct vmw_private *dev_priv)
514 578
515 return 0; 579 return 0;
516} 580}
581
582int vmw_kms_ldu_update_layout(struct vmw_private *dev_priv, unsigned num,
583 struct drm_vmw_rect *rects)
584{
585 struct drm_device *dev = dev_priv->dev;
586 struct vmw_legacy_display_unit *ldu;
587 struct drm_connector *con;
588 int i;
589
590 mutex_lock(&dev->mode_config.mutex);
591
592#if 0
593 DRM_INFO("%s: new layout ", __func__);
594 for (i = 0; i < (int)num; i++)
595 DRM_INFO("(%i, %i %ux%u) ", rects[i].x, rects[i].y,
596 rects[i].w, rects[i].h);
597 DRM_INFO("\n");
598#else
599 (void)i;
600#endif
601
602 list_for_each_entry(con, &dev->mode_config.connector_list, head) {
603 ldu = vmw_connector_to_ldu(con);
604 if (num > ldu->base.unit) {
605 ldu->pref_width = rects[ldu->base.unit].w;
606 ldu->pref_height = rects[ldu->base.unit].h;
607 ldu->pref_active = true;
608 } else {
609 ldu->pref_width = 800;
610 ldu->pref_height = 600;
611 ldu->pref_active = false;
612 }
613 con->status = vmw_ldu_connector_detect(con);
614 }
615
616 mutex_unlock(&dev->mode_config.mutex);
617
618 return 0;
619}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
index ad566c85b075..df2036ed18d5 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
@@ -358,6 +358,8 @@ static int vmw_overlay_update_stream(struct vmw_private *dev_priv,
358 if (stream->buf != buf) 358 if (stream->buf != buf)
359 stream->buf = vmw_dmabuf_reference(buf); 359 stream->buf = vmw_dmabuf_reference(buf);
360 stream->saved = *arg; 360 stream->saved = *arg;
361 /* stream is no longer stopped/paused */
362 stream->paused = false;
361 363
362 return 0; 364 return 0;
363} 365}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
index f8fbbc67a406..8612378b131e 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
@@ -597,8 +597,10 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
597 597
598 ret = copy_from_user(srf->sizes, user_sizes, 598 ret = copy_from_user(srf->sizes, user_sizes,
599 srf->num_sizes * sizeof(*srf->sizes)); 599 srf->num_sizes * sizeof(*srf->sizes));
600 if (unlikely(ret != 0)) 600 if (unlikely(ret != 0)) {
601 ret = -EFAULT;
601 goto out_err1; 602 goto out_err1;
603 }
602 604
603 if (srf->scanout && 605 if (srf->scanout &&
604 srf->num_sizes == 1 && 606 srf->num_sizes == 1 &&
@@ -697,9 +699,11 @@ int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
697 if (user_sizes) 699 if (user_sizes)
698 ret = copy_to_user(user_sizes, srf->sizes, 700 ret = copy_to_user(user_sizes, srf->sizes,
699 srf->num_sizes * sizeof(*srf->sizes)); 701 srf->num_sizes * sizeof(*srf->sizes));
700 if (unlikely(ret != 0)) 702 if (unlikely(ret != 0)) {
701 DRM_ERROR("copy_to_user failed %p %u\n", 703 DRM_ERROR("copy_to_user failed %p %u\n",
702 user_sizes, srf->num_sizes); 704 user_sizes, srf->num_sizes);
705 ret = -EFAULT;
706 }
703out_bad_resource: 707out_bad_resource:
704out_no_reference: 708out_no_reference:
705 ttm_base_object_unref(&base); 709 ttm_base_object_unref(&base);
diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c
index 441e38c95a85..b87569e96b16 100644
--- a/drivers/gpu/vga/vgaarb.c
+++ b/drivers/gpu/vga/vgaarb.c
@@ -1,12 +1,32 @@
1/* 1/*
2 * vgaarb.c 2 * vgaarb.c: Implements the VGA arbitration. For details refer to
3 * Documentation/vgaarbiter.txt
4 *
3 * 5 *
4 * (C) Copyright 2005 Benjamin Herrenschmidt <benh@kernel.crashing.org> 6 * (C) Copyright 2005 Benjamin Herrenschmidt <benh@kernel.crashing.org>
5 * (C) Copyright 2007 Paulo R. Zanoni <przanoni@gmail.com> 7 * (C) Copyright 2007 Paulo R. Zanoni <przanoni@gmail.com>
6 * (C) Copyright 2007, 2009 Tiago Vignatti <vignatti@freedesktop.org> 8 * (C) Copyright 2007, 2009 Tiago Vignatti <vignatti@freedesktop.org>
7 * 9 *
8 * Implements the VGA arbitration. For details refer to 10 * Permission is hereby granted, free of charge, to any person obtaining a
9 * Documentation/vgaarbiter.txt 11 * copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without restriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice (including the next
18 * paragraph) shall be included in all copies or substantial portions of the
19 * Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 * DEALINGS
28 * IN THE SOFTWARE.
29 *
10 */ 30 */
11 31
12#include <linux/module.h> 32#include <linux/module.h>
@@ -155,8 +175,8 @@ static struct vga_device *__vga_tryget(struct vga_device *vgadev,
155 (vgadev->decodes & VGA_RSRC_LEGACY_MEM)) 175 (vgadev->decodes & VGA_RSRC_LEGACY_MEM))
156 rsrc |= VGA_RSRC_LEGACY_MEM; 176 rsrc |= VGA_RSRC_LEGACY_MEM;
157 177
158 pr_devel("%s: %d\n", __func__, rsrc); 178 pr_debug("%s: %d\n", __func__, rsrc);
159 pr_devel("%s: owns: %d\n", __func__, vgadev->owns); 179 pr_debug("%s: owns: %d\n", __func__, vgadev->owns);
160 180
161 /* Check what resources we need to acquire */ 181 /* Check what resources we need to acquire */
162 wants = rsrc & ~vgadev->owns; 182 wants = rsrc & ~vgadev->owns;
@@ -268,7 +288,7 @@ static void __vga_put(struct vga_device *vgadev, unsigned int rsrc)
268{ 288{
269 unsigned int old_locks = vgadev->locks; 289 unsigned int old_locks = vgadev->locks;
270 290
271 pr_devel("%s\n", __func__); 291 pr_debug("%s\n", __func__);
272 292
273 /* Update our counters, and account for equivalent legacy resources 293 /* Update our counters, and account for equivalent legacy resources
274 * if we decode them 294 * if we decode them
@@ -575,6 +595,7 @@ static inline void vga_update_device_decodes(struct vga_device *vgadev,
575 else 595 else
576 vga_decode_count--; 596 vga_decode_count--;
577 } 597 }
598 pr_debug("vgaarb: decoding count now is: %d\n", vga_decode_count);
578} 599}
579 600
580void __vga_set_legacy_decoding(struct pci_dev *pdev, unsigned int decodes, bool userspace) 601void __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,
831 curr_pos += 5; 852 curr_pos += 5;
832 remaining -= 5; 853 remaining -= 5;
833 854
834 pr_devel("client 0x%p called 'lock'\n", priv); 855 pr_debug("client 0x%p called 'lock'\n", priv);
835 856
836 if (!vga_str_to_iostate(curr_pos, remaining, &io_state)) { 857 if (!vga_str_to_iostate(curr_pos, remaining, &io_state)) {
837 ret_val = -EPROTO; 858 ret_val = -EPROTO;
@@ -867,7 +888,7 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
867 curr_pos += 7; 888 curr_pos += 7;
868 remaining -= 7; 889 remaining -= 7;
869 890
870 pr_devel("client 0x%p called 'unlock'\n", priv); 891 pr_debug("client 0x%p called 'unlock'\n", priv);
871 892
872 if (strncmp(curr_pos, "all", 3) == 0) 893 if (strncmp(curr_pos, "all", 3) == 0)
873 io_state = VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM; 894 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,
917 curr_pos += 8; 938 curr_pos += 8;
918 remaining -= 8; 939 remaining -= 8;
919 940
920 pr_devel("client 0x%p called 'trylock'\n", priv); 941 pr_debug("client 0x%p called 'trylock'\n", priv);
921 942
922 if (!vga_str_to_iostate(curr_pos, remaining, &io_state)) { 943 if (!vga_str_to_iostate(curr_pos, remaining, &io_state)) {
923 ret_val = -EPROTO; 944 ret_val = -EPROTO;
@@ -961,7 +982,7 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
961 982
962 curr_pos += 7; 983 curr_pos += 7;
963 remaining -= 7; 984 remaining -= 7;
964 pr_devel("client 0x%p called 'target'\n", priv); 985 pr_debug("client 0x%p called 'target'\n", priv);
965 /* if target is default */ 986 /* if target is default */
966 if (!strncmp(curr_pos, "default", 7)) 987 if (!strncmp(curr_pos, "default", 7))
967 pdev = pci_dev_get(vga_default_device()); 988 pdev = pci_dev_get(vga_default_device());
@@ -971,11 +992,11 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
971 ret_val = -EPROTO; 992 ret_val = -EPROTO;
972 goto done; 993 goto done;
973 } 994 }
974 pr_devel("vgaarb: %s ==> %x:%x:%x.%x\n", curr_pos, 995 pr_debug("vgaarb: %s ==> %x:%x:%x.%x\n", curr_pos,
975 domain, bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); 996 domain, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
976 997
977 pbus = pci_find_bus(domain, bus); 998 pbus = pci_find_bus(domain, bus);
978 pr_devel("vgaarb: pbus %p\n", pbus); 999 pr_debug("vgaarb: pbus %p\n", pbus);
979 if (pbus == NULL) { 1000 if (pbus == NULL) {
980 pr_err("vgaarb: invalid PCI domain and/or bus address %x:%x\n", 1001 pr_err("vgaarb: invalid PCI domain and/or bus address %x:%x\n",
981 domain, bus); 1002 domain, bus);
@@ -983,7 +1004,7 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
983 goto done; 1004 goto done;
984 } 1005 }
985 pdev = pci_get_slot(pbus, devfn); 1006 pdev = pci_get_slot(pbus, devfn);
986 pr_devel("vgaarb: pdev %p\n", pdev); 1007 pr_debug("vgaarb: pdev %p\n", pdev);
987 if (!pdev) { 1008 if (!pdev) {
988 pr_err("vgaarb: invalid PCI address %x:%x\n", 1009 pr_err("vgaarb: invalid PCI address %x:%x\n",
989 bus, devfn); 1010 bus, devfn);
@@ -993,7 +1014,7 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
993 } 1014 }
994 1015
995 vgadev = vgadev_find(pdev); 1016 vgadev = vgadev_find(pdev);
996 pr_devel("vgaarb: vgadev %p\n", vgadev); 1017 pr_debug("vgaarb: vgadev %p\n", vgadev);
997 if (vgadev == NULL) { 1018 if (vgadev == NULL) {
998 pr_err("vgaarb: this pci device is not a vga device\n"); 1019 pr_err("vgaarb: this pci device is not a vga device\n");
999 pci_dev_put(pdev); 1020 pci_dev_put(pdev);
@@ -1029,7 +1050,7 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
1029 } else if (strncmp(curr_pos, "decodes ", 8) == 0) { 1050 } else if (strncmp(curr_pos, "decodes ", 8) == 0) {
1030 curr_pos += 8; 1051 curr_pos += 8;
1031 remaining -= 8; 1052 remaining -= 8;
1032 pr_devel("vgaarb: client 0x%p called 'decodes'\n", priv); 1053 pr_debug("vgaarb: client 0x%p called 'decodes'\n", priv);
1033 1054
1034 if (!vga_str_to_iostate(curr_pos, remaining, &io_state)) { 1055 if (!vga_str_to_iostate(curr_pos, remaining, &io_state)) {
1035 ret_val = -EPROTO; 1056 ret_val = -EPROTO;
@@ -1058,7 +1079,7 @@ static unsigned int vga_arb_fpoll(struct file *file, poll_table * wait)
1058{ 1079{
1059 struct vga_arb_private *priv = file->private_data; 1080 struct vga_arb_private *priv = file->private_data;
1060 1081
1061 pr_devel("%s\n", __func__); 1082 pr_debug("%s\n", __func__);
1062 1083
1063 if (priv == NULL) 1084 if (priv == NULL)
1064 return -ENODEV; 1085 return -ENODEV;
@@ -1071,7 +1092,7 @@ static int vga_arb_open(struct inode *inode, struct file *file)
1071 struct vga_arb_private *priv; 1092 struct vga_arb_private *priv;
1072 unsigned long flags; 1093 unsigned long flags;
1073 1094
1074 pr_devel("%s\n", __func__); 1095 pr_debug("%s\n", __func__);
1075 1096
1076 priv = kmalloc(sizeof(struct vga_arb_private), GFP_KERNEL); 1097 priv = kmalloc(sizeof(struct vga_arb_private), GFP_KERNEL);
1077 if (priv == NULL) 1098 if (priv == NULL)
@@ -1101,7 +1122,7 @@ static int vga_arb_release(struct inode *inode, struct file *file)
1101 unsigned long flags; 1122 unsigned long flags;
1102 int i; 1123 int i;
1103 1124
1104 pr_devel("%s\n", __func__); 1125 pr_debug("%s\n", __func__);
1105 1126
1106 if (priv == NULL) 1127 if (priv == NULL)
1107 return -ENODEV; 1128 return -ENODEV;
@@ -1112,7 +1133,7 @@ static int vga_arb_release(struct inode *inode, struct file *file)
1112 uc = &priv->cards[i]; 1133 uc = &priv->cards[i];
1113 if (uc->pdev == NULL) 1134 if (uc->pdev == NULL)
1114 continue; 1135 continue;
1115 pr_devel("uc->io_cnt == %d, uc->mem_cnt == %d\n", 1136 pr_debug("uc->io_cnt == %d, uc->mem_cnt == %d\n",
1116 uc->io_cnt, uc->mem_cnt); 1137 uc->io_cnt, uc->mem_cnt);
1117 while (uc->io_cnt--) 1138 while (uc->io_cnt--)
1118 vga_put(uc->pdev, VGA_RSRC_LEGACY_IO); 1139 vga_put(uc->pdev, VGA_RSRC_LEGACY_IO);
@@ -1165,7 +1186,7 @@ static int pci_notify(struct notifier_block *nb, unsigned long action,
1165 struct pci_dev *pdev = to_pci_dev(dev); 1186 struct pci_dev *pdev = to_pci_dev(dev);
1166 bool notify = false; 1187 bool notify = false;
1167 1188
1168 pr_devel("%s\n", __func__); 1189 pr_debug("%s\n", __func__);
1169 1190
1170 /* For now we're only intereted in devices added and removed. I didn't 1191 /* For now we're only intereted in devices added and removed. I didn't
1171 * test this thing here, so someone needs to double check for the 1192 * test this thing here, so someone needs to double check for the
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 76ba59b9fea1..132278fa6240 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -347,6 +347,14 @@ config HID_QUANTA
347 ---help--- 347 ---help---
348 Support for Quanta Optical Touch dual-touch panels. 348 Support for Quanta Optical Touch dual-touch panels.
349 349
350config HID_ROCCAT
351 tristate "Roccat special event support"
352 depends on USB_HID
353 ---help---
354 Support for Roccat special events.
355 Say Y here if you have a Roccat mouse or keyboard and want OSD or
356 macro execution support.
357
350config HID_ROCCAT_KONE 358config HID_ROCCAT_KONE
351 tristate "Roccat Kone Mouse support" 359 tristate "Roccat Kone Mouse support"
352 depends on USB_HID 360 depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 22e47eaeea32..987fa0627367 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -48,6 +48,7 @@ obj-$(CONFIG_HID_QUANTA) += hid-quanta.o
48obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o 48obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o
49obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o 49obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o
50obj-$(CONFIG_HID_PICOLCD) += hid-picolcd.o 50obj-$(CONFIG_HID_PICOLCD) += hid-picolcd.o
51obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o
51obj-$(CONFIG_HID_ROCCAT_KONE) += hid-roccat-kone.o 52obj-$(CONFIG_HID_ROCCAT_KONE) += hid-roccat-kone.o
52obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o 53obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o
53obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o 54obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index e10e314d38cc..aa0f7dcabcd7 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1301,6 +1301,7 @@ static const struct hid_device_id hid_blacklist[] = {
1301 { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) }, 1301 { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) },
1302 { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, 1302 { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
1303 { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, 1303 { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
1304 { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) },
1304 { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) }, 1305 { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
1305 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) }, 1306 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
1306 { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, 1307 { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
index 56f314fbd4f9..c94026768570 100644
--- a/drivers/hid/hid-debug.c
+++ b/drivers/hid/hid-debug.c
@@ -811,7 +811,7 @@ static const char *relatives[REL_MAX + 1] = {
811 [REL_WHEEL] = "Wheel", [REL_MISC] = "Misc", 811 [REL_WHEEL] = "Wheel", [REL_MISC] = "Misc",
812}; 812};
813 813
814static const char *absolutes[ABS_MAX + 1] = { 814static const char *absolutes[ABS_CNT] = {
815 [ABS_X] = "X", [ABS_Y] = "Y", 815 [ABS_X] = "X", [ABS_Y] = "Y",
816 [ABS_Z] = "Z", [ABS_RX] = "Rx", 816 [ABS_Z] = "Z", [ABS_RX] = "Rx",
817 [ABS_RY] = "Ry", [ABS_RZ] = "Rz", 817 [ABS_RY] = "Ry", [ABS_RZ] = "Rz",
diff --git a/drivers/hid/hid-gyration.c b/drivers/hid/hid-gyration.c
index 62416e6baeca..3975e039c3dd 100644
--- a/drivers/hid/hid-gyration.c
+++ b/drivers/hid/hid-gyration.c
@@ -73,6 +73,7 @@ static int gyration_event(struct hid_device *hdev, struct hid_field *field,
73static const struct hid_device_id gyration_devices[] = { 73static const struct hid_device_id gyration_devices[] = {
74 { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, 74 { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
75 { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, 75 { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
76 { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) },
76 { } 77 { }
77}; 78};
78MODULE_DEVICE_TABLE(hid, gyration_devices); 79MODULE_DEVICE_TABLE(hid, gyration_devices);
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 9776896cc4fc..6af77ed0b555 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -282,6 +282,7 @@
282#define USB_VENDOR_ID_GYRATION 0x0c16 282#define USB_VENDOR_ID_GYRATION 0x0c16
283#define USB_DEVICE_ID_GYRATION_REMOTE 0x0002 283#define USB_DEVICE_ID_GYRATION_REMOTE 0x0002
284#define USB_DEVICE_ID_GYRATION_REMOTE_2 0x0003 284#define USB_DEVICE_ID_GYRATION_REMOTE_2 0x0003
285#define USB_DEVICE_ID_GYRATION_REMOTE_3 0x0008
285 286
286#define USB_VENDOR_ID_HAPP 0x078b 287#define USB_VENDOR_ID_HAPP 0x078b
287#define USB_DEVICE_ID_UGCI_DRIVING 0x0010 288#define USB_DEVICE_ID_UGCI_DRIVING 0x0010
diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c
index 66e694054ba2..17f2dc04f883 100644
--- a/drivers/hid/hid-roccat-kone.c
+++ b/drivers/hid/hid-roccat-kone.c
@@ -37,6 +37,7 @@
37#include <linux/module.h> 37#include <linux/module.h>
38#include <linux/slab.h> 38#include <linux/slab.h>
39#include "hid-ids.h" 39#include "hid-ids.h"
40#include "hid-roccat.h"
40#include "hid-roccat-kone.h" 41#include "hid-roccat-kone.h"
41 42
42static void kone_set_settings_checksum(struct kone_settings *settings) 43static void kone_set_settings_checksum(struct kone_settings *settings)
@@ -263,7 +264,7 @@ static int kone_get_firmware_version(struct usb_device *usb_dev, int *result)
263 return 0; 264 return 0;
264} 265}
265 266
266static ssize_t kone_sysfs_read_settings(struct kobject *kobj, 267static ssize_t kone_sysfs_read_settings(struct file *fp, struct kobject *kobj,
267 struct bin_attribute *attr, char *buf, 268 struct bin_attribute *attr, char *buf,
268 loff_t off, size_t count) { 269 loff_t off, size_t count) {
269 struct device *dev = container_of(kobj, struct device, kobj); 270 struct device *dev = container_of(kobj, struct device, kobj);
@@ -287,7 +288,7 @@ static ssize_t kone_sysfs_read_settings(struct kobject *kobj,
287 * This function keeps values in kone_device up to date and assumes that in 288 * This function keeps values in kone_device up to date and assumes that in
288 * case of error the old data is still valid 289 * case of error the old data is still valid
289 */ 290 */
290static ssize_t kone_sysfs_write_settings(struct kobject *kobj, 291static ssize_t kone_sysfs_write_settings(struct file *fp, struct kobject *kobj,
291 struct bin_attribute *attr, char *buf, 292 struct bin_attribute *attr, char *buf,
292 loff_t off, size_t count) { 293 loff_t off, size_t count) {
293 struct device *dev = container_of(kobj, struct device, kobj); 294 struct device *dev = container_of(kobj, struct device, kobj);
@@ -342,31 +343,31 @@ static ssize_t kone_sysfs_read_profilex(struct kobject *kobj,
342 return count; 343 return count;
343} 344}
344 345
345static ssize_t kone_sysfs_read_profile1(struct kobject *kobj, 346static ssize_t kone_sysfs_read_profile1(struct file *fp, struct kobject *kobj,
346 struct bin_attribute *attr, char *buf, 347 struct bin_attribute *attr, char *buf,
347 loff_t off, size_t count) { 348 loff_t off, size_t count) {
348 return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 1); 349 return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 1);
349} 350}
350 351
351static ssize_t kone_sysfs_read_profile2(struct kobject *kobj, 352static ssize_t kone_sysfs_read_profile2(struct file *fp, struct kobject *kobj,
352 struct bin_attribute *attr, char *buf, 353 struct bin_attribute *attr, char *buf,
353 loff_t off, size_t count) { 354 loff_t off, size_t count) {
354 return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 2); 355 return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 2);
355} 356}
356 357
357static ssize_t kone_sysfs_read_profile3(struct kobject *kobj, 358static ssize_t kone_sysfs_read_profile3(struct file *fp, struct kobject *kobj,
358 struct bin_attribute *attr, char *buf, 359 struct bin_attribute *attr, char *buf,
359 loff_t off, size_t count) { 360 loff_t off, size_t count) {
360 return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 3); 361 return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 3);
361} 362}
362 363
363static ssize_t kone_sysfs_read_profile4(struct kobject *kobj, 364static ssize_t kone_sysfs_read_profile4(struct file *fp, struct kobject *kobj,
364 struct bin_attribute *attr, char *buf, 365 struct bin_attribute *attr, char *buf,
365 loff_t off, size_t count) { 366 loff_t off, size_t count) {
366 return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 4); 367 return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 4);
367} 368}
368 369
369static ssize_t kone_sysfs_read_profile5(struct kobject *kobj, 370static ssize_t kone_sysfs_read_profile5(struct file *fp, struct kobject *kobj,
370 struct bin_attribute *attr, char *buf, 371 struct bin_attribute *attr, char *buf,
371 loff_t off, size_t count) { 372 loff_t off, size_t count) {
372 return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 5); 373 return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 5);
@@ -404,31 +405,31 @@ static ssize_t kone_sysfs_write_profilex(struct kobject *kobj,
404 return sizeof(struct kone_profile); 405 return sizeof(struct kone_profile);
405} 406}
406 407
407static ssize_t kone_sysfs_write_profile1(struct kobject *kobj, 408static ssize_t kone_sysfs_write_profile1(struct file *fp, struct kobject *kobj,
408 struct bin_attribute *attr, char *buf, 409 struct bin_attribute *attr, char *buf,
409 loff_t off, size_t count) { 410 loff_t off, size_t count) {
410 return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 1); 411 return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 1);
411} 412}
412 413
413static ssize_t kone_sysfs_write_profile2(struct kobject *kobj, 414static ssize_t kone_sysfs_write_profile2(struct file *fp, struct kobject *kobj,
414 struct bin_attribute *attr, char *buf, 415 struct bin_attribute *attr, char *buf,
415 loff_t off, size_t count) { 416 loff_t off, size_t count) {
416 return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 2); 417 return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 2);
417} 418}
418 419
419static ssize_t kone_sysfs_write_profile3(struct kobject *kobj, 420static ssize_t kone_sysfs_write_profile3(struct file *fp, struct kobject *kobj,
420 struct bin_attribute *attr, char *buf, 421 struct bin_attribute *attr, char *buf,
421 loff_t off, size_t count) { 422 loff_t off, size_t count) {
422 return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 3); 423 return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 3);
423} 424}
424 425
425static ssize_t kone_sysfs_write_profile4(struct kobject *kobj, 426static ssize_t kone_sysfs_write_profile4(struct file *fp, struct kobject *kobj,
426 struct bin_attribute *attr, char *buf, 427 struct bin_attribute *attr, char *buf,
427 loff_t off, size_t count) { 428 loff_t off, size_t count) {
428 return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 4); 429 return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 4);
429} 430}
430 431
431static ssize_t kone_sysfs_write_profile5(struct kobject *kobj, 432static ssize_t kone_sysfs_write_profile5(struct file *fp, struct kobject *kobj,
432 struct bin_attribute *attr, char *buf, 433 struct bin_attribute *attr, char *buf,
433 loff_t off, size_t count) { 434 loff_t off, size_t count) {
434 return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 5); 435 return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 5);
@@ -849,6 +850,16 @@ static int kone_init_specials(struct hid_device *hdev)
849 "couldn't init struct kone_device\n"); 850 "couldn't init struct kone_device\n");
850 goto exit_free; 851 goto exit_free;
851 } 852 }
853
854 retval = roccat_connect(hdev);
855 if (retval < 0) {
856 dev_err(&hdev->dev, "couldn't init char dev\n");
857 /* be tolerant about not getting chrdev */
858 } else {
859 kone->roccat_claimed = 1;
860 kone->chrdev_minor = retval;
861 }
862
852 retval = kone_create_sysfs_attributes(intf); 863 retval = kone_create_sysfs_attributes(intf);
853 if (retval) { 864 if (retval) {
854 dev_err(&hdev->dev, "cannot create sysfs files\n"); 865 dev_err(&hdev->dev, "cannot create sysfs files\n");
@@ -868,10 +879,14 @@ exit_free:
868static void kone_remove_specials(struct hid_device *hdev) 879static void kone_remove_specials(struct hid_device *hdev)
869{ 880{
870 struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 881 struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
882 struct kone_device *kone;
871 883
872 if (intf->cur_altsetting->desc.bInterfaceProtocol 884 if (intf->cur_altsetting->desc.bInterfaceProtocol
873 == USB_INTERFACE_PROTOCOL_MOUSE) { 885 == USB_INTERFACE_PROTOCOL_MOUSE) {
874 kone_remove_sysfs_attributes(intf); 886 kone_remove_sysfs_attributes(intf);
887 kone = hid_get_drvdata(hdev);
888 if (kone->roccat_claimed)
889 roccat_disconnect(kone->chrdev_minor);
875 kfree(hid_get_drvdata(hdev)); 890 kfree(hid_get_drvdata(hdev));
876 } 891 }
877} 892}
@@ -930,6 +945,37 @@ static void kone_keep_values_up_to_date(struct kone_device *kone,
930 } 945 }
931} 946}
932 947
948static void kone_report_to_chrdev(struct kone_device const *kone,
949 struct kone_mouse_event const *event)
950{
951 struct kone_roccat_report roccat_report;
952
953 switch (event->event) {
954 case kone_mouse_event_switch_profile:
955 case kone_mouse_event_switch_dpi:
956 case kone_mouse_event_osd_profile:
957 case kone_mouse_event_osd_dpi:
958 roccat_report.event = event->event;
959 roccat_report.value = event->value;
960 roccat_report.key = 0;
961 roccat_report_event(kone->chrdev_minor,
962 (uint8_t *)&roccat_report,
963 sizeof(struct kone_roccat_report));
964 break;
965 case kone_mouse_event_call_overlong_macro:
966 if (event->value == kone_keystroke_action_press) {
967 roccat_report.event = kone_mouse_event_call_overlong_macro;
968 roccat_report.value = kone->actual_profile;
969 roccat_report.key = event->macro_key;
970 roccat_report_event(kone->chrdev_minor,
971 (uint8_t *)&roccat_report,
972 sizeof(struct kone_roccat_report));
973 }
974 break;
975 }
976
977}
978
933/* 979/*
934 * Is called for keyboard- and mousepart. 980 * Is called for keyboard- and mousepart.
935 * Only mousepart gets informations about special events in its extended event 981 * Only mousepart gets informations about special events in its extended event
@@ -958,6 +1004,9 @@ static int kone_raw_event(struct hid_device *hdev, struct hid_report *report,
958 1004
959 kone_keep_values_up_to_date(kone, event); 1005 kone_keep_values_up_to_date(kone, event);
960 1006
1007 if (kone->roccat_claimed)
1008 kone_report_to_chrdev(kone, event);
1009
961 return 0; /* always do further processing */ 1010 return 0; /* always do further processing */
962} 1011}
963 1012
diff --git a/drivers/hid/hid-roccat-kone.h b/drivers/hid/hid-roccat-kone.h
index b413b10a7f8a..003e6f81c195 100644
--- a/drivers/hid/hid-roccat-kone.h
+++ b/drivers/hid/hid-roccat-kone.h
@@ -189,6 +189,12 @@ enum kone_commands {
189 kone_command_firmware = 0xe5a 189 kone_command_firmware = 0xe5a
190}; 190};
191 191
192struct kone_roccat_report {
193 uint8_t event;
194 uint8_t value; /* holds dpi or profile value */
195 uint8_t key; /* macro key on overlong macro execution */
196};
197
192#pragma pack(pop) 198#pragma pack(pop)
193 199
194struct kone_device { 200struct kone_device {
@@ -219,6 +225,9 @@ struct kone_device {
219 * so it's read only once 225 * so it's read only once
220 */ 226 */
221 int firmware_version; 227 int firmware_version;
228
229 int roccat_claimed;
230 int chrdev_minor;
222}; 231};
223 232
224#endif 233#endif
diff --git a/drivers/hid/hid-roccat.c b/drivers/hid/hid-roccat.c
new file mode 100644
index 000000000000..e05d48edb66f
--- /dev/null
+++ b/drivers/hid/hid-roccat.c
@@ -0,0 +1,428 @@
1/*
2 * Roccat driver for Linux
3 *
4 * Copyright (c) 2010 Stefan Achatz <erazor_de@users.sourceforge.net>
5 */
6
7/*
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 2 of the License, or (at your option)
11 * any later version.
12 */
13
14/*
15 * Module roccat is a char device used to report special events of roccat
16 * hardware to userland. These events include requests for on-screen-display of
17 * profile or dpi settings or requests for execution of macro sequences that are
18 * not stored in device. The information in these events depends on hid device
19 * implementation and contains data that is not available in a single hid event
20 * or else hidraw could have been used.
21 * It is inspired by hidraw, but uses only one circular buffer for all readers.
22 */
23
24#include <linux/cdev.h>
25#include <linux/poll.h>
26#include <linux/sched.h>
27
28#include "hid-roccat.h"
29
30#define ROCCAT_FIRST_MINOR 0
31#define ROCCAT_MAX_DEVICES 8
32
33/* should be a power of 2 for performance reason */
34#define ROCCAT_CBUF_SIZE 16
35
36struct roccat_report {
37 uint8_t *value;
38 int len;
39};
40
41struct roccat_device {
42 unsigned int minor;
43 int open;
44 int exist;
45 wait_queue_head_t wait;
46 struct device *dev;
47 struct hid_device *hid;
48 struct list_head readers;
49 /* protects modifications of readers list */
50 struct mutex readers_lock;
51
52 /*
53 * circular_buffer has one writer and multiple readers with their own
54 * read pointers
55 */
56 struct roccat_report cbuf[ROCCAT_CBUF_SIZE];
57 int cbuf_end;
58 struct mutex cbuf_lock;
59};
60
61struct roccat_reader {
62 struct list_head node;
63 struct roccat_device *device;
64 int cbuf_start;
65};
66
67static int roccat_major;
68static struct class *roccat_class;
69static struct cdev roccat_cdev;
70
71static struct roccat_device *devices[ROCCAT_MAX_DEVICES];
72/* protects modifications of devices array */
73static DEFINE_MUTEX(devices_lock);
74
75static ssize_t roccat_read(struct file *file, char __user *buffer,
76 size_t count, loff_t *ppos)
77{
78 struct roccat_reader *reader = file->private_data;
79 struct roccat_device *device = reader->device;
80 struct roccat_report *report;
81 ssize_t retval = 0, len;
82 DECLARE_WAITQUEUE(wait, current);
83
84 mutex_lock(&device->cbuf_lock);
85
86 /* no data? */
87 if (reader->cbuf_start == device->cbuf_end) {
88 add_wait_queue(&device->wait, &wait);
89 set_current_state(TASK_INTERRUPTIBLE);
90
91 /* wait for data */
92 while (reader->cbuf_start == device->cbuf_end) {
93 if (file->f_flags & O_NONBLOCK) {
94 retval = -EAGAIN;
95 break;
96 }
97 if (signal_pending(current)) {
98 retval = -ERESTARTSYS;
99 break;
100 }
101 if (!device->exist) {
102 retval = -EIO;
103 break;
104 }
105
106 mutex_unlock(&device->cbuf_lock);
107 schedule();
108 mutex_lock(&device->cbuf_lock);
109 set_current_state(TASK_INTERRUPTIBLE);
110 }
111
112 set_current_state(TASK_RUNNING);
113 remove_wait_queue(&device->wait, &wait);
114 }
115
116 /* here we either have data or a reason to return if retval is set */
117 if (retval)
118 goto exit_unlock;
119
120 report = &device->cbuf[reader->cbuf_start];
121 /*
122 * If report is larger than requested amount of data, rest of report
123 * is lost!
124 */
125 len = report->len > count ? count : report->len;
126
127 if (copy_to_user(buffer, report->value, len)) {
128 retval = -EFAULT;
129 goto exit_unlock;
130 }
131 retval += len;
132 reader->cbuf_start = (reader->cbuf_start + 1) % ROCCAT_CBUF_SIZE;
133
134exit_unlock:
135 mutex_unlock(&device->cbuf_lock);
136 return retval;
137}
138
139static unsigned int roccat_poll(struct file *file, poll_table *wait)
140{
141 struct roccat_reader *reader = file->private_data;
142 poll_wait(file, &reader->device->wait, wait);
143 if (reader->cbuf_start != reader->device->cbuf_end)
144 return POLLIN | POLLRDNORM;
145 if (!reader->device->exist)
146 return POLLERR | POLLHUP;
147 return 0;
148}
149
150static int roccat_open(struct inode *inode, struct file *file)
151{
152 unsigned int minor = iminor(inode);
153 struct roccat_reader *reader;
154 struct roccat_device *device;
155 int error = 0;
156
157 reader = kzalloc(sizeof(struct roccat_reader), GFP_KERNEL);
158 if (!reader)
159 return -ENOMEM;
160
161 mutex_lock(&devices_lock);
162
163 device = devices[minor];
164
165 mutex_lock(&device->readers_lock);
166
167 if (!device) {
168 printk(KERN_EMERG "roccat device with minor %d doesn't exist\n",
169 minor);
170 error = -ENODEV;
171 goto exit_unlock;
172 }
173
174 if (!device->open++) {
175 /* power on device on adding first reader */
176 if (device->hid->ll_driver->power) {
177 error = device->hid->ll_driver->power(device->hid,
178 PM_HINT_FULLON);
179 if (error < 0) {
180 --device->open;
181 goto exit_unlock;
182 }
183 }
184 error = device->hid->ll_driver->open(device->hid);
185 if (error < 0) {
186 if (device->hid->ll_driver->power)
187 device->hid->ll_driver->power(device->hid,
188 PM_HINT_NORMAL);
189 --device->open;
190 goto exit_unlock;
191 }
192 }
193
194 reader->device = device;
195 /* new reader doesn't get old events */
196 reader->cbuf_start = device->cbuf_end;
197
198 list_add_tail(&reader->node, &device->readers);
199 file->private_data = reader;
200
201exit_unlock:
202 mutex_unlock(&device->readers_lock);
203 mutex_unlock(&devices_lock);
204 return error;
205}
206
207static int roccat_release(struct inode *inode, struct file *file)
208{
209 unsigned int minor = iminor(inode);
210 struct roccat_reader *reader = file->private_data;
211 struct roccat_device *device;
212
213 mutex_lock(&devices_lock);
214
215 device = devices[minor];
216 if (!device) {
217 mutex_unlock(&devices_lock);
218 printk(KERN_EMERG "roccat device with minor %d doesn't exist\n",
219 minor);
220 return -ENODEV;
221 }
222
223 mutex_lock(&device->readers_lock);
224 list_del(&reader->node);
225 mutex_unlock(&device->readers_lock);
226 kfree(reader);
227
228 if (!--device->open) {
229 /* removing last reader */
230 if (device->exist) {
231 if (device->hid->ll_driver->power)
232 device->hid->ll_driver->power(device->hid,
233 PM_HINT_NORMAL);
234 device->hid->ll_driver->close(device->hid);
235 } else {
236 kfree(device);
237 }
238 }
239
240 mutex_unlock(&devices_lock);
241
242 return 0;
243}
244
245/*
246 * roccat_report_event() - output data to readers
247 * @minor: minor device number returned by roccat_connect()
248 * @data: pointer to data
249 * @len: size of data
250 *
251 * Return value is zero on success, a negative error code on failure.
252 *
253 * This is called from interrupt handler.
254 */
255int roccat_report_event(int minor, u8 const *data, int len)
256{
257 struct roccat_device *device;
258 struct roccat_reader *reader;
259 struct roccat_report *report;
260 uint8_t *new_value;
261
262 new_value = kmemdup(data, len, GFP_ATOMIC);
263 if (!new_value)
264 return -ENOMEM;
265
266 device = devices[minor];
267
268 report = &device->cbuf[device->cbuf_end];
269
270 /* passing NULL is safe */
271 kfree(report->value);
272
273 report->value = new_value;
274 report->len = len;
275 device->cbuf_end = (device->cbuf_end + 1) % ROCCAT_CBUF_SIZE;
276
277 list_for_each_entry(reader, &device->readers, node) {
278 /*
279 * As we already inserted one element, the buffer can't be
280 * empty. If start and end are equal, buffer is full and we
281 * increase start, so that slow reader misses one event, but
282 * gets the newer ones in the right order.
283 */
284 if (reader->cbuf_start == device->cbuf_end)
285 reader->cbuf_start = (reader->cbuf_start + 1) % ROCCAT_CBUF_SIZE;
286 }
287
288 wake_up_interruptible(&device->wait);
289 return 0;
290}
291EXPORT_SYMBOL_GPL(roccat_report_event);
292
293/*
294 * roccat_connect() - create a char device for special event output
295 * @hid: the hid device the char device should be connected to.
296 *
297 * Return value is minor device number in Range [0, ROCCAT_MAX_DEVICES] on
298 * success, a negative error code on failure.
299 */
300int roccat_connect(struct hid_device *hid)
301{
302 unsigned int minor;
303 struct roccat_device *device;
304 int temp;
305
306 device = kzalloc(sizeof(struct roccat_device), GFP_KERNEL);
307 if (!device)
308 return -ENOMEM;
309
310 mutex_lock(&devices_lock);
311
312 for (minor = 0; minor < ROCCAT_MAX_DEVICES; ++minor) {
313 if (devices[minor])
314 continue;
315 break;
316 }
317
318 if (minor < ROCCAT_MAX_DEVICES) {
319 devices[minor] = device;
320 } else {
321 mutex_unlock(&devices_lock);
322 kfree(device);
323 return -EINVAL;
324 }
325
326 device->dev = device_create(roccat_class, &hid->dev,
327 MKDEV(roccat_major, minor), NULL,
328 "%s%s%d", "roccat", hid->driver->name, minor);
329
330 if (IS_ERR(device->dev)) {
331 devices[minor] = NULL;
332 mutex_unlock(&devices_lock);
333 temp = PTR_ERR(device->dev);
334 kfree(device);
335 return temp;
336 }
337
338 mutex_unlock(&devices_lock);
339
340 init_waitqueue_head(&device->wait);
341 INIT_LIST_HEAD(&device->readers);
342 mutex_init(&device->readers_lock);
343 mutex_init(&device->cbuf_lock);
344 device->minor = minor;
345 device->hid = hid;
346 device->exist = 1;
347 device->cbuf_end = 0;
348
349 return minor;
350}
351EXPORT_SYMBOL_GPL(roccat_connect);
352
353/* roccat_disconnect() - remove char device from hid device
354 * @minor: the minor device number returned by roccat_connect()
355 */
356void roccat_disconnect(int minor)
357{
358 struct roccat_device *device;
359
360 mutex_lock(&devices_lock);
361 device = devices[minor];
362 devices[minor] = NULL;
363 mutex_unlock(&devices_lock);
364
365 device->exist = 0; /* TODO exist maybe not needed */
366
367 device_destroy(roccat_class, MKDEV(roccat_major, minor));
368
369 if (device->open) {
370 device->hid->ll_driver->close(device->hid);
371 wake_up_interruptible(&device->wait);
372 } else {
373 kfree(device);
374 }
375}
376EXPORT_SYMBOL_GPL(roccat_disconnect);
377
378static const struct file_operations roccat_ops = {
379 .owner = THIS_MODULE,
380 .read = roccat_read,
381 .poll = roccat_poll,
382 .open = roccat_open,
383 .release = roccat_release,
384};
385
386static int __init roccat_init(void)
387{
388 int retval;
389 dev_t dev_id;
390
391 retval = alloc_chrdev_region(&dev_id, ROCCAT_FIRST_MINOR,
392 ROCCAT_MAX_DEVICES, "roccat");
393
394 roccat_major = MAJOR(dev_id);
395
396 if (retval < 0) {
397 printk(KERN_WARNING "roccat: can't get major number\n");
398 return retval;
399 }
400
401 roccat_class = class_create(THIS_MODULE, "roccat");
402 if (IS_ERR(roccat_class)) {
403 retval = PTR_ERR(roccat_class);
404 unregister_chrdev_region(dev_id, ROCCAT_MAX_DEVICES);
405 return retval;
406 }
407
408 cdev_init(&roccat_cdev, &roccat_ops);
409 cdev_add(&roccat_cdev, dev_id, ROCCAT_MAX_DEVICES);
410
411 return 0;
412}
413
414static void __exit roccat_exit(void)
415{
416 dev_t dev_id = MKDEV(roccat_major, 0);
417
418 cdev_del(&roccat_cdev);
419 class_destroy(roccat_class);
420 unregister_chrdev_region(dev_id, ROCCAT_MAX_DEVICES);
421}
422
423module_init(roccat_init);
424module_exit(roccat_exit);
425
426MODULE_AUTHOR("Stefan Achatz");
427MODULE_DESCRIPTION("USB Roccat char device");
428MODULE_LICENSE("GPL v2");
diff --git a/drivers/hid/hid-roccat.h b/drivers/hid/hid-roccat.h
new file mode 100644
index 000000000000..d8aae0c1fa7e
--- /dev/null
+++ b/drivers/hid/hid-roccat.h
@@ -0,0 +1,31 @@
1#ifndef __HID_ROCCAT_H
2#define __HID_ROCCAT_H
3
4/*
5 * Copyright (c) 2010 Stefan Achatz <erazor_de@users.sourceforge.net>
6 */
7
8/*
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the Free
11 * Software Foundation; either version 2 of the License, or (at your option)
12 * any later version.
13 */
14
15#include <linux/hid.h>
16#include <linux/types.h>
17
18#if defined(CONFIG_HID_ROCCAT) || defined (CONFIG_HID_ROCCAT_MODULE)
19int roccat_connect(struct hid_device *hid);
20void roccat_disconnect(int minor);
21int roccat_report_event(int minor, u8 const *data, int len);
22#else
23static inline int roccat_connect(struct hid_device *hid) { return -1; }
24static inline void roccat_disconnect(int minor) {}
25static inline int roccat_report_event(int minor, u8 const *data, int len)
26{
27 return 0;
28}
29#endif
30
31#endif
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 6a9ac754ca5d..e19cf8eb6ccf 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -447,13 +447,14 @@ config SENSORS_IT87
447 will be called it87. 447 will be called it87.
448 448
449config SENSORS_LM63 449config SENSORS_LM63
450 tristate "National Semiconductor LM63" 450 tristate "National Semiconductor LM63 and LM64"
451 depends on I2C 451 depends on I2C
452 help 452 help
453 If you say yes here you get support for the National Semiconductor 453 If you say yes here you get support for the National
454 LM63 remote diode digital temperature sensor with integrated fan 454 Semiconductor LM63 and LM64 remote diode digital temperature
455 control. Such chips are found on the Tyan S4882 (Thunder K8QS Pro) 455 sensors with integrated fan control. Such chips are found
456 motherboard, among others. 456 on the Tyan S4882 (Thunder K8QS Pro) motherboard, among
457 others.
457 458
458 This driver can also be built as a module. If so, the module 459 This driver can also be built as a module. If so, the module
459 will be called lm63. 460 will be called lm63.
@@ -492,7 +493,8 @@ config SENSORS_LM75
492 - NXP's LM75A 493 - NXP's LM75A
493 - ST Microelectronics STDS75 494 - ST Microelectronics STDS75
494 - TelCom (now Microchip) TCN75 495 - TelCom (now Microchip) TCN75
495 - Texas Instruments TMP100, TMP101, TMP75, TMP175, TMP275 496 - Texas Instruments TMP100, TMP101, TMP105, TMP75, TMP175,
497 TMP275
496 498
497 This driver supports driver model based binding through board 499 This driver supports driver model based binding through board
498 specific I2C device tables. 500 specific I2C device tables.
@@ -749,6 +751,16 @@ config SENSORS_DME1737
749 This driver can also be built as a module. If so, the module 751 This driver can also be built as a module. If so, the module
750 will be called dme1737. 752 will be called dme1737.
751 753
754config SENSORS_EMC1403
755 tristate "SMSC EMC1403 thermal sensor"
756 depends on I2C
757 help
758 If you say yes here you get support for the SMSC EMC1403
759 temperature monitoring chip.
760
761 Threshold values can be configured using sysfs.
762 Data from the different diodes are accessible via sysfs.
763
752config SENSORS_SMSC47M1 764config SENSORS_SMSC47M1
753 tristate "SMSC LPC47M10x and compatibles" 765 tristate "SMSC LPC47M10x and compatibles"
754 help 766 help
@@ -831,6 +843,16 @@ config SENSORS_THMC50
831 This driver can also be built as a module. If so, the module 843 This driver can also be built as a module. If so, the module
832 will be called thmc50. 844 will be called thmc50.
833 845
846config SENSORS_TMP102
847 tristate "Texas Instruments TMP102"
848 depends on I2C && EXPERIMENTAL
849 help
850 If you say yes here you get support for Texas Instruments TMP102
851 sensor chips.
852
853 This driver can also be built as a module. If so, the module
854 will be called tmp102.
855
834config SENSORS_TMP401 856config SENSORS_TMP401
835 tristate "Texas Instruments TMP401 and compatibles" 857 tristate "Texas Instruments TMP401 and compatibles"
836 depends on I2C && EXPERIMENTAL 858 depends on I2C && EXPERIMENTAL
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 86920fb34118..2138ceb1a713 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -41,6 +41,7 @@ obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o
41obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o 41obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o
42obj-$(CONFIG_SENSORS_DME1737) += dme1737.o 42obj-$(CONFIG_SENSORS_DME1737) += dme1737.o
43obj-$(CONFIG_SENSORS_DS1621) += ds1621.o 43obj-$(CONFIG_SENSORS_DS1621) += ds1621.o
44obj-$(CONFIG_SENSORS_EMC1403) += emc1403.o
44obj-$(CONFIG_SENSORS_F71805F) += f71805f.o 45obj-$(CONFIG_SENSORS_F71805F) += f71805f.o
45obj-$(CONFIG_SENSORS_F71882FG) += f71882fg.o 46obj-$(CONFIG_SENSORS_F71882FG) += f71882fg.o
46obj-$(CONFIG_SENSORS_F75375S) += f75375s.o 47obj-$(CONFIG_SENSORS_F75375S) += f75375s.o
@@ -90,6 +91,7 @@ obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o
90obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o 91obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o
91obj-$(CONFIG_SENSORS_AMC6821) += amc6821.o 92obj-$(CONFIG_SENSORS_AMC6821) += amc6821.o
92obj-$(CONFIG_SENSORS_THMC50) += thmc50.o 93obj-$(CONFIG_SENSORS_THMC50) += thmc50.o
94obj-$(CONFIG_SENSORS_TMP102) += tmp102.o
93obj-$(CONFIG_SENSORS_TMP401) += tmp401.o 95obj-$(CONFIG_SENSORS_TMP401) += tmp401.o
94obj-$(CONFIG_SENSORS_TMP421) += tmp421.o 96obj-$(CONFIG_SENSORS_TMP421) += tmp421.o
95obj-$(CONFIG_SENSORS_VIA_CPUTEMP)+= via-cputemp.o 97obj-$(CONFIG_SENSORS_VIA_CPUTEMP)+= via-cputemp.o
diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c
index 1644b92e7cc4..15c1a9616af3 100644
--- a/drivers/hwmon/adm1031.c
+++ b/drivers/hwmon/adm1031.c
@@ -36,6 +36,7 @@
36#define ADM1031_REG_FAN_DIV(nr) (0x20 + (nr)) 36#define ADM1031_REG_FAN_DIV(nr) (0x20 + (nr))
37#define ADM1031_REG_PWM (0x22) 37#define ADM1031_REG_PWM (0x22)
38#define ADM1031_REG_FAN_MIN(nr) (0x10 + (nr)) 38#define ADM1031_REG_FAN_MIN(nr) (0x10 + (nr))
39#define ADM1031_REG_FAN_FILTER (0x23)
39 40
40#define ADM1031_REG_TEMP_OFFSET(nr) (0x0d + (nr)) 41#define ADM1031_REG_TEMP_OFFSET(nr) (0x0d + (nr))
41#define ADM1031_REG_TEMP_MAX(nr) (0x14 + 4 * (nr)) 42#define ADM1031_REG_TEMP_MAX(nr) (0x14 + 4 * (nr))
@@ -61,6 +62,9 @@
61#define ADM1031_CONF2_TACH2_ENABLE 0x08 62#define ADM1031_CONF2_TACH2_ENABLE 0x08
62#define ADM1031_CONF2_TEMP_ENABLE(chan) (0x10 << (chan)) 63#define ADM1031_CONF2_TEMP_ENABLE(chan) (0x10 << (chan))
63 64
65#define ADM1031_UPDATE_RATE_MASK 0x1c
66#define ADM1031_UPDATE_RATE_SHIFT 2
67
64/* Addresses to scan */ 68/* Addresses to scan */
65static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; 69static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
66 70
@@ -75,6 +79,7 @@ struct adm1031_data {
75 int chip_type; 79 int chip_type;
76 char valid; /* !=0 if following fields are valid */ 80 char valid; /* !=0 if following fields are valid */
77 unsigned long last_updated; /* In jiffies */ 81 unsigned long last_updated; /* In jiffies */
82 unsigned int update_rate; /* In milliseconds */
78 /* The chan_select_table contains the possible configurations for 83 /* The chan_select_table contains the possible configurations for
79 * auto fan control. 84 * auto fan control.
80 */ 85 */
@@ -738,6 +743,57 @@ static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 12);
738static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 13); 743static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 13);
739static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 14); 744static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 14);
740 745
746/* Update Rate */
747static const unsigned int update_rates[] = {
748 16000, 8000, 4000, 2000, 1000, 500, 250, 125,
749};
750
751static ssize_t show_update_rate(struct device *dev,
752 struct device_attribute *attr, char *buf)
753{
754 struct i2c_client *client = to_i2c_client(dev);
755 struct adm1031_data *data = i2c_get_clientdata(client);
756
757 return sprintf(buf, "%u\n", data->update_rate);
758}
759
760static ssize_t set_update_rate(struct device *dev,
761 struct device_attribute *attr,
762 const char *buf, size_t count)
763{
764 struct i2c_client *client = to_i2c_client(dev);
765 struct adm1031_data *data = i2c_get_clientdata(client);
766 unsigned long val;
767 int i, err;
768 u8 reg;
769
770 err = strict_strtoul(buf, 10, &val);
771 if (err)
772 return err;
773
774 /* find the nearest update rate from the table */
775 for (i = 0; i < ARRAY_SIZE(update_rates) - 1; i++) {
776 if (val >= update_rates[i])
777 break;
778 }
779 /* if not found, we point to the last entry (lowest update rate) */
780
781 /* set the new update rate while preserving other settings */
782 reg = adm1031_read_value(client, ADM1031_REG_FAN_FILTER);
783 reg &= ~ADM1031_UPDATE_RATE_MASK;
784 reg |= i << ADM1031_UPDATE_RATE_SHIFT;
785 adm1031_write_value(client, ADM1031_REG_FAN_FILTER, reg);
786
787 mutex_lock(&data->update_lock);
788 data->update_rate = update_rates[i];
789 mutex_unlock(&data->update_lock);
790
791 return count;
792}
793
794static DEVICE_ATTR(update_rate, S_IRUGO | S_IWUSR, show_update_rate,
795 set_update_rate);
796
741static struct attribute *adm1031_attributes[] = { 797static struct attribute *adm1031_attributes[] = {
742 &sensor_dev_attr_fan1_input.dev_attr.attr, 798 &sensor_dev_attr_fan1_input.dev_attr.attr,
743 &sensor_dev_attr_fan1_div.dev_attr.attr, 799 &sensor_dev_attr_fan1_div.dev_attr.attr,
@@ -774,6 +830,7 @@ static struct attribute *adm1031_attributes[] = {
774 830
775 &sensor_dev_attr_auto_fan1_min_pwm.dev_attr.attr, 831 &sensor_dev_attr_auto_fan1_min_pwm.dev_attr.attr,
776 832
833 &dev_attr_update_rate.attr,
777 &dev_attr_alarms.attr, 834 &dev_attr_alarms.attr,
778 835
779 NULL 836 NULL
@@ -900,6 +957,7 @@ static void adm1031_init_client(struct i2c_client *client)
900{ 957{
901 unsigned int read_val; 958 unsigned int read_val;
902 unsigned int mask; 959 unsigned int mask;
960 int i;
903 struct adm1031_data *data = i2c_get_clientdata(client); 961 struct adm1031_data *data = i2c_get_clientdata(client);
904 962
905 mask = (ADM1031_CONF2_PWM1_ENABLE | ADM1031_CONF2_TACH1_ENABLE); 963 mask = (ADM1031_CONF2_PWM1_ENABLE | ADM1031_CONF2_TACH1_ENABLE);
@@ -919,18 +977,24 @@ static void adm1031_init_client(struct i2c_client *client)
919 ADM1031_CONF1_MONITOR_ENABLE); 977 ADM1031_CONF1_MONITOR_ENABLE);
920 } 978 }
921 979
980 /* Read the chip's update rate */
981 mask = ADM1031_UPDATE_RATE_MASK;
982 read_val = adm1031_read_value(client, ADM1031_REG_FAN_FILTER);
983 i = (read_val & mask) >> ADM1031_UPDATE_RATE_SHIFT;
984 data->update_rate = update_rates[i];
922} 985}
923 986
924static struct adm1031_data *adm1031_update_device(struct device *dev) 987static struct adm1031_data *adm1031_update_device(struct device *dev)
925{ 988{
926 struct i2c_client *client = to_i2c_client(dev); 989 struct i2c_client *client = to_i2c_client(dev);
927 struct adm1031_data *data = i2c_get_clientdata(client); 990 struct adm1031_data *data = i2c_get_clientdata(client);
991 unsigned long next_update;
928 int chan; 992 int chan;
929 993
930 mutex_lock(&data->update_lock); 994 mutex_lock(&data->update_lock);
931 995
932 if (time_after(jiffies, data->last_updated + HZ + HZ / 2) 996 next_update = data->last_updated + msecs_to_jiffies(data->update_rate);
933 || !data->valid) { 997 if (time_after(jiffies, next_update) || !data->valid) {
934 998
935 dev_dbg(&client->dev, "Starting adm1031 update\n"); 999 dev_dbg(&client->dev, "Starting adm1031 update\n");
936 for (chan = 0; 1000 for (chan = 0;
diff --git a/drivers/hwmon/adt7411.c b/drivers/hwmon/adt7411.c
index 4086c7257f91..f13c843a2964 100644
--- a/drivers/hwmon/adt7411.c
+++ b/drivers/hwmon/adt7411.c
@@ -316,7 +316,6 @@ static int __devinit adt7411_probe(struct i2c_client *client,
316 exit_remove: 316 exit_remove:
317 sysfs_remove_group(&client->dev.kobj, &adt7411_attr_grp); 317 sysfs_remove_group(&client->dev.kobj, &adt7411_attr_grp);
318 exit_free: 318 exit_free:
319 i2c_set_clientdata(client, NULL);
320 kfree(data); 319 kfree(data);
321 return ret; 320 return ret;
322} 321}
@@ -327,7 +326,6 @@ static int __devexit adt7411_remove(struct i2c_client *client)
327 326
328 hwmon_device_unregister(data->hwmon_dev); 327 hwmon_device_unregister(data->hwmon_dev);
329 sysfs_remove_group(&client->dev.kobj, &adt7411_attr_grp); 328 sysfs_remove_group(&client->dev.kobj, &adt7411_attr_grp);
330 i2c_set_clientdata(client, NULL);
331 kfree(data); 329 kfree(data);
332 return 0; 330 return 0;
333} 331}
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index f085c18d2905..b6598aa557a0 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -148,6 +148,20 @@ static const char *temperature_sensors_sets[][41] = {
148/* Set 18: MacBook Pro 2,2 */ 148/* Set 18: MacBook Pro 2,2 */
149 { "TB0T", "TC0D", "TC0P", "TG0H", "TG0P", "TG0T", "TM0P", "TTF0", 149 { "TB0T", "TC0D", "TC0P", "TG0H", "TG0P", "TG0T", "TM0P", "TTF0",
150 "Th0H", "Th1H", "Tm0P", "Ts0P", NULL }, 150 "Th0H", "Th1H", "Tm0P", "Ts0P", NULL },
151/* Set 19: Macbook Pro 5,3 */
152 { "TB0T", "TB1T", "TB2T", "TB3T", "TC0D", "TC0F", "TC0P", "TG0D",
153 "TG0F", "TG0H", "TG0P", "TG0T", "TN0D", "TN0P", "TTF0", "Th2H",
154 "Tm0P", "Ts0P", "Ts0S", NULL },
155/* Set 20: MacBook Pro 5,4 */
156 { "TB0T", "TB1T", "TB2T", "TB3T", "TC0D", "TC0F", "TC0P", "TN0D",
157 "TN0P", "TTF0", "Th2H", "Ts0P", "Ts0S", NULL },
158/* Set 21: MacBook Pro 6,2 */
159 { "TB0T", "TB1T", "TB2T", "TC0C", "TC0D", "TC0P", "TC1C", "TG0D",
160 "TG0P", "TG0T", "TMCD", "TP0P", "TPCD", "Th1H", "Th2H", "Tm0P",
161 "Ts0P", "Ts0S", NULL },
162/* Set 22: MacBook Pro 7,1 */
163 { "TB0T", "TB1T", "TB2T", "TC0D", "TC0P", "TN0D", "TN0P", "TN0S",
164 "TN1D", "TN1F", "TN1G", "TN1S", "Th1H", "Ts0P", "Ts0S", NULL },
151}; 165};
152 166
153/* List of keys used to read/write fan speeds */ 167/* List of keys used to read/write fan speeds */
@@ -646,6 +660,17 @@ out:
646 return snprintf(sysfsbuf, PAGE_SIZE, "(%d,%d)\n", left, right); 660 return snprintf(sysfsbuf, PAGE_SIZE, "(%d,%d)\n", left, right);
647} 661}
648 662
663/* Displays sensor key as label */
664static ssize_t applesmc_show_sensor_label(struct device *dev,
665 struct device_attribute *devattr, char *sysfsbuf)
666{
667 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
668 const char *key =
669 temperature_sensors_sets[applesmc_temperature_set][attr->index];
670
671 return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", key);
672}
673
649/* Displays degree Celsius * 1000 */ 674/* Displays degree Celsius * 1000 */
650static ssize_t applesmc_show_temperature(struct device *dev, 675static ssize_t applesmc_show_temperature(struct device *dev,
651 struct device_attribute *devattr, char *sysfsbuf) 676 struct device_attribute *devattr, char *sysfsbuf)
@@ -1113,6 +1138,86 @@ static const struct attribute_group fan_attribute_groups[] = {
1113/* 1138/*
1114 * Temperature sensors sysfs entries. 1139 * Temperature sensors sysfs entries.
1115 */ 1140 */
1141static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO,
1142 applesmc_show_sensor_label, NULL, 0);
1143static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO,
1144 applesmc_show_sensor_label, NULL, 1);
1145static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO,
1146 applesmc_show_sensor_label, NULL, 2);
1147static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO,
1148 applesmc_show_sensor_label, NULL, 3);
1149static SENSOR_DEVICE_ATTR(temp5_label, S_IRUGO,
1150 applesmc_show_sensor_label, NULL, 4);
1151static SENSOR_DEVICE_ATTR(temp6_label, S_IRUGO,
1152 applesmc_show_sensor_label, NULL, 5);
1153static SENSOR_DEVICE_ATTR(temp7_label, S_IRUGO,
1154 applesmc_show_sensor_label, NULL, 6);
1155static SENSOR_DEVICE_ATTR(temp8_label, S_IRUGO,
1156 applesmc_show_sensor_label, NULL, 7);
1157static SENSOR_DEVICE_ATTR(temp9_label, S_IRUGO,
1158 applesmc_show_sensor_label, NULL, 8);
1159static SENSOR_DEVICE_ATTR(temp10_label, S_IRUGO,
1160 applesmc_show_sensor_label, NULL, 9);
1161static SENSOR_DEVICE_ATTR(temp11_label, S_IRUGO,
1162 applesmc_show_sensor_label, NULL, 10);
1163static SENSOR_DEVICE_ATTR(temp12_label, S_IRUGO,
1164 applesmc_show_sensor_label, NULL, 11);
1165static SENSOR_DEVICE_ATTR(temp13_label, S_IRUGO,
1166 applesmc_show_sensor_label, NULL, 12);
1167static SENSOR_DEVICE_ATTR(temp14_label, S_IRUGO,
1168 applesmc_show_sensor_label, NULL, 13);
1169static SENSOR_DEVICE_ATTR(temp15_label, S_IRUGO,
1170 applesmc_show_sensor_label, NULL, 14);
1171static SENSOR_DEVICE_ATTR(temp16_label, S_IRUGO,
1172 applesmc_show_sensor_label, NULL, 15);
1173static SENSOR_DEVICE_ATTR(temp17_label, S_IRUGO,
1174 applesmc_show_sensor_label, NULL, 16);
1175static SENSOR_DEVICE_ATTR(temp18_label, S_IRUGO,
1176 applesmc_show_sensor_label, NULL, 17);
1177static SENSOR_DEVICE_ATTR(temp19_label, S_IRUGO,
1178 applesmc_show_sensor_label, NULL, 18);
1179static SENSOR_DEVICE_ATTR(temp20_label, S_IRUGO,
1180 applesmc_show_sensor_label, NULL, 19);
1181static SENSOR_DEVICE_ATTR(temp21_label, S_IRUGO,
1182 applesmc_show_sensor_label, NULL, 20);
1183static SENSOR_DEVICE_ATTR(temp22_label, S_IRUGO,
1184 applesmc_show_sensor_label, NULL, 21);
1185static SENSOR_DEVICE_ATTR(temp23_label, S_IRUGO,
1186 applesmc_show_sensor_label, NULL, 22);
1187static SENSOR_DEVICE_ATTR(temp24_label, S_IRUGO,
1188 applesmc_show_sensor_label, NULL, 23);
1189static SENSOR_DEVICE_ATTR(temp25_label, S_IRUGO,
1190 applesmc_show_sensor_label, NULL, 24);
1191static SENSOR_DEVICE_ATTR(temp26_label, S_IRUGO,
1192 applesmc_show_sensor_label, NULL, 25);
1193static SENSOR_DEVICE_ATTR(temp27_label, S_IRUGO,
1194 applesmc_show_sensor_label, NULL, 26);
1195static SENSOR_DEVICE_ATTR(temp28_label, S_IRUGO,
1196 applesmc_show_sensor_label, NULL, 27);
1197static SENSOR_DEVICE_ATTR(temp29_label, S_IRUGO,
1198 applesmc_show_sensor_label, NULL, 28);
1199static SENSOR_DEVICE_ATTR(temp30_label, S_IRUGO,
1200 applesmc_show_sensor_label, NULL, 29);
1201static SENSOR_DEVICE_ATTR(temp31_label, S_IRUGO,
1202 applesmc_show_sensor_label, NULL, 30);
1203static SENSOR_DEVICE_ATTR(temp32_label, S_IRUGO,
1204 applesmc_show_sensor_label, NULL, 31);
1205static SENSOR_DEVICE_ATTR(temp33_label, S_IRUGO,
1206 applesmc_show_sensor_label, NULL, 32);
1207static SENSOR_DEVICE_ATTR(temp34_label, S_IRUGO,
1208 applesmc_show_sensor_label, NULL, 33);
1209static SENSOR_DEVICE_ATTR(temp35_label, S_IRUGO,
1210 applesmc_show_sensor_label, NULL, 34);
1211static SENSOR_DEVICE_ATTR(temp36_label, S_IRUGO,
1212 applesmc_show_sensor_label, NULL, 35);
1213static SENSOR_DEVICE_ATTR(temp37_label, S_IRUGO,
1214 applesmc_show_sensor_label, NULL, 36);
1215static SENSOR_DEVICE_ATTR(temp38_label, S_IRUGO,
1216 applesmc_show_sensor_label, NULL, 37);
1217static SENSOR_DEVICE_ATTR(temp39_label, S_IRUGO,
1218 applesmc_show_sensor_label, NULL, 38);
1219static SENSOR_DEVICE_ATTR(temp40_label, S_IRUGO,
1220 applesmc_show_sensor_label, NULL, 39);
1116static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, 1221static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO,
1117 applesmc_show_temperature, NULL, 0); 1222 applesmc_show_temperature, NULL, 0);
1118static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, 1223static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO,
@@ -1194,6 +1299,50 @@ static SENSOR_DEVICE_ATTR(temp39_input, S_IRUGO,
1194static SENSOR_DEVICE_ATTR(temp40_input, S_IRUGO, 1299static SENSOR_DEVICE_ATTR(temp40_input, S_IRUGO,
1195 applesmc_show_temperature, NULL, 39); 1300 applesmc_show_temperature, NULL, 39);
1196 1301
1302static struct attribute *label_attributes[] = {
1303 &sensor_dev_attr_temp1_label.dev_attr.attr,
1304 &sensor_dev_attr_temp2_label.dev_attr.attr,
1305 &sensor_dev_attr_temp3_label.dev_attr.attr,
1306 &sensor_dev_attr_temp4_label.dev_attr.attr,
1307 &sensor_dev_attr_temp5_label.dev_attr.attr,
1308 &sensor_dev_attr_temp6_label.dev_attr.attr,
1309 &sensor_dev_attr_temp7_label.dev_attr.attr,
1310 &sensor_dev_attr_temp8_label.dev_attr.attr,
1311 &sensor_dev_attr_temp9_label.dev_attr.attr,
1312 &sensor_dev_attr_temp10_label.dev_attr.attr,
1313 &sensor_dev_attr_temp11_label.dev_attr.attr,
1314 &sensor_dev_attr_temp12_label.dev_attr.attr,
1315 &sensor_dev_attr_temp13_label.dev_attr.attr,
1316 &sensor_dev_attr_temp14_label.dev_attr.attr,
1317 &sensor_dev_attr_temp15_label.dev_attr.attr,
1318 &sensor_dev_attr_temp16_label.dev_attr.attr,
1319 &sensor_dev_attr_temp17_label.dev_attr.attr,
1320 &sensor_dev_attr_temp18_label.dev_attr.attr,
1321 &sensor_dev_attr_temp19_label.dev_attr.attr,
1322 &sensor_dev_attr_temp20_label.dev_attr.attr,
1323 &sensor_dev_attr_temp21_label.dev_attr.attr,
1324 &sensor_dev_attr_temp22_label.dev_attr.attr,
1325 &sensor_dev_attr_temp23_label.dev_attr.attr,
1326 &sensor_dev_attr_temp24_label.dev_attr.attr,
1327 &sensor_dev_attr_temp25_label.dev_attr.attr,
1328 &sensor_dev_attr_temp26_label.dev_attr.attr,
1329 &sensor_dev_attr_temp27_label.dev_attr.attr,
1330 &sensor_dev_attr_temp28_label.dev_attr.attr,
1331 &sensor_dev_attr_temp29_label.dev_attr.attr,
1332 &sensor_dev_attr_temp30_label.dev_attr.attr,
1333 &sensor_dev_attr_temp31_label.dev_attr.attr,
1334 &sensor_dev_attr_temp32_label.dev_attr.attr,
1335 &sensor_dev_attr_temp33_label.dev_attr.attr,
1336 &sensor_dev_attr_temp34_label.dev_attr.attr,
1337 &sensor_dev_attr_temp35_label.dev_attr.attr,
1338 &sensor_dev_attr_temp36_label.dev_attr.attr,
1339 &sensor_dev_attr_temp37_label.dev_attr.attr,
1340 &sensor_dev_attr_temp38_label.dev_attr.attr,
1341 &sensor_dev_attr_temp39_label.dev_attr.attr,
1342 &sensor_dev_attr_temp40_label.dev_attr.attr,
1343 NULL
1344};
1345
1197static struct attribute *temperature_attributes[] = { 1346static struct attribute *temperature_attributes[] = {
1198 &sensor_dev_attr_temp1_input.dev_attr.attr, 1347 &sensor_dev_attr_temp1_input.dev_attr.attr,
1199 &sensor_dev_attr_temp2_input.dev_attr.attr, 1348 &sensor_dev_attr_temp2_input.dev_attr.attr,
@@ -1241,6 +1390,10 @@ static struct attribute *temperature_attributes[] = {
1241static const struct attribute_group temperature_attributes_group = 1390static const struct attribute_group temperature_attributes_group =
1242 { .attrs = temperature_attributes }; 1391 { .attrs = temperature_attributes };
1243 1392
1393static const struct attribute_group label_attributes_group = {
1394 .attrs = label_attributes
1395};
1396
1244/* Module stuff */ 1397/* Module stuff */
1245 1398
1246/* 1399/*
@@ -1363,6 +1516,14 @@ static __initdata struct dmi_match_data applesmc_dmi_data[] = {
1363 { .accelerometer = 0, .light = 0, .temperature_set = 17 }, 1516 { .accelerometer = 0, .light = 0, .temperature_set = 17 },
1364/* MacBook Pro 2,2: accelerometer, backlight and temperature set 18 */ 1517/* MacBook Pro 2,2: accelerometer, backlight and temperature set 18 */
1365 { .accelerometer = 1, .light = 1, .temperature_set = 18 }, 1518 { .accelerometer = 1, .light = 1, .temperature_set = 18 },
1519/* MacBook Pro 5,3: accelerometer, backlight and temperature set 19 */
1520 { .accelerometer = 1, .light = 1, .temperature_set = 19 },
1521/* MacBook Pro 5,4: accelerometer, backlight and temperature set 20 */
1522 { .accelerometer = 1, .light = 1, .temperature_set = 20 },
1523/* MacBook Pro 6,2: accelerometer, backlight and temperature set 21 */
1524 { .accelerometer = 1, .light = 1, .temperature_set = 21 },
1525/* MacBook Pro 7,1: accelerometer, backlight and temperature set 22 */
1526 { .accelerometer = 1, .light = 1, .temperature_set = 22 },
1366}; 1527};
1367 1528
1368/* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1". 1529/* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1".
@@ -1376,6 +1537,22 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = {
1376 DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), 1537 DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
1377 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir") }, 1538 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir") },
1378 &applesmc_dmi_data[7]}, 1539 &applesmc_dmi_data[7]},
1540 { applesmc_dmi_match, "Apple MacBook Pro 7", {
1541 DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
1542 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro7") },
1543 &applesmc_dmi_data[22]},
1544 { applesmc_dmi_match, "Apple MacBook Pro 5,4", {
1545 DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
1546 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,4") },
1547 &applesmc_dmi_data[20]},
1548 { applesmc_dmi_match, "Apple MacBook Pro 5,3", {
1549 DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
1550 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,3") },
1551 &applesmc_dmi_data[19]},
1552 { applesmc_dmi_match, "Apple MacBook Pro 6", {
1553 DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
1554 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro6") },
1555 &applesmc_dmi_data[21]},
1379 { applesmc_dmi_match, "Apple MacBook Pro 5", { 1556 { applesmc_dmi_match, "Apple MacBook Pro 5", {
1380 DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), 1557 DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
1381 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5") }, 1558 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5") },
@@ -1518,7 +1695,8 @@ static int __init applesmc_init(void)
1518 for (i = 0; 1695 for (i = 0;
1519 temperature_sensors_sets[applesmc_temperature_set][i] != NULL; 1696 temperature_sensors_sets[applesmc_temperature_set][i] != NULL;
1520 i++) { 1697 i++) {
1521 if (temperature_attributes[i] == NULL) { 1698 if (temperature_attributes[i] == NULL ||
1699 label_attributes[i] == NULL) {
1522 printk(KERN_ERR "applesmc: More temperature sensors " 1700 printk(KERN_ERR "applesmc: More temperature sensors "
1523 "in temperature_sensors_sets (at least %i)" 1701 "in temperature_sensors_sets (at least %i)"
1524 "than available sysfs files in " 1702 "than available sysfs files in "
@@ -1530,6 +1708,10 @@ static int __init applesmc_init(void)
1530 temperature_attributes[i]); 1708 temperature_attributes[i]);
1531 if (ret) 1709 if (ret)
1532 goto out_temperature; 1710 goto out_temperature;
1711 ret = sysfs_create_file(&pdev->dev.kobj,
1712 label_attributes[i]);
1713 if (ret)
1714 goto out_temperature;
1533 } 1715 }
1534 1716
1535 if (applesmc_accelerometer) { 1717 if (applesmc_accelerometer) {
@@ -1580,6 +1762,7 @@ out_accelerometer:
1580 if (applesmc_accelerometer) 1762 if (applesmc_accelerometer)
1581 applesmc_release_accelerometer(); 1763 applesmc_release_accelerometer();
1582out_temperature: 1764out_temperature:
1765 sysfs_remove_group(&pdev->dev.kobj, &label_attributes_group);
1583 sysfs_remove_group(&pdev->dev.kobj, &temperature_attributes_group); 1766 sysfs_remove_group(&pdev->dev.kobj, &temperature_attributes_group);
1584out_fans: 1767out_fans:
1585 while (fans_handled) 1768 while (fans_handled)
@@ -1609,6 +1792,7 @@ static void __exit applesmc_exit(void)
1609 } 1792 }
1610 if (applesmc_accelerometer) 1793 if (applesmc_accelerometer)
1611 applesmc_release_accelerometer(); 1794 applesmc_release_accelerometer();
1795 sysfs_remove_group(&pdev->dev.kobj, &label_attributes_group);
1612 sysfs_remove_group(&pdev->dev.kobj, &temperature_attributes_group); 1796 sysfs_remove_group(&pdev->dev.kobj, &temperature_attributes_group);
1613 while (fans_handled) 1797 while (fans_handled)
1614 sysfs_remove_group(&pdev->dev.kobj, 1798 sysfs_remove_group(&pdev->dev.kobj,
diff --git a/drivers/hwmon/asc7621.c b/drivers/hwmon/asc7621.c
index 0f388adc6187..3b973f30b1f6 100644
--- a/drivers/hwmon/asc7621.c
+++ b/drivers/hwmon/asc7621.c
@@ -1141,7 +1141,6 @@ exit_remove:
1141 &(asc7621_params[i].sda.dev_attr)); 1141 &(asc7621_params[i].sda.dev_attr));
1142 } 1142 }
1143 1143
1144 i2c_set_clientdata(client, NULL);
1145 kfree(data); 1144 kfree(data);
1146 return err; 1145 return err;
1147} 1146}
@@ -1196,7 +1195,6 @@ static int asc7621_remove(struct i2c_client *client)
1196 &(asc7621_params[i].sda.dev_attr)); 1195 &(asc7621_params[i].sda.dev_attr));
1197 } 1196 }
1198 1197
1199 i2c_set_clientdata(client, NULL);
1200 kfree(data); 1198 kfree(data);
1201 return 0; 1199 return 0;
1202} 1200}
diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c
index 16c420240724..653db1bda934 100644
--- a/drivers/hwmon/asus_atk0110.c
+++ b/drivers/hwmon/asus_atk0110.c
@@ -1411,6 +1411,13 @@ static int __init atk0110_init(void)
1411{ 1411{
1412 int ret; 1412 int ret;
1413 1413
1414 /* Make sure it's safe to access the device through ACPI */
1415 if (!acpi_resources_are_enforced()) {
1416 pr_err("atk: Resources not safely usable due to "
1417 "acpi_enforce_resources kernel parameter\n");
1418 return -EBUSY;
1419 }
1420
1414 ret = acpi_bus_register_driver(&atk_driver); 1421 ret = acpi_bus_register_driver(&atk_driver);
1415 if (ret) 1422 if (ret)
1416 pr_info("atk: acpi_bus_register_driver failed: %d\n", ret); 1423 pr_info("atk: acpi_bus_register_driver failed: %d\n", ret);
diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c
index 823dd28a902c..980c17d5eeae 100644
--- a/drivers/hwmon/dme1737.c
+++ b/drivers/hwmon/dme1737.c
@@ -1,12 +1,14 @@
1/* 1/*
2 * dme1737.c - Driver for the SMSC DME1737, Asus A8000, SMSC SCH311x and 2 * dme1737.c - Driver for the SMSC DME1737, Asus A8000, SMSC SCH311x, SCH5027,
3 * SCH5027 Super-I/O chips integrated hardware monitoring features. 3 * and SCH5127 Super-I/O chips integrated hardware monitoring
4 * Copyright (c) 2007, 2008 Juerg Haefliger <juergh@gmail.com> 4 * features.
5 * Copyright (c) 2007, 2008, 2009, 2010 Juerg Haefliger <juergh@gmail.com>
5 * 6 *
6 * This driver is an I2C/ISA hybrid, meaning that it uses the I2C bus to access 7 * This driver is an I2C/ISA hybrid, meaning that it uses the I2C bus to access
7 * the chip registers if a DME1737, A8000, or SCH5027 is found and the ISA bus 8 * the chip registers if a DME1737, A8000, or SCH5027 is found and the ISA bus
8 * if a SCH311x chip is found. Both types of chips have very similar hardware 9 * if a SCH311x or SCH5127 chip is found. Both types of chips have very
9 * monitoring capabilities but differ in the way they can be accessed. 10 * similar hardware monitoring capabilities but differ in the way they can be
11 * accessed.
10 * 12 *
11 * This program is free software; you can redistribute it and/or modify 13 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by 14 * it under the terms of the GNU General Public License as published by
@@ -57,7 +59,7 @@ MODULE_PARM_DESC(probe_all_addr, "Include probing of non-standard LPC "
57/* Addresses to scan */ 59/* Addresses to scan */
58static const unsigned short normal_i2c[] = {0x2c, 0x2d, 0x2e, I2C_CLIENT_END}; 60static const unsigned short normal_i2c[] = {0x2c, 0x2d, 0x2e, I2C_CLIENT_END};
59 61
60enum chips { dme1737, sch5027, sch311x }; 62enum chips { dme1737, sch5027, sch311x, sch5127 };
61 63
62/* --------------------------------------------------------------------- 64/* ---------------------------------------------------------------------
63 * Registers 65 * Registers
@@ -164,10 +166,29 @@ static const u8 DME1737_BIT_ALARM_FAN[] = {10, 11, 12, 13, 22, 23};
164#define DME1737_VERSTEP_MASK 0xf8 166#define DME1737_VERSTEP_MASK 0xf8
165#define SCH311X_DEVICE 0x8c 167#define SCH311X_DEVICE 0x8c
166#define SCH5027_VERSTEP 0x69 168#define SCH5027_VERSTEP 0x69
169#define SCH5127_DEVICE 0x8e
170
171/* Device ID values (global configuration register index 0x20) */
172#define DME1737_ID_1 0x77
173#define DME1737_ID_2 0x78
174#define SCH3112_ID 0x7c
175#define SCH3114_ID 0x7d
176#define SCH3116_ID 0x7f
177#define SCH5027_ID 0x89
178#define SCH5127_ID 0x86
167 179
168/* Length of ISA address segment */ 180/* Length of ISA address segment */
169#define DME1737_EXTENT 2 181#define DME1737_EXTENT 2
170 182
183/* chip-dependent features */
184#define HAS_TEMP_OFFSET (1 << 0) /* bit 0 */
185#define HAS_VID (1 << 1) /* bit 1 */
186#define HAS_ZONE3 (1 << 2) /* bit 2 */
187#define HAS_ZONE_HYST (1 << 3) /* bit 3 */
188#define HAS_PWM_MIN (1 << 4) /* bit 4 */
189#define HAS_FAN(ix) (1 << ((ix) + 5)) /* bits 5-10 */
190#define HAS_PWM(ix) (1 << ((ix) + 11)) /* bits 11-16 */
191
171/* --------------------------------------------------------------------- 192/* ---------------------------------------------------------------------
172 * Data structures and manipulation thereof 193 * Data structures and manipulation thereof
173 * --------------------------------------------------------------------- */ 194 * --------------------------------------------------------------------- */
@@ -187,8 +208,7 @@ struct dme1737_data {
187 208
188 u8 vid; 209 u8 vid;
189 u8 pwm_rr_en; 210 u8 pwm_rr_en;
190 u8 has_pwm; 211 u32 has_features;
191 u8 has_fan;
192 212
193 /* Register values */ 213 /* Register values */
194 u16 in[7]; 214 u16 in[7];
@@ -224,8 +244,11 @@ static const int IN_NOMINAL_SCH311x[] = {2500, 1500, 3300, 5000, 12000, 3300,
224 3300}; 244 3300};
225static const int IN_NOMINAL_SCH5027[] = {5000, 2250, 3300, 1125, 1125, 3300, 245static const int IN_NOMINAL_SCH5027[] = {5000, 2250, 3300, 1125, 1125, 3300,
226 3300}; 246 3300};
247static const int IN_NOMINAL_SCH5127[] = {2500, 2250, 3300, 1125, 1125, 3300,
248 3300};
227#define IN_NOMINAL(type) ((type) == sch311x ? IN_NOMINAL_SCH311x : \ 249#define IN_NOMINAL(type) ((type) == sch311x ? IN_NOMINAL_SCH311x : \
228 (type) == sch5027 ? IN_NOMINAL_SCH5027 : \ 250 (type) == sch5027 ? IN_NOMINAL_SCH5027 : \
251 (type) == sch5127 ? IN_NOMINAL_SCH5127 : \
229 IN_NOMINAL_DME1737) 252 IN_NOMINAL_DME1737)
230 253
231/* Voltage input 254/* Voltage input
@@ -568,7 +591,7 @@ static struct dme1737_data *dme1737_update_device(struct device *dev)
568 591
569 /* Sample register contents every 1 sec */ 592 /* Sample register contents every 1 sec */
570 if (time_after(jiffies, data->last_update + HZ) || !data->valid) { 593 if (time_after(jiffies, data->last_update + HZ) || !data->valid) {
571 if (data->type == dme1737) { 594 if (data->has_features & HAS_VID) {
572 data->vid = dme1737_read(data, DME1737_REG_VID) & 595 data->vid = dme1737_read(data, DME1737_REG_VID) &
573 0x3f; 596 0x3f;
574 } 597 }
@@ -599,7 +622,7 @@ static struct dme1737_data *dme1737_update_device(struct device *dev)
599 DME1737_REG_TEMP_MIN(ix)); 622 DME1737_REG_TEMP_MIN(ix));
600 data->temp_max[ix] = dme1737_read(data, 623 data->temp_max[ix] = dme1737_read(data,
601 DME1737_REG_TEMP_MAX(ix)); 624 DME1737_REG_TEMP_MAX(ix));
602 if (data->type != sch5027) { 625 if (data->has_features & HAS_TEMP_OFFSET) {
603 data->temp_offset[ix] = dme1737_read(data, 626 data->temp_offset[ix] = dme1737_read(data,
604 DME1737_REG_TEMP_OFFSET(ix)); 627 DME1737_REG_TEMP_OFFSET(ix));
605 } 628 }
@@ -626,7 +649,7 @@ static struct dme1737_data *dme1737_update_device(struct device *dev)
626 for (ix = 0; ix < ARRAY_SIZE(data->fan); ix++) { 649 for (ix = 0; ix < ARRAY_SIZE(data->fan); ix++) {
627 /* Skip reading registers if optional fans are not 650 /* Skip reading registers if optional fans are not
628 * present */ 651 * present */
629 if (!(data->has_fan & (1 << ix))) { 652 if (!(data->has_features & HAS_FAN(ix))) {
630 continue; 653 continue;
631 } 654 }
632 data->fan[ix] = dme1737_read(data, 655 data->fan[ix] = dme1737_read(data,
@@ -650,7 +673,7 @@ static struct dme1737_data *dme1737_update_device(struct device *dev)
650 for (ix = 0; ix < ARRAY_SIZE(data->pwm); ix++) { 673 for (ix = 0; ix < ARRAY_SIZE(data->pwm); ix++) {
651 /* Skip reading registers if optional PWMs are not 674 /* Skip reading registers if optional PWMs are not
652 * present */ 675 * present */
653 if (!(data->has_pwm & (1 << ix))) { 676 if (!(data->has_features & HAS_PWM(ix))) {
654 continue; 677 continue;
655 } 678 }
656 data->pwm[ix] = dme1737_read(data, 679 data->pwm[ix] = dme1737_read(data,
@@ -672,12 +695,24 @@ static struct dme1737_data *dme1737_update_device(struct device *dev)
672 695
673 /* Thermal zone registers */ 696 /* Thermal zone registers */
674 for (ix = 0; ix < ARRAY_SIZE(data->zone_low); ix++) { 697 for (ix = 0; ix < ARRAY_SIZE(data->zone_low); ix++) {
675 data->zone_low[ix] = dme1737_read(data, 698 /* Skip reading registers if zone3 is not present */
676 DME1737_REG_ZONE_LOW(ix)); 699 if ((ix == 2) && !(data->has_features & HAS_ZONE3)) {
677 data->zone_abs[ix] = dme1737_read(data, 700 continue;
678 DME1737_REG_ZONE_ABS(ix)); 701 }
702 /* sch5127 zone2 registers are special */
703 if ((ix == 1) && (data->type == sch5127)) {
704 data->zone_low[1] = dme1737_read(data,
705 DME1737_REG_ZONE_LOW(2));
706 data->zone_abs[1] = dme1737_read(data,
707 DME1737_REG_ZONE_ABS(2));
708 } else {
709 data->zone_low[ix] = dme1737_read(data,
710 DME1737_REG_ZONE_LOW(ix));
711 data->zone_abs[ix] = dme1737_read(data,
712 DME1737_REG_ZONE_ABS(ix));
713 }
679 } 714 }
680 if (data->type != sch5027) { 715 if (data->has_features & HAS_ZONE_HYST) {
681 for (ix = 0; ix < ARRAY_SIZE(data->zone_hyst); ix++) { 716 for (ix = 0; ix < ARRAY_SIZE(data->zone_hyst); ix++) {
682 data->zone_hyst[ix] = dme1737_read(data, 717 data->zone_hyst[ix] = dme1737_read(data,
683 DME1737_REG_ZONE_HYST(ix)); 718 DME1737_REG_ZONE_HYST(ix));
@@ -1594,10 +1629,6 @@ static struct attribute *dme1737_attr[] ={
1594 &sensor_dev_attr_zone2_auto_point2_temp.dev_attr.attr, 1629 &sensor_dev_attr_zone2_auto_point2_temp.dev_attr.attr,
1595 &sensor_dev_attr_zone2_auto_point3_temp.dev_attr.attr, 1630 &sensor_dev_attr_zone2_auto_point3_temp.dev_attr.attr,
1596 &sensor_dev_attr_zone2_auto_channels_temp.dev_attr.attr, 1631 &sensor_dev_attr_zone2_auto_channels_temp.dev_attr.attr,
1597 &sensor_dev_attr_zone3_auto_point1_temp.dev_attr.attr,
1598 &sensor_dev_attr_zone3_auto_point2_temp.dev_attr.attr,
1599 &sensor_dev_attr_zone3_auto_point3_temp.dev_attr.attr,
1600 &sensor_dev_attr_zone3_auto_channels_temp.dev_attr.attr,
1601 NULL 1632 NULL
1602}; 1633};
1603 1634
@@ -1605,27 +1636,23 @@ static const struct attribute_group dme1737_group = {
1605 .attrs = dme1737_attr, 1636 .attrs = dme1737_attr,
1606}; 1637};
1607 1638
1608/* The following struct holds misc attributes, which are not available in all 1639/* The following struct holds temp offset attributes, which are not available
1609 * chips. Their creation depends on the chip type which is determined during 1640 * in all chips. The following chips support them:
1610 * module load. */ 1641 * DME1737, SCH311x */
1611static struct attribute *dme1737_misc_attr[] = { 1642static struct attribute *dme1737_temp_offset_attr[] = {
1612 /* Temperatures */
1613 &sensor_dev_attr_temp1_offset.dev_attr.attr, 1643 &sensor_dev_attr_temp1_offset.dev_attr.attr,
1614 &sensor_dev_attr_temp2_offset.dev_attr.attr, 1644 &sensor_dev_attr_temp2_offset.dev_attr.attr,
1615 &sensor_dev_attr_temp3_offset.dev_attr.attr, 1645 &sensor_dev_attr_temp3_offset.dev_attr.attr,
1616 /* Zones */
1617 &sensor_dev_attr_zone1_auto_point1_temp_hyst.dev_attr.attr,
1618 &sensor_dev_attr_zone2_auto_point1_temp_hyst.dev_attr.attr,
1619 &sensor_dev_attr_zone3_auto_point1_temp_hyst.dev_attr.attr,
1620 NULL 1646 NULL
1621}; 1647};
1622 1648
1623static const struct attribute_group dme1737_misc_group = { 1649static const struct attribute_group dme1737_temp_offset_group = {
1624 .attrs = dme1737_misc_attr, 1650 .attrs = dme1737_temp_offset_attr,
1625}; 1651};
1626 1652
1627/* The following struct holds VID-related attributes. Their creation 1653/* The following struct holds VID related attributes, which are not available
1628 depends on the chip type which is determined during module load. */ 1654 * in all chips. The following chips support them:
1655 * DME1737 */
1629static struct attribute *dme1737_vid_attr[] = { 1656static struct attribute *dme1737_vid_attr[] = {
1630 &dev_attr_vrm.attr, 1657 &dev_attr_vrm.attr,
1631 &dev_attr_cpu0_vid.attr, 1658 &dev_attr_cpu0_vid.attr,
@@ -1636,6 +1663,36 @@ static const struct attribute_group dme1737_vid_group = {
1636 .attrs = dme1737_vid_attr, 1663 .attrs = dme1737_vid_attr,
1637}; 1664};
1638 1665
1666/* The following struct holds temp zone 3 related attributes, which are not
1667 * available in all chips. The following chips support them:
1668 * DME1737, SCH311x, SCH5027 */
1669static struct attribute *dme1737_zone3_attr[] = {
1670 &sensor_dev_attr_zone3_auto_point1_temp.dev_attr.attr,
1671 &sensor_dev_attr_zone3_auto_point2_temp.dev_attr.attr,
1672 &sensor_dev_attr_zone3_auto_point3_temp.dev_attr.attr,
1673 &sensor_dev_attr_zone3_auto_channels_temp.dev_attr.attr,
1674 NULL
1675};
1676
1677static const struct attribute_group dme1737_zone3_group = {
1678 .attrs = dme1737_zone3_attr,
1679};
1680
1681
1682/* The following struct holds temp zone hysteresis related attributes, which
1683 * are not available in all chips. The following chips support them:
1684 * DME1737, SCH311x */
1685static struct attribute *dme1737_zone_hyst_attr[] = {
1686 &sensor_dev_attr_zone1_auto_point1_temp_hyst.dev_attr.attr,
1687 &sensor_dev_attr_zone2_auto_point1_temp_hyst.dev_attr.attr,
1688 &sensor_dev_attr_zone3_auto_point1_temp_hyst.dev_attr.attr,
1689 NULL
1690};
1691
1692static const struct attribute_group dme1737_zone_hyst_group = {
1693 .attrs = dme1737_zone_hyst_attr,
1694};
1695
1639/* The following structs hold the PWM attributes, some of which are optional. 1696/* The following structs hold the PWM attributes, some of which are optional.
1640 * Their creation depends on the chip configuration which is determined during 1697 * Their creation depends on the chip configuration which is determined during
1641 * module load. */ 1698 * module load. */
@@ -1691,10 +1748,10 @@ static const struct attribute_group dme1737_pwm_group[] = {
1691 { .attrs = dme1737_pwm6_attr }, 1748 { .attrs = dme1737_pwm6_attr },
1692}; 1749};
1693 1750
1694/* The following struct holds misc PWM attributes, which are not available in 1751/* The following struct holds auto PWM min attributes, which are not available
1695 * all chips. Their creation depends on the chip type which is determined 1752 * in all chips. Their creation depends on the chip type which is determined
1696 * during module load. */ 1753 * during module load. */
1697static struct attribute *dme1737_pwm_misc_attr[] = { 1754static struct attribute *dme1737_auto_pwm_min_attr[] = {
1698 &sensor_dev_attr_pwm1_auto_pwm_min.dev_attr.attr, 1755 &sensor_dev_attr_pwm1_auto_pwm_min.dev_attr.attr,
1699 &sensor_dev_attr_pwm2_auto_pwm_min.dev_attr.attr, 1756 &sensor_dev_attr_pwm2_auto_pwm_min.dev_attr.attr,
1700 &sensor_dev_attr_pwm3_auto_pwm_min.dev_attr.attr, 1757 &sensor_dev_attr_pwm3_auto_pwm_min.dev_attr.attr,
@@ -1764,14 +1821,25 @@ static struct attribute *dme1737_zone_chmod_attr[] = {
1764 &sensor_dev_attr_zone2_auto_point1_temp.dev_attr.attr, 1821 &sensor_dev_attr_zone2_auto_point1_temp.dev_attr.attr,
1765 &sensor_dev_attr_zone2_auto_point2_temp.dev_attr.attr, 1822 &sensor_dev_attr_zone2_auto_point2_temp.dev_attr.attr,
1766 &sensor_dev_attr_zone2_auto_point3_temp.dev_attr.attr, 1823 &sensor_dev_attr_zone2_auto_point3_temp.dev_attr.attr,
1824 NULL
1825};
1826
1827static const struct attribute_group dme1737_zone_chmod_group = {
1828 .attrs = dme1737_zone_chmod_attr,
1829};
1830
1831
1832/* The permissions of the following zone 3 attributes are changed to read-
1833 * writeable if the chip is *not* locked. Otherwise they stay read-only. */
1834static struct attribute *dme1737_zone3_chmod_attr[] = {
1767 &sensor_dev_attr_zone3_auto_point1_temp.dev_attr.attr, 1835 &sensor_dev_attr_zone3_auto_point1_temp.dev_attr.attr,
1768 &sensor_dev_attr_zone3_auto_point2_temp.dev_attr.attr, 1836 &sensor_dev_attr_zone3_auto_point2_temp.dev_attr.attr,
1769 &sensor_dev_attr_zone3_auto_point3_temp.dev_attr.attr, 1837 &sensor_dev_attr_zone3_auto_point3_temp.dev_attr.attr,
1770 NULL 1838 NULL
1771}; 1839};
1772 1840
1773static const struct attribute_group dme1737_zone_chmod_group = { 1841static const struct attribute_group dme1737_zone3_chmod_group = {
1774 .attrs = dme1737_zone_chmod_attr, 1842 .attrs = dme1737_zone3_chmod_attr,
1775}; 1843};
1776 1844
1777/* The permissions of the following PWM attributes are changed to read- 1845/* The permissions of the following PWM attributes are changed to read-
@@ -1887,30 +1955,35 @@ static void dme1737_remove_files(struct device *dev)
1887 int ix; 1955 int ix;
1888 1956
1889 for (ix = 0; ix < ARRAY_SIZE(dme1737_fan_group); ix++) { 1957 for (ix = 0; ix < ARRAY_SIZE(dme1737_fan_group); ix++) {
1890 if (data->has_fan & (1 << ix)) { 1958 if (data->has_features & HAS_FAN(ix)) {
1891 sysfs_remove_group(&dev->kobj, 1959 sysfs_remove_group(&dev->kobj,
1892 &dme1737_fan_group[ix]); 1960 &dme1737_fan_group[ix]);
1893 } 1961 }
1894 } 1962 }
1895 1963
1896 for (ix = 0; ix < ARRAY_SIZE(dme1737_pwm_group); ix++) { 1964 for (ix = 0; ix < ARRAY_SIZE(dme1737_pwm_group); ix++) {
1897 if (data->has_pwm & (1 << ix)) { 1965 if (data->has_features & HAS_PWM(ix)) {
1898 sysfs_remove_group(&dev->kobj, 1966 sysfs_remove_group(&dev->kobj,
1899 &dme1737_pwm_group[ix]); 1967 &dme1737_pwm_group[ix]);
1900 if (data->type != sch5027 && ix < 3) { 1968 if ((data->has_features & HAS_PWM_MIN) && ix < 3) {
1901 sysfs_remove_file(&dev->kobj, 1969 sysfs_remove_file(&dev->kobj,
1902 dme1737_pwm_misc_attr[ix]); 1970 dme1737_auto_pwm_min_attr[ix]);
1903 } 1971 }
1904 } 1972 }
1905 } 1973 }
1906 1974
1907 if (data->type != sch5027) { 1975 if (data->has_features & HAS_TEMP_OFFSET) {
1908 sysfs_remove_group(&dev->kobj, &dme1737_misc_group); 1976 sysfs_remove_group(&dev->kobj, &dme1737_temp_offset_group);
1909 } 1977 }
1910 if (data->type == dme1737) { 1978 if (data->has_features & HAS_VID) {
1911 sysfs_remove_group(&dev->kobj, &dme1737_vid_group); 1979 sysfs_remove_group(&dev->kobj, &dme1737_vid_group);
1912 } 1980 }
1913 1981 if (data->has_features & HAS_ZONE3) {
1982 sysfs_remove_group(&dev->kobj, &dme1737_zone3_group);
1983 }
1984 if (data->has_features & HAS_ZONE_HYST) {
1985 sysfs_remove_group(&dev->kobj, &dme1737_zone_hyst_group);
1986 }
1914 sysfs_remove_group(&dev->kobj, &dme1737_group); 1987 sysfs_remove_group(&dev->kobj, &dme1737_group);
1915 1988
1916 if (!data->client) { 1989 if (!data->client) {
@@ -1934,23 +2007,31 @@ static int dme1737_create_files(struct device *dev)
1934 goto exit_remove; 2007 goto exit_remove;
1935 } 2008 }
1936 2009
1937 /* Create misc sysfs attributes */ 2010 /* Create chip-dependent sysfs attributes */
1938 if ((data->type != sch5027) && 2011 if ((data->has_features & HAS_TEMP_OFFSET) &&
1939 (err = sysfs_create_group(&dev->kobj, 2012 (err = sysfs_create_group(&dev->kobj,
1940 &dme1737_misc_group))) { 2013 &dme1737_temp_offset_group))) {
1941 goto exit_remove; 2014 goto exit_remove;
1942 } 2015 }
1943 2016 if ((data->has_features & HAS_VID) &&
1944 /* Create VID-related sysfs attributes */
1945 if ((data->type == dme1737) &&
1946 (err = sysfs_create_group(&dev->kobj, 2017 (err = sysfs_create_group(&dev->kobj,
1947 &dme1737_vid_group))) { 2018 &dme1737_vid_group))) {
1948 goto exit_remove; 2019 goto exit_remove;
1949 } 2020 }
2021 if ((data->has_features & HAS_ZONE3) &&
2022 (err = sysfs_create_group(&dev->kobj,
2023 &dme1737_zone3_group))) {
2024 goto exit_remove;
2025 }
2026 if ((data->has_features & HAS_ZONE_HYST) &&
2027 (err = sysfs_create_group(&dev->kobj,
2028 &dme1737_zone_hyst_group))) {
2029 goto exit_remove;
2030 }
1950 2031
1951 /* Create fan sysfs attributes */ 2032 /* Create fan sysfs attributes */
1952 for (ix = 0; ix < ARRAY_SIZE(dme1737_fan_group); ix++) { 2033 for (ix = 0; ix < ARRAY_SIZE(dme1737_fan_group); ix++) {
1953 if (data->has_fan & (1 << ix)) { 2034 if (data->has_features & HAS_FAN(ix)) {
1954 if ((err = sysfs_create_group(&dev->kobj, 2035 if ((err = sysfs_create_group(&dev->kobj,
1955 &dme1737_fan_group[ix]))) { 2036 &dme1737_fan_group[ix]))) {
1956 goto exit_remove; 2037 goto exit_remove;
@@ -1960,14 +2041,14 @@ static int dme1737_create_files(struct device *dev)
1960 2041
1961 /* Create PWM sysfs attributes */ 2042 /* Create PWM sysfs attributes */
1962 for (ix = 0; ix < ARRAY_SIZE(dme1737_pwm_group); ix++) { 2043 for (ix = 0; ix < ARRAY_SIZE(dme1737_pwm_group); ix++) {
1963 if (data->has_pwm & (1 << ix)) { 2044 if (data->has_features & HAS_PWM(ix)) {
1964 if ((err = sysfs_create_group(&dev->kobj, 2045 if ((err = sysfs_create_group(&dev->kobj,
1965 &dme1737_pwm_group[ix]))) { 2046 &dme1737_pwm_group[ix]))) {
1966 goto exit_remove; 2047 goto exit_remove;
1967 } 2048 }
1968 if (data->type != sch5027 && ix < 3 && 2049 if ((data->has_features & HAS_PWM_MIN) && ix < 3 &&
1969 (err = sysfs_create_file(&dev->kobj, 2050 (err = sysfs_create_file(&dev->kobj,
1970 dme1737_pwm_misc_attr[ix]))) { 2051 dme1737_auto_pwm_min_attr[ix]))) {
1971 goto exit_remove; 2052 goto exit_remove;
1972 } 2053 }
1973 } 2054 }
@@ -1983,21 +2064,30 @@ static int dme1737_create_files(struct device *dev)
1983 dme1737_chmod_group(dev, &dme1737_zone_chmod_group, 2064 dme1737_chmod_group(dev, &dme1737_zone_chmod_group,
1984 S_IRUGO | S_IWUSR); 2065 S_IRUGO | S_IWUSR);
1985 2066
1986 /* Change permissions of misc sysfs attributes */ 2067 /* Change permissions of chip-dependent sysfs attributes */
1987 if (data->type != sch5027) { 2068 if (data->has_features & HAS_TEMP_OFFSET) {
1988 dme1737_chmod_group(dev, &dme1737_misc_group, 2069 dme1737_chmod_group(dev, &dme1737_temp_offset_group,
2070 S_IRUGO | S_IWUSR);
2071 }
2072 if (data->has_features & HAS_ZONE3) {
2073 dme1737_chmod_group(dev, &dme1737_zone3_chmod_group,
2074 S_IRUGO | S_IWUSR);
2075 }
2076 if (data->has_features & HAS_ZONE_HYST) {
2077 dme1737_chmod_group(dev, &dme1737_zone_hyst_group,
1989 S_IRUGO | S_IWUSR); 2078 S_IRUGO | S_IWUSR);
1990 } 2079 }
1991 2080
1992 /* Change permissions of PWM sysfs attributes */ 2081 /* Change permissions of PWM sysfs attributes */
1993 for (ix = 0; ix < ARRAY_SIZE(dme1737_pwm_chmod_group); ix++) { 2082 for (ix = 0; ix < ARRAY_SIZE(dme1737_pwm_chmod_group); ix++) {
1994 if (data->has_pwm & (1 << ix)) { 2083 if (data->has_features & HAS_PWM(ix)) {
1995 dme1737_chmod_group(dev, 2084 dme1737_chmod_group(dev,
1996 &dme1737_pwm_chmod_group[ix], 2085 &dme1737_pwm_chmod_group[ix],
1997 S_IRUGO | S_IWUSR); 2086 S_IRUGO | S_IWUSR);
1998 if (data->type != sch5027 && ix < 3) { 2087 if ((data->has_features & HAS_PWM_MIN) &&
2088 ix < 3) {
1999 dme1737_chmod_file(dev, 2089 dme1737_chmod_file(dev,
2000 dme1737_pwm_misc_attr[ix], 2090 dme1737_auto_pwm_min_attr[ix],
2001 S_IRUGO | S_IWUSR); 2091 S_IRUGO | S_IWUSR);
2002 } 2092 }
2003 } 2093 }
@@ -2005,7 +2095,7 @@ static int dme1737_create_files(struct device *dev)
2005 2095
2006 /* Change permissions of pwm[1-3] if in manual mode */ 2096 /* Change permissions of pwm[1-3] if in manual mode */
2007 for (ix = 0; ix < 3; ix++) { 2097 for (ix = 0; ix < 3; ix++) {
2008 if ((data->has_pwm & (1 << ix)) && 2098 if ((data->has_features & HAS_PWM(ix)) &&
2009 (PWM_EN_FROM_REG(data->pwm_config[ix]) == 1)) { 2099 (PWM_EN_FROM_REG(data->pwm_config[ix]) == 1)) {
2010 dme1737_chmod_file(dev, 2100 dme1737_chmod_file(dev,
2011 dme1737_pwm_chmod_attr[ix], 2101 dme1737_pwm_chmod_attr[ix],
@@ -2052,20 +2142,20 @@ static int dme1737_init_device(struct device *dev)
2052 return -EFAULT; 2142 return -EFAULT;
2053 } 2143 }
2054 2144
2055 /* Determine which optional fan and pwm features are enabled/present */ 2145 /* Determine which optional fan and pwm features are enabled (only
2146 * valid for I2C devices) */
2056 if (client) { /* I2C chip */ 2147 if (client) { /* I2C chip */
2057 data->config2 = dme1737_read(data, DME1737_REG_CONFIG2); 2148 data->config2 = dme1737_read(data, DME1737_REG_CONFIG2);
2058 /* Check if optional fan3 input is enabled */ 2149 /* Check if optional fan3 input is enabled */
2059 if (data->config2 & 0x04) { 2150 if (data->config2 & 0x04) {
2060 data->has_fan |= (1 << 2); 2151 data->has_features |= HAS_FAN(2);
2061 } 2152 }
2062 2153
2063 /* Fan4 and pwm3 are only available if the client's I2C address 2154 /* Fan4 and pwm3 are only available if the client's I2C address
2064 * is the default 0x2e. Otherwise the I/Os associated with 2155 * is the default 0x2e. Otherwise the I/Os associated with
2065 * these functions are used for addr enable/select. */ 2156 * these functions are used for addr enable/select. */
2066 if (client->addr == 0x2e) { 2157 if (client->addr == 0x2e) {
2067 data->has_fan |= (1 << 3); 2158 data->has_features |= HAS_FAN(3) | HAS_PWM(2);
2068 data->has_pwm |= (1 << 2);
2069 } 2159 }
2070 2160
2071 /* Determine which of the optional fan[5-6] and pwm[5-6] 2161 /* Determine which of the optional fan[5-6] and pwm[5-6]
@@ -2077,26 +2167,40 @@ static int dme1737_init_device(struct device *dev)
2077 dev_warn(dev, "Failed to query Super-IO for optional " 2167 dev_warn(dev, "Failed to query Super-IO for optional "
2078 "features.\n"); 2168 "features.\n");
2079 } 2169 }
2080 } else { /* ISA chip */
2081 /* Fan3 and pwm3 are always available. Fan[4-5] and pwm[5-6]
2082 * don't exist in the ISA chip. */
2083 data->has_fan |= (1 << 2);
2084 data->has_pwm |= (1 << 2);
2085 } 2170 }
2086 2171
2087 /* Fan1, fan2, pwm1, and pwm2 are always present */ 2172 /* Fan[1-2] and pwm[1-2] are present in all chips */
2088 data->has_fan |= 0x03; 2173 data->has_features |= HAS_FAN(0) | HAS_FAN(1) | HAS_PWM(0) | HAS_PWM(1);
2089 data->has_pwm |= 0x03; 2174
2175 /* Chip-dependent features */
2176 switch (data->type) {
2177 case dme1737:
2178 data->has_features |= HAS_TEMP_OFFSET | HAS_VID | HAS_ZONE3 |
2179 HAS_ZONE_HYST | HAS_PWM_MIN;
2180 break;
2181 case sch311x:
2182 data->has_features |= HAS_TEMP_OFFSET | HAS_ZONE3 |
2183 HAS_ZONE_HYST | HAS_PWM_MIN | HAS_FAN(2) | HAS_PWM(2);
2184 break;
2185 case sch5027:
2186 data->has_features |= HAS_ZONE3;
2187 break;
2188 case sch5127:
2189 data->has_features |= HAS_FAN(2) | HAS_PWM(2);
2190 break;
2191 default:
2192 break;
2193 }
2090 2194
2091 dev_info(dev, "Optional features: pwm3=%s, pwm5=%s, pwm6=%s, " 2195 dev_info(dev, "Optional features: pwm3=%s, pwm5=%s, pwm6=%s, "
2092 "fan3=%s, fan4=%s, fan5=%s, fan6=%s.\n", 2196 "fan3=%s, fan4=%s, fan5=%s, fan6=%s.\n",
2093 (data->has_pwm & (1 << 2)) ? "yes" : "no", 2197 (data->has_features & HAS_PWM(2)) ? "yes" : "no",
2094 (data->has_pwm & (1 << 4)) ? "yes" : "no", 2198 (data->has_features & HAS_PWM(4)) ? "yes" : "no",
2095 (data->has_pwm & (1 << 5)) ? "yes" : "no", 2199 (data->has_features & HAS_PWM(5)) ? "yes" : "no",
2096 (data->has_fan & (1 << 2)) ? "yes" : "no", 2200 (data->has_features & HAS_FAN(2)) ? "yes" : "no",
2097 (data->has_fan & (1 << 3)) ? "yes" : "no", 2201 (data->has_features & HAS_FAN(3)) ? "yes" : "no",
2098 (data->has_fan & (1 << 4)) ? "yes" : "no", 2202 (data->has_features & HAS_FAN(4)) ? "yes" : "no",
2099 (data->has_fan & (1 << 5)) ? "yes" : "no"); 2203 (data->has_features & HAS_FAN(5)) ? "yes" : "no");
2100 2204
2101 reg = dme1737_read(data, DME1737_REG_TACH_PWM); 2205 reg = dme1737_read(data, DME1737_REG_TACH_PWM);
2102 /* Inform if fan-to-pwm mapping differs from the default */ 2206 /* Inform if fan-to-pwm mapping differs from the default */
@@ -2122,7 +2226,7 @@ static int dme1737_init_device(struct device *dev)
2122 for (ix = 0; ix < 3; ix++) { 2226 for (ix = 0; ix < 3; ix++) {
2123 data->pwm_config[ix] = dme1737_read(data, 2227 data->pwm_config[ix] = dme1737_read(data,
2124 DME1737_REG_PWM_CONFIG(ix)); 2228 DME1737_REG_PWM_CONFIG(ix));
2125 if ((data->has_pwm & (1 << ix)) && 2229 if ((data->has_features & HAS_PWM(ix)) &&
2126 (PWM_EN_FROM_REG(data->pwm_config[ix]) == -1)) { 2230 (PWM_EN_FROM_REG(data->pwm_config[ix]) == -1)) {
2127 dev_info(dev, "Switching pwm%d to " 2231 dev_info(dev, "Switching pwm%d to "
2128 "manual mode.\n", ix + 1); 2232 "manual mode.\n", ix + 1);
@@ -2142,7 +2246,7 @@ static int dme1737_init_device(struct device *dev)
2142 data->pwm_acz[2] = 4; /* pwm3 -> zone3 */ 2246 data->pwm_acz[2] = 4; /* pwm3 -> zone3 */
2143 2247
2144 /* Set VRM */ 2248 /* Set VRM */
2145 if (data->type == dme1737) { 2249 if (data->has_features & HAS_VID) {
2146 data->vrm = vid_which_vrm(); 2250 data->vrm = vid_which_vrm();
2147 } 2251 }
2148 2252
@@ -2163,10 +2267,10 @@ static int dme1737_i2c_get_features(int sio_cip, struct dme1737_data *data)
2163 dme1737_sio_enter(sio_cip); 2267 dme1737_sio_enter(sio_cip);
2164 2268
2165 /* Check device ID 2269 /* Check device ID
2166 * The DME1737 can return either 0x78 or 0x77 as its device ID. 2270 * We currently know about two kinds of DME1737 and SCH5027. */
2167 * The SCH5027 returns 0x89 as its device ID. */
2168 reg = force_id ? force_id : dme1737_sio_inb(sio_cip, 0x20); 2271 reg = force_id ? force_id : dme1737_sio_inb(sio_cip, 0x20);
2169 if (!(reg == 0x77 || reg == 0x78 || reg == 0x89)) { 2272 if (!(reg == DME1737_ID_1 || reg == DME1737_ID_2 ||
2273 reg == SCH5027_ID)) {
2170 err = -ENODEV; 2274 err = -ENODEV;
2171 goto exit; 2275 goto exit;
2172 } 2276 }
@@ -2185,16 +2289,16 @@ static int dme1737_i2c_get_features(int sio_cip, struct dme1737_data *data)
2185 * are enabled and available. Bits [3:2] of registers 0x43-0x46 are set 2289 * are enabled and available. Bits [3:2] of registers 0x43-0x46 are set
2186 * to '10' if the respective feature is enabled. */ 2290 * to '10' if the respective feature is enabled. */
2187 if ((inb(addr + 0x43) & 0x0c) == 0x08) { /* fan6 */ 2291 if ((inb(addr + 0x43) & 0x0c) == 0x08) { /* fan6 */
2188 data->has_fan |= (1 << 5); 2292 data->has_features |= HAS_FAN(5);
2189 } 2293 }
2190 if ((inb(addr + 0x44) & 0x0c) == 0x08) { /* pwm6 */ 2294 if ((inb(addr + 0x44) & 0x0c) == 0x08) { /* pwm6 */
2191 data->has_pwm |= (1 << 5); 2295 data->has_features |= HAS_PWM(5);
2192 } 2296 }
2193 if ((inb(addr + 0x45) & 0x0c) == 0x08) { /* fan5 */ 2297 if ((inb(addr + 0x45) & 0x0c) == 0x08) { /* fan5 */
2194 data->has_fan |= (1 << 4); 2298 data->has_features |= HAS_FAN(4);
2195 } 2299 }
2196 if ((inb(addr + 0x46) & 0x0c) == 0x08) { /* pwm5 */ 2300 if ((inb(addr + 0x46) & 0x0c) == 0x08) { /* pwm5 */
2197 data->has_pwm |= (1 << 4); 2301 data->has_features |= HAS_PWM(4);
2198 } 2302 }
2199 2303
2200exit: 2304exit:
@@ -2222,7 +2326,6 @@ static int dme1737_i2c_detect(struct i2c_client *client,
2222 if (company == DME1737_COMPANY_SMSC && 2326 if (company == DME1737_COMPANY_SMSC &&
2223 verstep == SCH5027_VERSTEP) { 2327 verstep == SCH5027_VERSTEP) {
2224 name = "sch5027"; 2328 name = "sch5027";
2225
2226 } else if (company == DME1737_COMPANY_SMSC && 2329 } else if (company == DME1737_COMPANY_SMSC &&
2227 (verstep & DME1737_VERSTEP_MASK) == DME1737_VERSTEP) { 2330 (verstep & DME1737_VERSTEP_MASK) == DME1737_VERSTEP) {
2228 name = "dme1737"; 2331 name = "dme1737";
@@ -2329,10 +2432,10 @@ static int __init dme1737_isa_detect(int sio_cip, unsigned short *addr)
2329 dme1737_sio_enter(sio_cip); 2432 dme1737_sio_enter(sio_cip);
2330 2433
2331 /* Check device ID 2434 /* Check device ID
2332 * We currently know about SCH3112 (0x7c), SCH3114 (0x7d), and 2435 * We currently know about SCH3112, SCH3114, SCH3116, and SCH5127 */
2333 * SCH3116 (0x7f). */
2334 reg = force_id ? force_id : dme1737_sio_inb(sio_cip, 0x20); 2436 reg = force_id ? force_id : dme1737_sio_inb(sio_cip, 0x20);
2335 if (!(reg == 0x7c || reg == 0x7d || reg == 0x7f)) { 2437 if (!(reg == SCH3112_ID || reg == SCH3114_ID || reg == SCH3116_ID ||
2438 reg == SCH5127_ID)) {
2336 err = -ENODEV; 2439 err = -ENODEV;
2337 goto exit; 2440 goto exit;
2338 } 2441 }
@@ -2424,23 +2527,42 @@ static int __devinit dme1737_isa_probe(struct platform_device *pdev)
2424 platform_set_drvdata(pdev, data); 2527 platform_set_drvdata(pdev, data);
2425 2528
2426 /* Skip chip detection if module is loaded with force_id parameter */ 2529 /* Skip chip detection if module is loaded with force_id parameter */
2427 if (!force_id) { 2530 switch (force_id) {
2531 case SCH3112_ID:
2532 case SCH3114_ID:
2533 case SCH3116_ID:
2534 data->type = sch311x;
2535 break;
2536 case SCH5127_ID:
2537 data->type = sch5127;
2538 break;
2539 default:
2428 company = dme1737_read(data, DME1737_REG_COMPANY); 2540 company = dme1737_read(data, DME1737_REG_COMPANY);
2429 device = dme1737_read(data, DME1737_REG_DEVICE); 2541 device = dme1737_read(data, DME1737_REG_DEVICE);
2430 2542
2431 if (!((company == DME1737_COMPANY_SMSC) && 2543 if ((company == DME1737_COMPANY_SMSC) &&
2432 (device == SCH311X_DEVICE))) { 2544 (device == SCH311X_DEVICE)) {
2545 data->type = sch311x;
2546 } else if ((company == DME1737_COMPANY_SMSC) &&
2547 (device == SCH5127_DEVICE)) {
2548 data->type = sch5127;
2549 } else {
2433 err = -ENODEV; 2550 err = -ENODEV;
2434 goto exit_kfree; 2551 goto exit_kfree;
2435 } 2552 }
2436 } 2553 }
2437 data->type = sch311x;
2438 2554
2439 /* Fill in the remaining client fields and initialize the mutex */ 2555 if (data->type == sch5127) {
2440 data->name = "sch311x"; 2556 data->name = "sch5127";
2557 } else {
2558 data->name = "sch311x";
2559 }
2560
2561 /* Initialize the mutex */
2441 mutex_init(&data->update_lock); 2562 mutex_init(&data->update_lock);
2442 2563
2443 dev_info(dev, "Found a SCH311x chip at 0x%04x\n", data->addr); 2564 dev_info(dev, "Found a %s chip at 0x%04x\n",
2565 data->type == sch5127 ? "SCH5127" : "SCH311x", data->addr);
2444 2566
2445 /* Initialize the chip */ 2567 /* Initialize the chip */
2446 if ((err = dme1737_init_device(dev))) { 2568 if ((err = dme1737_init_device(dev))) {
diff --git a/drivers/hwmon/emc1403.c b/drivers/hwmon/emc1403.c
new file mode 100644
index 000000000000..0e4b5642638d
--- /dev/null
+++ b/drivers/hwmon/emc1403.c
@@ -0,0 +1,344 @@
1/*
2 * emc1403.c - SMSC Thermal Driver
3 *
4 * Copyright (C) 2008 Intel Corp
5 *
6 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
20 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
21 *
22 * TODO
23 * - cache alarm and critical limit registers
24 * - add emc1404 support
25 */
26
27#include <linux/module.h>
28#include <linux/init.h>
29#include <linux/slab.h>
30#include <linux/i2c.h>
31#include <linux/hwmon.h>
32#include <linux/hwmon-sysfs.h>
33#include <linux/err.h>
34#include <linux/sysfs.h>
35#include <linux/mutex.h>
36
37#define THERMAL_PID_REG 0xfd
38#define THERMAL_SMSC_ID_REG 0xfe
39#define THERMAL_REVISION_REG 0xff
40
41struct thermal_data {
42 struct device *hwmon_dev;
43 struct mutex mutex;
44 /* Cache the hyst value so we don't keep re-reading it. In theory
45 we could cache it forever as nobody else should be writing it. */
46 u8 cached_hyst;
47 unsigned long hyst_valid;
48};
49
50static ssize_t show_temp(struct device *dev,
51 struct device_attribute *attr, char *buf)
52{
53 struct i2c_client *client = to_i2c_client(dev);
54 struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
55 int retval = i2c_smbus_read_byte_data(client, sda->index);
56
57 if (retval < 0)
58 return retval;
59 return sprintf(buf, "%d000\n", retval);
60}
61
62static ssize_t show_bit(struct device *dev,
63 struct device_attribute *attr, char *buf)
64{
65 struct i2c_client *client = to_i2c_client(dev);
66 struct sensor_device_attribute_2 *sda = to_sensor_dev_attr_2(attr);
67 int retval = i2c_smbus_read_byte_data(client, sda->nr);
68
69 if (retval < 0)
70 return retval;
71 retval &= sda->index;
72 return sprintf(buf, "%d\n", retval ? 1 : 0);
73}
74
75static ssize_t store_temp(struct device *dev,
76 struct device_attribute *attr, const char *buf, size_t count)
77{
78 struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
79 struct i2c_client *client = to_i2c_client(dev);
80 unsigned long val;
81 int retval;
82
83 if (strict_strtoul(buf, 10, &val))
84 return -EINVAL;
85 retval = i2c_smbus_write_byte_data(client, sda->index,
86 DIV_ROUND_CLOSEST(val, 1000));
87 if (retval < 0)
88 return retval;
89 return count;
90}
91
92static ssize_t show_hyst(struct device *dev,
93 struct device_attribute *attr, char *buf)
94{
95 struct i2c_client *client = to_i2c_client(dev);
96 struct thermal_data *data = i2c_get_clientdata(client);
97 struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
98 int retval;
99 int hyst;
100
101 retval = i2c_smbus_read_byte_data(client, sda->index);
102 if (retval < 0)
103 return retval;
104
105 if (time_after(jiffies, data->hyst_valid)) {
106 hyst = i2c_smbus_read_byte_data(client, 0x21);
107 if (hyst < 0)
108 return retval;
109 data->cached_hyst = hyst;
110 data->hyst_valid = jiffies + HZ;
111 }
112 return sprintf(buf, "%d000\n", retval - data->cached_hyst);
113}
114
115static ssize_t store_hyst(struct device *dev,
116 struct device_attribute *attr, const char *buf, size_t count)
117{
118 struct i2c_client *client = to_i2c_client(dev);
119 struct thermal_data *data = i2c_get_clientdata(client);
120 struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
121 int retval;
122 int hyst;
123 unsigned long val;
124
125 if (strict_strtoul(buf, 10, &val))
126 return -EINVAL;
127
128 mutex_lock(&data->mutex);
129 retval = i2c_smbus_read_byte_data(client, sda->index);
130 if (retval < 0)
131 goto fail;
132
133 hyst = val - retval * 1000;
134 hyst = DIV_ROUND_CLOSEST(hyst, 1000);
135 if (hyst < 0 || hyst > 255) {
136 retval = -ERANGE;
137 goto fail;
138 }
139
140 retval = i2c_smbus_write_byte_data(client, 0x21, hyst);
141 if (retval == 0) {
142 retval = count;
143 data->cached_hyst = hyst;
144 data->hyst_valid = jiffies + HZ;
145 }
146fail:
147 mutex_unlock(&data->mutex);
148 return retval;
149}
150
151/*
152 * Sensors. We pass the actual i2c register to the methods.
153 */
154
155static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO | S_IWUSR,
156 show_temp, store_temp, 0x06);
157static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR,
158 show_temp, store_temp, 0x05);
159static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO | S_IWUSR,
160 show_temp, store_temp, 0x20);
161static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0x00);
162static SENSOR_DEVICE_ATTR_2(temp1_min_alarm, S_IRUGO,
163 show_bit, NULL, 0x36, 0x01);
164static SENSOR_DEVICE_ATTR_2(temp1_max_alarm, S_IRUGO,
165 show_bit, NULL, 0x35, 0x01);
166static SENSOR_DEVICE_ATTR_2(temp1_crit_alarm, S_IRUGO,
167 show_bit, NULL, 0x37, 0x01);
168static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO | S_IWUSR,
169 show_hyst, store_hyst, 0x20);
170
171static SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO | S_IWUSR,
172 show_temp, store_temp, 0x08);
173static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO | S_IWUSR,
174 show_temp, store_temp, 0x07);
175static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO | S_IWUSR,
176 show_temp, store_temp, 0x19);
177static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 0x01);
178static SENSOR_DEVICE_ATTR_2(temp2_min_alarm, S_IRUGO,
179 show_bit, NULL, 0x36, 0x02);
180static SENSOR_DEVICE_ATTR_2(temp2_max_alarm, S_IRUGO,
181 show_bit, NULL, 0x35, 0x02);
182static SENSOR_DEVICE_ATTR_2(temp2_crit_alarm, S_IRUGO,
183 show_bit, NULL, 0x37, 0x02);
184static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO | S_IWUSR,
185 show_hyst, store_hyst, 0x19);
186
187static SENSOR_DEVICE_ATTR(temp3_min, S_IRUGO | S_IWUSR,
188 show_temp, store_temp, 0x16);
189static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO | S_IWUSR,
190 show_temp, store_temp, 0x15);
191static SENSOR_DEVICE_ATTR(temp3_crit, S_IRUGO | S_IWUSR,
192 show_temp, store_temp, 0x1A);
193static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 0x23);
194static SENSOR_DEVICE_ATTR_2(temp3_min_alarm, S_IRUGO,
195 show_bit, NULL, 0x36, 0x04);
196static SENSOR_DEVICE_ATTR_2(temp3_max_alarm, S_IRUGO,
197 show_bit, NULL, 0x35, 0x04);
198static SENSOR_DEVICE_ATTR_2(temp3_crit_alarm, S_IRUGO,
199 show_bit, NULL, 0x37, 0x04);
200static SENSOR_DEVICE_ATTR(temp3_crit_hyst, S_IRUGO | S_IWUSR,
201 show_hyst, store_hyst, 0x1A);
202
203static struct attribute *mid_att_thermal[] = {
204 &sensor_dev_attr_temp1_min.dev_attr.attr,
205 &sensor_dev_attr_temp1_max.dev_attr.attr,
206 &sensor_dev_attr_temp1_crit.dev_attr.attr,
207 &sensor_dev_attr_temp1_input.dev_attr.attr,
208 &sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
209 &sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
210 &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
211 &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,
212 &sensor_dev_attr_temp2_min.dev_attr.attr,
213 &sensor_dev_attr_temp2_max.dev_attr.attr,
214 &sensor_dev_attr_temp2_crit.dev_attr.attr,
215 &sensor_dev_attr_temp2_input.dev_attr.attr,
216 &sensor_dev_attr_temp2_min_alarm.dev_attr.attr,
217 &sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
218 &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
219 &sensor_dev_attr_temp2_crit_hyst.dev_attr.attr,
220 &sensor_dev_attr_temp3_min.dev_attr.attr,
221 &sensor_dev_attr_temp3_max.dev_attr.attr,
222 &sensor_dev_attr_temp3_crit.dev_attr.attr,
223 &sensor_dev_attr_temp3_input.dev_attr.attr,
224 &sensor_dev_attr_temp3_min_alarm.dev_attr.attr,
225 &sensor_dev_attr_temp3_max_alarm.dev_attr.attr,
226 &sensor_dev_attr_temp3_crit_alarm.dev_attr.attr,
227 &sensor_dev_attr_temp3_crit_hyst.dev_attr.attr,
228 NULL
229};
230
231static const struct attribute_group m_thermal_gr = {
232 .attrs = mid_att_thermal
233};
234
235static int emc1403_detect(struct i2c_client *client,
236 struct i2c_board_info *info)
237{
238 int id;
239 /* Check if thermal chip is SMSC and EMC1403 */
240
241 id = i2c_smbus_read_byte_data(client, THERMAL_SMSC_ID_REG);
242 if (id != 0x5d)
243 return -ENODEV;
244
245 /* Note: 0x25 is the 1404 which is very similar and this
246 driver could be extended */
247 id = i2c_smbus_read_byte_data(client, THERMAL_PID_REG);
248 if (id != 0x21)
249 return -ENODEV;
250
251 id = i2c_smbus_read_byte_data(client, THERMAL_REVISION_REG);
252 if (id != 0x01)
253 return -ENODEV;
254
255 strlcpy(info->type, "emc1403", I2C_NAME_SIZE);
256 return 0;
257}
258
259static int emc1403_probe(struct i2c_client *client,
260 const struct i2c_device_id *id)
261{
262 int res;
263 struct thermal_data *data;
264
265 data = kzalloc(sizeof(struct thermal_data), GFP_KERNEL);
266 if (data == NULL) {
267 dev_warn(&client->dev, "out of memory");
268 return -ENOMEM;
269 }
270
271 i2c_set_clientdata(client, data);
272 mutex_init(&data->mutex);
273 data->hyst_valid = jiffies - 1; /* Expired */
274
275 res = sysfs_create_group(&client->dev.kobj, &m_thermal_gr);
276 if (res) {
277 dev_warn(&client->dev, "create group failed\n");
278 hwmon_device_unregister(data->hwmon_dev);
279 goto thermal_error1;
280 }
281 data->hwmon_dev = hwmon_device_register(&client->dev);
282 if (IS_ERR(data->hwmon_dev)) {
283 res = PTR_ERR(data->hwmon_dev);
284 dev_warn(&client->dev, "register hwmon dev failed\n");
285 goto thermal_error2;
286 }
287 dev_info(&client->dev, "EMC1403 Thermal chip found\n");
288 return res;
289
290thermal_error2:
291 sysfs_remove_group(&client->dev.kobj, &m_thermal_gr);
292thermal_error1:
293 kfree(data);
294 return res;
295}
296
297static int emc1403_remove(struct i2c_client *client)
298{
299 struct thermal_data *data = i2c_get_clientdata(client);
300
301 hwmon_device_unregister(data->hwmon_dev);
302 sysfs_remove_group(&client->dev.kobj, &m_thermal_gr);
303 kfree(data);
304 return 0;
305}
306
307static const unsigned short emc1403_address_list[] = {
308 0x18, 0x2a, 0x4c, 0x4d, I2C_CLIENT_END
309};
310
311static const struct i2c_device_id emc1403_idtable[] = {
312 { "emc1403", 0 },
313 { }
314};
315MODULE_DEVICE_TABLE(i2c, emc1403_idtable);
316
317static struct i2c_driver sensor_emc1403 = {
318 .class = I2C_CLASS_HWMON,
319 .driver = {
320 .name = "emc1403",
321 },
322 .detect = emc1403_detect,
323 .probe = emc1403_probe,
324 .remove = emc1403_remove,
325 .id_table = emc1403_idtable,
326 .address_list = emc1403_address_list,
327};
328
329static int __init sensor_emc1403_init(void)
330{
331 return i2c_add_driver(&sensor_emc1403);
332}
333
334static void __exit sensor_emc1403_exit(void)
335{
336 i2c_del_driver(&sensor_emc1403);
337}
338
339module_init(sensor_emc1403_init);
340module_exit(sensor_emc1403_exit);
341
342MODULE_AUTHOR("Kalhan Trisal <kalhan.trisal@intel.com");
343MODULE_DESCRIPTION("emc1403 Thermal Driver");
344MODULE_LICENSE("GPL v2");
diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c
index a95fa4256caa..537841ef44b9 100644
--- a/drivers/hwmon/f71882fg.c
+++ b/drivers/hwmon/f71882fg.c
@@ -856,21 +856,19 @@ static inline int superio_inb(int base, int reg)
856static int superio_inw(int base, int reg) 856static int superio_inw(int base, int reg)
857{ 857{
858 int val; 858 int val;
859 outb(reg++, base); 859 val = superio_inb(base, reg) << 8;
860 val = inb(base + 1) << 8; 860 val |= superio_inb(base, reg + 1);
861 outb(reg, base);
862 val |= inb(base + 1);
863 return val; 861 return val;
864} 862}
865 863
866static inline void superio_enter(int base) 864static inline void superio_enter(int base)
867{ 865{
868 /* according to the datasheet the key must be send twice! */ 866 /* according to the datasheet the key must be send twice! */
869 outb( SIO_UNLOCK_KEY, base); 867 outb(SIO_UNLOCK_KEY, base);
870 outb( SIO_UNLOCK_KEY, base); 868 outb(SIO_UNLOCK_KEY, base);
871} 869}
872 870
873static inline void superio_select( int base, int ld) 871static inline void superio_select(int base, int ld)
874{ 872{
875 outb(SIO_REG_LDSEL, base); 873 outb(SIO_REG_LDSEL, base);
876 outb(ld, base + 1); 874 outb(ld, base + 1);
@@ -905,10 +903,8 @@ static u16 f71882fg_read16(struct f71882fg_data *data, u8 reg)
905{ 903{
906 u16 val; 904 u16 val;
907 905
908 outb(reg++, data->addr + ADDR_REG_OFFSET); 906 val = f71882fg_read8(data, reg) << 8;
909 val = inb(data->addr + DATA_REG_OFFSET) << 8; 907 val |= f71882fg_read8(data, reg + 1);
910 outb(reg, data->addr + ADDR_REG_OFFSET);
911 val |= inb(data->addr + DATA_REG_OFFSET);
912 908
913 return val; 909 return val;
914} 910}
@@ -921,10 +917,8 @@ static void f71882fg_write8(struct f71882fg_data *data, u8 reg, u8 val)
921 917
922static void f71882fg_write16(struct f71882fg_data *data, u8 reg, u16 val) 918static void f71882fg_write16(struct f71882fg_data *data, u8 reg, u16 val)
923{ 919{
924 outb(reg++, data->addr + ADDR_REG_OFFSET); 920 f71882fg_write8(data, reg, val >> 8);
925 outb(val >> 8, data->addr + DATA_REG_OFFSET); 921 f71882fg_write8(data, reg + 1, val & 0xff);
926 outb(reg, data->addr + ADDR_REG_OFFSET);
927 outb(val & 255, data->addr + DATA_REG_OFFSET);
928} 922}
929 923
930static u16 f71882fg_read_temp(struct f71882fg_data *data, int nr) 924static u16 f71882fg_read_temp(struct f71882fg_data *data, int nr)
@@ -945,7 +939,7 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev)
945 mutex_lock(&data->update_lock); 939 mutex_lock(&data->update_lock);
946 940
947 /* Update once every 60 seconds */ 941 /* Update once every 60 seconds */
948 if ( time_after(jiffies, data->last_limits + 60 * HZ ) || 942 if (time_after(jiffies, data->last_limits + 60 * HZ) ||
949 !data->valid) { 943 !data->valid) {
950 if (data->type == f71882fg || data->type == f71889fg) { 944 if (data->type == f71882fg || data->type == f71889fg) {
951 data->in1_max = 945 data->in1_max =
@@ -1127,8 +1121,12 @@ static ssize_t store_fan_full_speed(struct device *dev,
1127 const char *buf, size_t count) 1121 const char *buf, size_t count)
1128{ 1122{
1129 struct f71882fg_data *data = dev_get_drvdata(dev); 1123 struct f71882fg_data *data = dev_get_drvdata(dev);
1130 int nr = to_sensor_dev_attr_2(devattr)->index; 1124 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1131 long val = simple_strtol(buf, NULL, 10); 1125 long val;
1126
1127 err = strict_strtol(buf, 10, &val);
1128 if (err)
1129 return err;
1132 1130
1133 val = SENSORS_LIMIT(val, 23, 1500000); 1131 val = SENSORS_LIMIT(val, 23, 1500000);
1134 val = fan_to_reg(val); 1132 val = fan_to_reg(val);
@@ -1157,8 +1155,12 @@ static ssize_t store_fan_beep(struct device *dev, struct device_attribute
1157 *devattr, const char *buf, size_t count) 1155 *devattr, const char *buf, size_t count)
1158{ 1156{
1159 struct f71882fg_data *data = dev_get_drvdata(dev); 1157 struct f71882fg_data *data = dev_get_drvdata(dev);
1160 int nr = to_sensor_dev_attr_2(devattr)->index; 1158 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1161 unsigned long val = simple_strtoul(buf, NULL, 10); 1159 unsigned long val;
1160
1161 err = strict_strtoul(buf, 10, &val);
1162 if (err)
1163 return err;
1162 1164
1163 mutex_lock(&data->update_lock); 1165 mutex_lock(&data->update_lock);
1164 data->fan_beep = f71882fg_read8(data, F71882FG_REG_FAN_BEEP); 1166 data->fan_beep = f71882fg_read8(data, F71882FG_REG_FAN_BEEP);
@@ -1206,7 +1208,14 @@ static ssize_t store_in_max(struct device *dev, struct device_attribute
1206 *devattr, const char *buf, size_t count) 1208 *devattr, const char *buf, size_t count)
1207{ 1209{
1208 struct f71882fg_data *data = dev_get_drvdata(dev); 1210 struct f71882fg_data *data = dev_get_drvdata(dev);
1209 long val = simple_strtol(buf, NULL, 10) / 8; 1211 int err;
1212 long val;
1213
1214 err = strict_strtol(buf, 10, &val);
1215 if (err)
1216 return err;
1217
1218 val /= 8;
1210 val = SENSORS_LIMIT(val, 0, 255); 1219 val = SENSORS_LIMIT(val, 0, 255);
1211 1220
1212 mutex_lock(&data->update_lock); 1221 mutex_lock(&data->update_lock);
@@ -1233,8 +1242,12 @@ static ssize_t store_in_beep(struct device *dev, struct device_attribute
1233 *devattr, const char *buf, size_t count) 1242 *devattr, const char *buf, size_t count)
1234{ 1243{
1235 struct f71882fg_data *data = dev_get_drvdata(dev); 1244 struct f71882fg_data *data = dev_get_drvdata(dev);
1236 int nr = to_sensor_dev_attr_2(devattr)->index; 1245 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1237 unsigned long val = simple_strtoul(buf, NULL, 10); 1246 unsigned long val;
1247
1248 err = strict_strtoul(buf, 10, &val);
1249 if (err)
1250 return err;
1238 1251
1239 mutex_lock(&data->update_lock); 1252 mutex_lock(&data->update_lock);
1240 data->in_beep = f71882fg_read8(data, F71882FG_REG_IN_BEEP); 1253 data->in_beep = f71882fg_read8(data, F71882FG_REG_IN_BEEP);
@@ -1299,8 +1312,14 @@ static ssize_t store_temp_max(struct device *dev, struct device_attribute
1299 *devattr, const char *buf, size_t count) 1312 *devattr, const char *buf, size_t count)
1300{ 1313{
1301 struct f71882fg_data *data = dev_get_drvdata(dev); 1314 struct f71882fg_data *data = dev_get_drvdata(dev);
1302 int nr = to_sensor_dev_attr_2(devattr)->index; 1315 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1303 long val = simple_strtol(buf, NULL, 10) / 1000; 1316 long val;
1317
1318 err = strict_strtol(buf, 10, &val);
1319 if (err)
1320 return err;
1321
1322 val /= 1000;
1304 val = SENSORS_LIMIT(val, 0, 255); 1323 val = SENSORS_LIMIT(val, 0, 255);
1305 1324
1306 mutex_lock(&data->update_lock); 1325 mutex_lock(&data->update_lock);
@@ -1333,10 +1352,16 @@ static ssize_t store_temp_max_hyst(struct device *dev, struct device_attribute
1333 *devattr, const char *buf, size_t count) 1352 *devattr, const char *buf, size_t count)
1334{ 1353{
1335 struct f71882fg_data *data = dev_get_drvdata(dev); 1354 struct f71882fg_data *data = dev_get_drvdata(dev);
1336 int nr = to_sensor_dev_attr_2(devattr)->index; 1355 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1337 long val = simple_strtol(buf, NULL, 10) / 1000;
1338 ssize_t ret = count; 1356 ssize_t ret = count;
1339 u8 reg; 1357 u8 reg;
1358 long val;
1359
1360 err = strict_strtol(buf, 10, &val);
1361 if (err)
1362 return err;
1363
1364 val /= 1000;
1340 1365
1341 mutex_lock(&data->update_lock); 1366 mutex_lock(&data->update_lock);
1342 1367
@@ -1372,8 +1397,14 @@ static ssize_t store_temp_crit(struct device *dev, struct device_attribute
1372 *devattr, const char *buf, size_t count) 1397 *devattr, const char *buf, size_t count)
1373{ 1398{
1374 struct f71882fg_data *data = dev_get_drvdata(dev); 1399 struct f71882fg_data *data = dev_get_drvdata(dev);
1375 int nr = to_sensor_dev_attr_2(devattr)->index; 1400 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1376 long val = simple_strtol(buf, NULL, 10) / 1000; 1401 long val;
1402
1403 err = strict_strtol(buf, 10, &val);
1404 if (err)
1405 return err;
1406
1407 val /= 1000;
1377 val = SENSORS_LIMIT(val, 0, 255); 1408 val = SENSORS_LIMIT(val, 0, 255);
1378 1409
1379 mutex_lock(&data->update_lock); 1410 mutex_lock(&data->update_lock);
@@ -1427,8 +1458,12 @@ static ssize_t store_temp_beep(struct device *dev, struct device_attribute
1427 *devattr, const char *buf, size_t count) 1458 *devattr, const char *buf, size_t count)
1428{ 1459{
1429 struct f71882fg_data *data = dev_get_drvdata(dev); 1460 struct f71882fg_data *data = dev_get_drvdata(dev);
1430 int nr = to_sensor_dev_attr_2(devattr)->index; 1461 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1431 unsigned long val = simple_strtoul(buf, NULL, 10); 1462 unsigned long val;
1463
1464 err = strict_strtoul(buf, 10, &val);
1465 if (err)
1466 return err;
1432 1467
1433 mutex_lock(&data->update_lock); 1468 mutex_lock(&data->update_lock);
1434 data->temp_beep = f71882fg_read8(data, F71882FG_REG_TEMP_BEEP); 1469 data->temp_beep = f71882fg_read8(data, F71882FG_REG_TEMP_BEEP);
@@ -1490,8 +1525,13 @@ static ssize_t store_pwm(struct device *dev,
1490 size_t count) 1525 size_t count)
1491{ 1526{
1492 struct f71882fg_data *data = dev_get_drvdata(dev); 1527 struct f71882fg_data *data = dev_get_drvdata(dev);
1493 int nr = to_sensor_dev_attr_2(devattr)->index; 1528 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1494 long val = simple_strtol(buf, NULL, 10); 1529 long val;
1530
1531 err = strict_strtol(buf, 10, &val);
1532 if (err)
1533 return err;
1534
1495 val = SENSORS_LIMIT(val, 0, 255); 1535 val = SENSORS_LIMIT(val, 0, 255);
1496 1536
1497 mutex_lock(&data->update_lock); 1537 mutex_lock(&data->update_lock);
@@ -1551,8 +1591,12 @@ static ssize_t store_pwm_enable(struct device *dev, struct device_attribute
1551 *devattr, const char *buf, size_t count) 1591 *devattr, const char *buf, size_t count)
1552{ 1592{
1553 struct f71882fg_data *data = dev_get_drvdata(dev); 1593 struct f71882fg_data *data = dev_get_drvdata(dev);
1554 int nr = to_sensor_dev_attr_2(devattr)->index; 1594 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1555 long val = simple_strtol(buf, NULL, 10); 1595 long val;
1596
1597 err = strict_strtol(buf, 10, &val);
1598 if (err)
1599 return err;
1556 1600
1557 /* Special case for F8000 pwm channel 3 which only does auto mode */ 1601 /* Special case for F8000 pwm channel 3 which only does auto mode */
1558 if (data->type == f8000 && nr == 2 && val != 2) 1602 if (data->type == f8000 && nr == 2 && val != 2)
@@ -1626,9 +1670,14 @@ static ssize_t store_pwm_auto_point_pwm(struct device *dev,
1626 const char *buf, size_t count) 1670 const char *buf, size_t count)
1627{ 1671{
1628 struct f71882fg_data *data = dev_get_drvdata(dev); 1672 struct f71882fg_data *data = dev_get_drvdata(dev);
1629 int pwm = to_sensor_dev_attr_2(devattr)->index; 1673 int err, pwm = to_sensor_dev_attr_2(devattr)->index;
1630 int point = to_sensor_dev_attr_2(devattr)->nr; 1674 int point = to_sensor_dev_attr_2(devattr)->nr;
1631 long val = simple_strtol(buf, NULL, 10); 1675 long val;
1676
1677 err = strict_strtol(buf, 10, &val);
1678 if (err)
1679 return err;
1680
1632 val = SENSORS_LIMIT(val, 0, 255); 1681 val = SENSORS_LIMIT(val, 0, 255);
1633 1682
1634 mutex_lock(&data->update_lock); 1683 mutex_lock(&data->update_lock);
@@ -1674,10 +1723,16 @@ static ssize_t store_pwm_auto_point_temp_hyst(struct device *dev,
1674 const char *buf, size_t count) 1723 const char *buf, size_t count)
1675{ 1724{
1676 struct f71882fg_data *data = dev_get_drvdata(dev); 1725 struct f71882fg_data *data = dev_get_drvdata(dev);
1677 int nr = to_sensor_dev_attr_2(devattr)->index; 1726 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1678 int point = to_sensor_dev_attr_2(devattr)->nr; 1727 int point = to_sensor_dev_attr_2(devattr)->nr;
1679 long val = simple_strtol(buf, NULL, 10) / 1000;
1680 u8 reg; 1728 u8 reg;
1729 long val;
1730
1731 err = strict_strtol(buf, 10, &val);
1732 if (err)
1733 return err;
1734
1735 val /= 1000;
1681 1736
1682 mutex_lock(&data->update_lock); 1737 mutex_lock(&data->update_lock);
1683 data->pwm_auto_point_temp[nr][point] = 1738 data->pwm_auto_point_temp[nr][point] =
@@ -1716,8 +1771,12 @@ static ssize_t store_pwm_interpolate(struct device *dev,
1716 const char *buf, size_t count) 1771 const char *buf, size_t count)
1717{ 1772{
1718 struct f71882fg_data *data = dev_get_drvdata(dev); 1773 struct f71882fg_data *data = dev_get_drvdata(dev);
1719 int nr = to_sensor_dev_attr_2(devattr)->index; 1774 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1720 unsigned long val = simple_strtoul(buf, NULL, 10); 1775 unsigned long val;
1776
1777 err = strict_strtoul(buf, 10, &val);
1778 if (err)
1779 return err;
1721 1780
1722 mutex_lock(&data->update_lock); 1781 mutex_lock(&data->update_lock);
1723 data->pwm_auto_point_mapping[nr] = 1782 data->pwm_auto_point_mapping[nr] =
@@ -1752,8 +1811,12 @@ static ssize_t store_pwm_auto_point_channel(struct device *dev,
1752 const char *buf, size_t count) 1811 const char *buf, size_t count)
1753{ 1812{
1754 struct f71882fg_data *data = dev_get_drvdata(dev); 1813 struct f71882fg_data *data = dev_get_drvdata(dev);
1755 int nr = to_sensor_dev_attr_2(devattr)->index; 1814 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1756 long val = simple_strtol(buf, NULL, 10); 1815 long val;
1816
1817 err = strict_strtol(buf, 10, &val);
1818 if (err)
1819 return err;
1757 1820
1758 switch (val) { 1821 switch (val) {
1759 case 1: 1822 case 1:
@@ -1798,9 +1861,15 @@ static ssize_t store_pwm_auto_point_temp(struct device *dev,
1798 const char *buf, size_t count) 1861 const char *buf, size_t count)
1799{ 1862{
1800 struct f71882fg_data *data = dev_get_drvdata(dev); 1863 struct f71882fg_data *data = dev_get_drvdata(dev);
1801 int pwm = to_sensor_dev_attr_2(devattr)->index; 1864 int err, pwm = to_sensor_dev_attr_2(devattr)->index;
1802 int point = to_sensor_dev_attr_2(devattr)->nr; 1865 int point = to_sensor_dev_attr_2(devattr)->nr;
1803 long val = simple_strtol(buf, NULL, 10) / 1000; 1866 long val;
1867
1868 err = strict_strtol(buf, 10, &val);
1869 if (err)
1870 return err;
1871
1872 val /= 1000;
1804 1873
1805 if (data->type == f71889fg) 1874 if (data->type == f71889fg)
1806 val = SENSORS_LIMIT(val, -128, 127); 1875 val = SENSORS_LIMIT(val, -128, 127);
@@ -2109,6 +2178,13 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address,
2109 int err = -ENODEV; 2178 int err = -ENODEV;
2110 u16 devid; 2179 u16 devid;
2111 2180
2181 /* Don't step on other drivers' I/O space by accident */
2182 if (!request_region(sioaddr, 2, DRVNAME)) {
2183 printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n",
2184 (int)sioaddr);
2185 return -EBUSY;
2186 }
2187
2112 superio_enter(sioaddr); 2188 superio_enter(sioaddr);
2113 2189
2114 devid = superio_inw(sioaddr, SIO_REG_MANID); 2190 devid = superio_inw(sioaddr, SIO_REG_MANID);
@@ -2151,8 +2227,7 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address,
2151 } 2227 }
2152 2228
2153 *address = superio_inw(sioaddr, SIO_REG_ADDR); 2229 *address = superio_inw(sioaddr, SIO_REG_ADDR);
2154 if (*address == 0) 2230 if (*address == 0) {
2155 {
2156 printk(KERN_WARNING DRVNAME ": Base address not set\n"); 2231 printk(KERN_WARNING DRVNAME ": Base address not set\n");
2157 goto exit; 2232 goto exit;
2158 } 2233 }
@@ -2164,6 +2239,7 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address,
2164 (int)superio_inb(sioaddr, SIO_REG_DEVREV)); 2239 (int)superio_inb(sioaddr, SIO_REG_DEVREV));
2165exit: 2240exit:
2166 superio_exit(sioaddr); 2241 superio_exit(sioaddr);
2242 release_region(sioaddr, 2);
2167 return err; 2243 return err;
2168} 2244}
2169 2245
diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c
index bad2cf3ef4a4..0f58ecc5334d 100644
--- a/drivers/hwmon/f75375s.c
+++ b/drivers/hwmon/f75375s.c
@@ -662,7 +662,6 @@ exit_remove:
662 sysfs_remove_group(&client->dev.kobj, &f75375_group); 662 sysfs_remove_group(&client->dev.kobj, &f75375_group);
663exit_free: 663exit_free:
664 kfree(data); 664 kfree(data);
665 i2c_set_clientdata(client, NULL);
666 return err; 665 return err;
667} 666}
668 667
@@ -672,7 +671,6 @@ static int f75375_remove(struct i2c_client *client)
672 hwmon_device_unregister(data->hwmon_dev); 671 hwmon_device_unregister(data->hwmon_dev);
673 sysfs_remove_group(&client->dev.kobj, &f75375_group); 672 sysfs_remove_group(&client->dev.kobj, &f75375_group);
674 kfree(data); 673 kfree(data);
675 i2c_set_clientdata(client, NULL);
676 return 0; 674 return 0;
677} 675}
678 676
diff --git a/drivers/hwmon/g760a.c b/drivers/hwmon/g760a.c
index 09ea12e0a551..1f63d1a3af5e 100644
--- a/drivers/hwmon/g760a.c
+++ b/drivers/hwmon/g760a.c
@@ -236,7 +236,6 @@ error_hwmon_device_register:
236 sysfs_remove_group(&client->dev.kobj, &g760a_group); 236 sysfs_remove_group(&client->dev.kobj, &g760a_group);
237error_sysfs_create_group: 237error_sysfs_create_group:
238 kfree(data); 238 kfree(data);
239 i2c_set_clientdata(client, NULL);
240 239
241 return err; 240 return err;
242} 241}
@@ -247,7 +246,6 @@ static int g760a_remove(struct i2c_client *client)
247 hwmon_device_unregister(data->hwmon_dev); 246 hwmon_device_unregister(data->hwmon_dev);
248 sysfs_remove_group(&client->dev.kobj, &g760a_group); 247 sysfs_remove_group(&client->dev.kobj, &g760a_group);
249 kfree(data); 248 kfree(data);
250 i2c_set_clientdata(client, NULL);
251 249
252 return 0; 250 return 0;
253} 251}
diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c
index bf81aff7051d..776aeb3019d2 100644
--- a/drivers/hwmon/lm63.c
+++ b/drivers/hwmon/lm63.c
@@ -53,7 +53,7 @@
53 * Address is fully defined internally and cannot be changed. 53 * Address is fully defined internally and cannot be changed.
54 */ 54 */
55 55
56static const unsigned short normal_i2c[] = { 0x4c, I2C_CLIENT_END }; 56static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END };
57 57
58/* 58/*
59 * The LM63 registers 59 * The LM63 registers
@@ -131,12 +131,15 @@ static struct lm63_data *lm63_update_device(struct device *dev);
131static int lm63_detect(struct i2c_client *client, struct i2c_board_info *info); 131static int lm63_detect(struct i2c_client *client, struct i2c_board_info *info);
132static void lm63_init_client(struct i2c_client *client); 132static void lm63_init_client(struct i2c_client *client);
133 133
134enum chips { lm63, lm64 };
135
134/* 136/*
135 * Driver data (common to all clients) 137 * Driver data (common to all clients)
136 */ 138 */
137 139
138static const struct i2c_device_id lm63_id[] = { 140static const struct i2c_device_id lm63_id[] = {
139 { "lm63", 0 }, 141 { "lm63", lm63 },
142 { "lm64", lm64 },
140 { } 143 { }
141}; 144};
142MODULE_DEVICE_TABLE(i2c, lm63_id); 145MODULE_DEVICE_TABLE(i2c, lm63_id);
@@ -422,6 +425,7 @@ static int lm63_detect(struct i2c_client *new_client,
422 struct i2c_adapter *adapter = new_client->adapter; 425 struct i2c_adapter *adapter = new_client->adapter;
423 u8 man_id, chip_id, reg_config1, reg_config2; 426 u8 man_id, chip_id, reg_config1, reg_config2;
424 u8 reg_alert_status, reg_alert_mask; 427 u8 reg_alert_status, reg_alert_mask;
428 int address = new_client->addr;
425 429
426 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 430 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
427 return -ENODEV; 431 return -ENODEV;
@@ -439,7 +443,6 @@ static int lm63_detect(struct i2c_client *new_client,
439 LM63_REG_ALERT_MASK); 443 LM63_REG_ALERT_MASK);
440 444
441 if (man_id != 0x01 /* National Semiconductor */ 445 if (man_id != 0x01 /* National Semiconductor */
442 || chip_id != 0x41 /* LM63 */
443 || (reg_config1 & 0x18) != 0x00 446 || (reg_config1 & 0x18) != 0x00
444 || (reg_config2 & 0xF8) != 0x00 447 || (reg_config2 & 0xF8) != 0x00
445 || (reg_alert_status & 0x20) != 0x00 448 || (reg_alert_status & 0x20) != 0x00
@@ -450,7 +453,12 @@ static int lm63_detect(struct i2c_client *new_client,
450 return -ENODEV; 453 return -ENODEV;
451 } 454 }
452 455
453 strlcpy(info->type, "lm63", I2C_NAME_SIZE); 456 if (chip_id == 0x41 && address == 0x4c)
457 strlcpy(info->type, "lm63", I2C_NAME_SIZE);
458 else if (chip_id == 0x51 && (address == 0x18 || address == 0x4e))
459 strlcpy(info->type, "lm64", I2C_NAME_SIZE);
460 else
461 return -ENODEV;
454 462
455 return 0; 463 return 0;
456} 464}
diff --git a/drivers/hwmon/lm73.c b/drivers/hwmon/lm73.c
index 4d1b76bc8148..29b9030d42c3 100644
--- a/drivers/hwmon/lm73.c
+++ b/drivers/hwmon/lm73.c
@@ -136,7 +136,6 @@ static int lm73_remove(struct i2c_client *client)
136 136
137 hwmon_device_unregister(hwmon_dev); 137 hwmon_device_unregister(hwmon_dev);
138 sysfs_remove_group(&client->dev.kobj, &lm73_group); 138 sysfs_remove_group(&client->dev.kobj, &lm73_group);
139 i2c_set_clientdata(client, NULL);
140 return 0; 139 return 0;
141} 140}
142 141
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
index 8ae2cfe2d827..393f354f92a4 100644
--- a/drivers/hwmon/lm75.c
+++ b/drivers/hwmon/lm75.c
@@ -46,6 +46,7 @@ enum lm75_type { /* keep sorted in alphabetical order */
46 tcn75, 46 tcn75,
47 tmp100, 47 tmp100,
48 tmp101, 48 tmp101,
49 tmp105,
49 tmp175, 50 tmp175,
50 tmp275, 51 tmp275,
51 tmp75, 52 tmp75,
@@ -191,7 +192,6 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
191exit_remove: 192exit_remove:
192 sysfs_remove_group(&client->dev.kobj, &lm75_group); 193 sysfs_remove_group(&client->dev.kobj, &lm75_group);
193exit_free: 194exit_free:
194 i2c_set_clientdata(client, NULL);
195 kfree(data); 195 kfree(data);
196 return status; 196 return status;
197} 197}
@@ -203,7 +203,6 @@ static int lm75_remove(struct i2c_client *client)
203 hwmon_device_unregister(data->hwmon_dev); 203 hwmon_device_unregister(data->hwmon_dev);
204 sysfs_remove_group(&client->dev.kobj, &lm75_group); 204 sysfs_remove_group(&client->dev.kobj, &lm75_group);
205 lm75_write_value(client, LM75_REG_CONF, data->orig_conf); 205 lm75_write_value(client, LM75_REG_CONF, data->orig_conf);
206 i2c_set_clientdata(client, NULL);
207 kfree(data); 206 kfree(data);
208 return 0; 207 return 0;
209} 208}
@@ -220,6 +219,7 @@ static const struct i2c_device_id lm75_ids[] = {
220 { "tcn75", tcn75, }, 219 { "tcn75", tcn75, },
221 { "tmp100", tmp100, }, 220 { "tmp100", tmp100, },
222 { "tmp101", tmp101, }, 221 { "tmp101", tmp101, },
222 { "tmp105", tmp105, },
223 { "tmp175", tmp175, }, 223 { "tmp175", tmp175, },
224 { "tmp275", tmp275, }, 224 { "tmp275", tmp275, },
225 { "tmp75", tmp75, }, 225 { "tmp75", tmp75, },
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c
index 7cc2708871ab..760ef72eea56 100644
--- a/drivers/hwmon/lm90.c
+++ b/drivers/hwmon/lm90.c
@@ -982,7 +982,8 @@ static struct lm90_data *lm90_update_device(struct device *dev)
982 982
983 mutex_lock(&data->update_lock); 983 mutex_lock(&data->update_lock);
984 984
985 if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { 985 if (time_after(jiffies, data->last_updated + HZ / 2 + HZ / 10)
986 || !data->valid) {
986 u8 h, l; 987 u8 h, l;
987 988
988 dev_dbg(&client->dev, "Updating lm90 data.\n"); 989 dev_dbg(&client->dev, "Updating lm90 data.\n");
diff --git a/drivers/hwmon/lm95241.c b/drivers/hwmon/lm95241.c
index 8fc8eb8cba47..94741d42112d 100644
--- a/drivers/hwmon/lm95241.c
+++ b/drivers/hwmon/lm95241.c
@@ -399,7 +399,6 @@ static int lm95241_remove(struct i2c_client *client)
399 hwmon_device_unregister(data->hwmon_dev); 399 hwmon_device_unregister(data->hwmon_dev);
400 sysfs_remove_group(&client->dev.kobj, &lm95241_group); 400 sysfs_remove_group(&client->dev.kobj, &lm95241_group);
401 401
402 i2c_set_clientdata(client, NULL);
403 kfree(data); 402 kfree(data);
404 return 0; 403 return 0;
405} 404}
diff --git a/drivers/hwmon/ltc4245.c b/drivers/hwmon/ltc4245.c
index 65c232a9d0c5..21d201befc2c 100644
--- a/drivers/hwmon/ltc4245.c
+++ b/drivers/hwmon/ltc4245.c
@@ -45,9 +45,7 @@ enum ltc4245_cmd {
45 LTC4245_VEEIN = 0x19, 45 LTC4245_VEEIN = 0x19,
46 LTC4245_VEESENSE = 0x1a, 46 LTC4245_VEESENSE = 0x1a,
47 LTC4245_VEEOUT = 0x1b, 47 LTC4245_VEEOUT = 0x1b,
48 LTC4245_GPIOADC1 = 0x1c, 48 LTC4245_GPIOADC = 0x1c,
49 LTC4245_GPIOADC2 = 0x1d,
50 LTC4245_GPIOADC3 = 0x1e,
51}; 49};
52 50
53struct ltc4245_data { 51struct ltc4245_data {
@@ -61,7 +59,7 @@ struct ltc4245_data {
61 u8 cregs[0x08]; 59 u8 cregs[0x08];
62 60
63 /* Voltage registers */ 61 /* Voltage registers */
64 u8 vregs[0x0f]; 62 u8 vregs[0x0d];
65}; 63};
66 64
67static struct ltc4245_data *ltc4245_update_device(struct device *dev) 65static struct ltc4245_data *ltc4245_update_device(struct device *dev)
@@ -86,7 +84,7 @@ static struct ltc4245_data *ltc4245_update_device(struct device *dev)
86 data->cregs[i] = val; 84 data->cregs[i] = val;
87 } 85 }
88 86
89 /* Read voltage registers -- 0x10 to 0x1f */ 87 /* Read voltage registers -- 0x10 to 0x1c */
90 for (i = 0; i < ARRAY_SIZE(data->vregs); i++) { 88 for (i = 0; i < ARRAY_SIZE(data->vregs); i++) {
91 val = i2c_smbus_read_byte_data(client, i+0x10); 89 val = i2c_smbus_read_byte_data(client, i+0x10);
92 if (unlikely(val < 0)) 90 if (unlikely(val < 0))
@@ -128,9 +126,7 @@ static int ltc4245_get_voltage(struct device *dev, u8 reg)
128 case LTC4245_VEEOUT: 126 case LTC4245_VEEOUT:
129 voltage = regval * -55; 127 voltage = regval * -55;
130 break; 128 break;
131 case LTC4245_GPIOADC1: 129 case LTC4245_GPIOADC:
132 case LTC4245_GPIOADC2:
133 case LTC4245_GPIOADC3:
134 voltage = regval * 10; 130 voltage = regval * 10;
135 break; 131 break;
136 default: 132 default:
@@ -297,9 +293,7 @@ LTC4245_ALARM(in7_min_alarm, (1 << 2), LTC4245_FAULT2);
297LTC4245_ALARM(in8_min_alarm, (1 << 3), LTC4245_FAULT2); 293LTC4245_ALARM(in8_min_alarm, (1 << 3), LTC4245_FAULT2);
298 294
299/* GPIO voltages */ 295/* GPIO voltages */
300LTC4245_VOLTAGE(in9_input, LTC4245_GPIOADC1); 296LTC4245_VOLTAGE(in9_input, LTC4245_GPIOADC);
301LTC4245_VOLTAGE(in10_input, LTC4245_GPIOADC2);
302LTC4245_VOLTAGE(in11_input, LTC4245_GPIOADC3);
303 297
304/* Power Consumption (virtual) */ 298/* Power Consumption (virtual) */
305LTC4245_POWER(power1_input, LTC4245_12VSENSE); 299LTC4245_POWER(power1_input, LTC4245_12VSENSE);
@@ -342,8 +336,6 @@ static struct attribute *ltc4245_attributes[] = {
342 &sensor_dev_attr_in8_min_alarm.dev_attr.attr, 336 &sensor_dev_attr_in8_min_alarm.dev_attr.attr,
343 337
344 &sensor_dev_attr_in9_input.dev_attr.attr, 338 &sensor_dev_attr_in9_input.dev_attr.attr,
345 &sensor_dev_attr_in10_input.dev_attr.attr,
346 &sensor_dev_attr_in11_input.dev_attr.attr,
347 339
348 &sensor_dev_attr_power1_input.dev_attr.attr, 340 &sensor_dev_attr_power1_input.dev_attr.attr,
349 &sensor_dev_attr_power2_input.dev_attr.attr, 341 &sensor_dev_attr_power2_input.dev_attr.attr,
diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c
new file mode 100644
index 000000000000..93187c3cb5e7
--- /dev/null
+++ b/drivers/hwmon/tmp102.c
@@ -0,0 +1,319 @@
1/* Texas Instruments TMP102 SMBus temperature sensor driver
2 *
3 * Copyright (C) 2010 Steven King <sfking@fdwdc.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <linux/module.h>
21#include <linux/init.h>
22#include <linux/slab.h>
23#include <linux/i2c.h>
24#include <linux/hwmon.h>
25#include <linux/hwmon-sysfs.h>
26#include <linux/err.h>
27#include <linux/mutex.h>
28#include <linux/device.h>
29
30#define DRIVER_NAME "tmp102"
31
32#define TMP102_TEMP_REG 0x00
33#define TMP102_CONF_REG 0x01
34/* note: these bit definitions are byte swapped */
35#define TMP102_CONF_SD 0x0100
36#define TMP102_CONF_TM 0x0200
37#define TMP102_CONF_POL 0x0400
38#define TMP102_CONF_F0 0x0800
39#define TMP102_CONF_F1 0x1000
40#define TMP102_CONF_R0 0x2000
41#define TMP102_CONF_R1 0x4000
42#define TMP102_CONF_OS 0x8000
43#define TMP102_CONF_EM 0x0010
44#define TMP102_CONF_AL 0x0020
45#define TMP102_CONF_CR0 0x0040
46#define TMP102_CONF_CR1 0x0080
47#define TMP102_TLOW_REG 0x02
48#define TMP102_THIGH_REG 0x03
49
50struct tmp102 {
51 struct device *hwmon_dev;
52 struct mutex lock;
53 u16 config_orig;
54 unsigned long last_update;
55 int temp[3];
56};
57
58/* SMBus specifies low byte first, but the TMP102 returns high byte first,
59 * so we have to swab16 the values */
60static inline int tmp102_read_reg(struct i2c_client *client, u8 reg)
61{
62 int result = i2c_smbus_read_word_data(client, reg);
63 return result < 0 ? result : swab16(result);
64}
65
66static inline int tmp102_write_reg(struct i2c_client *client, u8 reg, u16 val)
67{
68 return i2c_smbus_write_word_data(client, reg, swab16(val));
69}
70
71/* convert left adjusted 13-bit TMP102 register value to milliCelsius */
72static inline int tmp102_reg_to_mC(s16 val)
73{
74 return ((val & ~0x01) * 1000) / 128;
75}
76
77/* convert milliCelsius to left adjusted 13-bit TMP102 register value */
78static inline u16 tmp102_mC_to_reg(int val)
79{
80 return (val * 128) / 1000;
81}
82
83static const u8 tmp102_reg[] = {
84 TMP102_TEMP_REG,
85 TMP102_TLOW_REG,
86 TMP102_THIGH_REG,
87};
88
89static struct tmp102 *tmp102_update_device(struct i2c_client *client)
90{
91 struct tmp102 *tmp102 = i2c_get_clientdata(client);
92
93 mutex_lock(&tmp102->lock);
94 if (time_after(jiffies, tmp102->last_update + HZ / 3)) {
95 int i;
96 for (i = 0; i < ARRAY_SIZE(tmp102->temp); ++i) {
97 int status = tmp102_read_reg(client, tmp102_reg[i]);
98 if (status > -1)
99 tmp102->temp[i] = tmp102_reg_to_mC(status);
100 }
101 tmp102->last_update = jiffies;
102 }
103 mutex_unlock(&tmp102->lock);
104 return tmp102;
105}
106
107static ssize_t tmp102_show_temp(struct device *dev,
108 struct device_attribute *attr,
109 char *buf)
110{
111 struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
112 struct tmp102 *tmp102 = tmp102_update_device(to_i2c_client(dev));
113
114 return sprintf(buf, "%d\n", tmp102->temp[sda->index]);
115}
116
117static ssize_t tmp102_set_temp(struct device *dev,
118 struct device_attribute *attr,
119 const char *buf, size_t count)
120{
121 struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
122 struct i2c_client *client = to_i2c_client(dev);
123 struct tmp102 *tmp102 = i2c_get_clientdata(client);
124 long val;
125 int status;
126
127 if (strict_strtol(buf, 10, &val) < 0)
128 return -EINVAL;
129 val = SENSORS_LIMIT(val, -256000, 255000);
130
131 mutex_lock(&tmp102->lock);
132 tmp102->temp[sda->index] = val;
133 status = tmp102_write_reg(client, tmp102_reg[sda->index],
134 tmp102_mC_to_reg(val));
135 mutex_unlock(&tmp102->lock);
136 return status ? : count;
137}
138
139static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, tmp102_show_temp, NULL , 0);
140
141static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, tmp102_show_temp,
142 tmp102_set_temp, 1);
143
144static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, tmp102_show_temp,
145 tmp102_set_temp, 2);
146
147static struct attribute *tmp102_attributes[] = {
148 &sensor_dev_attr_temp1_input.dev_attr.attr,
149 &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
150 &sensor_dev_attr_temp1_max.dev_attr.attr,
151 NULL
152};
153
154static const struct attribute_group tmp102_attr_group = {
155 .attrs = tmp102_attributes,
156};
157
158#define TMP102_CONFIG (TMP102_CONF_TM | TMP102_CONF_EM | TMP102_CONF_CR1)
159#define TMP102_CONFIG_RD_ONLY (TMP102_CONF_R0 | TMP102_CONF_R1 | TMP102_CONF_AL)
160
161static int __devinit tmp102_probe(struct i2c_client *client,
162 const struct i2c_device_id *id)
163{
164 struct tmp102 *tmp102;
165 int status;
166
167 if (!i2c_check_functionality(client->adapter,
168 I2C_FUNC_SMBUS_WORD_DATA)) {
169 dev_err(&client->dev, "adapter doesnt support SMBus word "
170 "transactions\n");
171 return -ENODEV;
172 }
173
174 tmp102 = kzalloc(sizeof(*tmp102), GFP_KERNEL);
175 if (!tmp102) {
176 dev_dbg(&client->dev, "kzalloc failed\n");
177 return -ENOMEM;
178 }
179 i2c_set_clientdata(client, tmp102);
180
181 status = tmp102_read_reg(client, TMP102_CONF_REG);
182 if (status < 0) {
183 dev_err(&client->dev, "error reading config register\n");
184 goto fail_free;
185 }
186 tmp102->config_orig = status;
187 status = tmp102_write_reg(client, TMP102_CONF_REG, TMP102_CONFIG);
188 if (status < 0) {
189 dev_err(&client->dev, "error writing config register\n");
190 goto fail_restore_config;
191 }
192 status = tmp102_read_reg(client, TMP102_CONF_REG);
193 if (status < 0) {
194 dev_err(&client->dev, "error reading config register\n");
195 goto fail_restore_config;
196 }
197 status &= ~TMP102_CONFIG_RD_ONLY;
198 if (status != TMP102_CONFIG) {
199 dev_err(&client->dev, "config settings did not stick\n");
200 status = -ENODEV;
201 goto fail_restore_config;
202 }
203 tmp102->last_update = jiffies - HZ;
204 mutex_init(&tmp102->lock);
205
206 status = sysfs_create_group(&client->dev.kobj, &tmp102_attr_group);
207 if (status) {
208 dev_dbg(&client->dev, "could not create sysfs files\n");
209 goto fail_restore_config;
210 }
211 tmp102->hwmon_dev = hwmon_device_register(&client->dev);
212 if (IS_ERR(tmp102->hwmon_dev)) {
213 dev_dbg(&client->dev, "unable to register hwmon device\n");
214 status = PTR_ERR(tmp102->hwmon_dev);
215 goto fail_remove_sysfs;
216 }
217
218 dev_info(&client->dev, "initialized\n");
219
220 return 0;
221
222fail_remove_sysfs:
223 sysfs_remove_group(&client->dev.kobj, &tmp102_attr_group);
224fail_restore_config:
225 tmp102_write_reg(client, TMP102_CONF_REG, tmp102->config_orig);
226fail_free:
227 kfree(tmp102);
228
229 return status;
230}
231
232static int __devexit tmp102_remove(struct i2c_client *client)
233{
234 struct tmp102 *tmp102 = i2c_get_clientdata(client);
235
236 hwmon_device_unregister(tmp102->hwmon_dev);
237 sysfs_remove_group(&client->dev.kobj, &tmp102_attr_group);
238
239 /* Stop monitoring if device was stopped originally */
240 if (tmp102->config_orig & TMP102_CONF_SD) {
241 int config;
242
243 config = tmp102_read_reg(client, TMP102_CONF_REG);
244 if (config >= 0)
245 tmp102_write_reg(client, TMP102_CONF_REG,
246 config | TMP102_CONF_SD);
247 }
248
249 kfree(tmp102);
250
251 return 0;
252}
253
254#ifdef CONFIG_PM
255static int tmp102_suspend(struct device *dev)
256{
257 struct i2c_client *client = to_i2c_client(dev);
258 int config;
259
260 config = tmp102_read_reg(client, TMP102_CONF_REG);
261 if (config < 0)
262 return config;
263
264 config |= TMP102_CONF_SD;
265 return tmp102_write_reg(client, TMP102_CONF_REG, config);
266}
267
268static int tmp102_resume(struct device *dev)
269{
270 struct i2c_client *client = to_i2c_client(dev);
271 int config;
272
273 config = tmp102_read_reg(client, TMP102_CONF_REG);
274 if (config < 0)
275 return config;
276
277 config &= ~TMP102_CONF_SD;
278 return tmp102_write_reg(client, TMP102_CONF_REG, config);
279}
280
281static const struct dev_pm_ops tmp102_dev_pm_ops = {
282 .suspend = tmp102_suspend,
283 .resume = tmp102_resume,
284};
285
286#define TMP102_DEV_PM_OPS (&tmp102_dev_pm_ops)
287#else
288#define TMP102_DEV_PM_OPS NULL
289#endif /* CONFIG_PM */
290
291static const struct i2c_device_id tmp102_id[] = {
292 { "tmp102", 0 },
293 { }
294};
295MODULE_DEVICE_TABLE(i2c, tmp102_id);
296
297static struct i2c_driver tmp102_driver = {
298 .driver.name = DRIVER_NAME,
299 .driver.pm = TMP102_DEV_PM_OPS,
300 .probe = tmp102_probe,
301 .remove = __devexit_p(tmp102_remove),
302 .id_table = tmp102_id,
303};
304
305static int __init tmp102_init(void)
306{
307 return i2c_add_driver(&tmp102_driver);
308}
309module_init(tmp102_init);
310
311static void __exit tmp102_exit(void)
312{
313 i2c_del_driver(&tmp102_driver);
314}
315module_exit(tmp102_exit);
316
317MODULE_AUTHOR("Steven King <sfking@fdwdc.com>");
318MODULE_DESCRIPTION("Texas Instruments TMP102 temperature sensor driver");
319MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/tmp401.c b/drivers/hwmon/tmp401.c
index d14a1af9f550..ad8d535235c5 100644
--- a/drivers/hwmon/tmp401.c
+++ b/drivers/hwmon/tmp401.c
@@ -92,17 +92,6 @@ static const u8 TMP411_TEMP_HIGHEST_LSB[2] = { 0x33, 0x37 };
92#define TMP411_DEVICE_ID 0x12 92#define TMP411_DEVICE_ID 0x12
93 93
94/* 94/*
95 * Functions declarations
96 */
97
98static int tmp401_probe(struct i2c_client *client,
99 const struct i2c_device_id *id);
100static int tmp401_detect(struct i2c_client *client,
101 struct i2c_board_info *info);
102static int tmp401_remove(struct i2c_client *client);
103static struct tmp401_data *tmp401_update_device(struct device *dev);
104
105/*
106 * Driver data (common to all clients) 95 * Driver data (common to all clients)
107 */ 96 */
108 97
@@ -113,18 +102,6 @@ static const struct i2c_device_id tmp401_id[] = {
113}; 102};
114MODULE_DEVICE_TABLE(i2c, tmp401_id); 103MODULE_DEVICE_TABLE(i2c, tmp401_id);
115 104
116static struct i2c_driver tmp401_driver = {
117 .class = I2C_CLASS_HWMON,
118 .driver = {
119 .name = "tmp401",
120 },
121 .probe = tmp401_probe,
122 .remove = tmp401_remove,
123 .id_table = tmp401_id,
124 .detect = tmp401_detect,
125 .address_list = normal_i2c,
126};
127
128/* 105/*
129 * Client data (each client gets its own) 106 * Client data (each client gets its own)
130 */ 107 */
@@ -194,6 +171,71 @@ static u8 tmp401_crit_temp_to_register(long temp, u8 config)
194 return (temp + 500) / 1000; 171 return (temp + 500) / 1000;
195} 172}
196 173
174static struct tmp401_data *tmp401_update_device_reg16(
175 struct i2c_client *client, struct tmp401_data *data)
176{
177 int i;
178
179 for (i = 0; i < 2; i++) {
180 /*
181 * High byte must be read first immediately followed
182 * by the low byte
183 */
184 data->temp[i] = i2c_smbus_read_byte_data(client,
185 TMP401_TEMP_MSB[i]) << 8;
186 data->temp[i] |= i2c_smbus_read_byte_data(client,
187 TMP401_TEMP_LSB[i]);
188 data->temp_low[i] = i2c_smbus_read_byte_data(client,
189 TMP401_TEMP_LOW_LIMIT_MSB_READ[i]) << 8;
190 data->temp_low[i] |= i2c_smbus_read_byte_data(client,
191 TMP401_TEMP_LOW_LIMIT_LSB[i]);
192 data->temp_high[i] = i2c_smbus_read_byte_data(client,
193 TMP401_TEMP_HIGH_LIMIT_MSB_READ[i]) << 8;
194 data->temp_high[i] |= i2c_smbus_read_byte_data(client,
195 TMP401_TEMP_HIGH_LIMIT_LSB[i]);
196 data->temp_crit[i] = i2c_smbus_read_byte_data(client,
197 TMP401_TEMP_CRIT_LIMIT[i]);
198
199 if (data->kind == tmp411) {
200 data->temp_lowest[i] = i2c_smbus_read_byte_data(client,
201 TMP411_TEMP_LOWEST_MSB[i]) << 8;
202 data->temp_lowest[i] |= i2c_smbus_read_byte_data(
203 client, TMP411_TEMP_LOWEST_LSB[i]);
204
205 data->temp_highest[i] = i2c_smbus_read_byte_data(
206 client, TMP411_TEMP_HIGHEST_MSB[i]) << 8;
207 data->temp_highest[i] |= i2c_smbus_read_byte_data(
208 client, TMP411_TEMP_HIGHEST_LSB[i]);
209 }
210 }
211 return data;
212}
213
214static struct tmp401_data *tmp401_update_device(struct device *dev)
215{
216 struct i2c_client *client = to_i2c_client(dev);
217 struct tmp401_data *data = i2c_get_clientdata(client);
218
219 mutex_lock(&data->update_lock);
220
221 if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
222 data->status = i2c_smbus_read_byte_data(client, TMP401_STATUS);
223 data->config = i2c_smbus_read_byte_data(client,
224 TMP401_CONFIG_READ);
225 tmp401_update_device_reg16(client, data);
226
227 data->temp_crit_hyst = i2c_smbus_read_byte_data(client,
228 TMP401_TEMP_CRIT_HYST);
229
230 data->last_updated = jiffies;
231 data->valid = 1;
232 }
233
234 mutex_unlock(&data->update_lock);
235
236 return data;
237}
238
197static ssize_t show_temp_value(struct device *dev, 239static ssize_t show_temp_value(struct device *dev,
198 struct device_attribute *devattr, char *buf) 240 struct device_attribute *devattr, char *buf)
199{ 241{
@@ -420,30 +462,36 @@ static ssize_t reset_temp_history(struct device *dev,
420} 462}
421 463
422static struct sensor_device_attribute tmp401_attr[] = { 464static struct sensor_device_attribute tmp401_attr[] = {
423 SENSOR_ATTR(temp1_input, 0444, show_temp_value, NULL, 0), 465 SENSOR_ATTR(temp1_input, S_IRUGO, show_temp_value, NULL, 0),
424 SENSOR_ATTR(temp1_min, 0644, show_temp_min, store_temp_min, 0), 466 SENSOR_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp_min,
425 SENSOR_ATTR(temp1_max, 0644, show_temp_max, store_temp_max, 0), 467 store_temp_min, 0),
426 SENSOR_ATTR(temp1_crit, 0644, show_temp_crit, store_temp_crit, 0), 468 SENSOR_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
427 SENSOR_ATTR(temp1_crit_hyst, 0644, show_temp_crit_hyst, 469 store_temp_max, 0),
470 SENSOR_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp_crit,
471 store_temp_crit, 0),
472 SENSOR_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temp_crit_hyst,
428 store_temp_crit_hyst, 0), 473 store_temp_crit_hyst, 0),
429 SENSOR_ATTR(temp1_min_alarm, 0444, show_status, NULL, 474 SENSOR_ATTR(temp1_min_alarm, S_IRUGO, show_status, NULL,
430 TMP401_STATUS_LOCAL_LOW), 475 TMP401_STATUS_LOCAL_LOW),
431 SENSOR_ATTR(temp1_max_alarm, 0444, show_status, NULL, 476 SENSOR_ATTR(temp1_max_alarm, S_IRUGO, show_status, NULL,
432 TMP401_STATUS_LOCAL_HIGH), 477 TMP401_STATUS_LOCAL_HIGH),
433 SENSOR_ATTR(temp1_crit_alarm, 0444, show_status, NULL, 478 SENSOR_ATTR(temp1_crit_alarm, S_IRUGO, show_status, NULL,
434 TMP401_STATUS_LOCAL_CRIT), 479 TMP401_STATUS_LOCAL_CRIT),
435 SENSOR_ATTR(temp2_input, 0444, show_temp_value, NULL, 1), 480 SENSOR_ATTR(temp2_input, S_IRUGO, show_temp_value, NULL, 1),
436 SENSOR_ATTR(temp2_min, 0644, show_temp_min, store_temp_min, 1), 481 SENSOR_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp_min,
437 SENSOR_ATTR(temp2_max, 0644, show_temp_max, store_temp_max, 1), 482 store_temp_min, 1),
438 SENSOR_ATTR(temp2_crit, 0644, show_temp_crit, store_temp_crit, 1), 483 SENSOR_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_max,
439 SENSOR_ATTR(temp2_crit_hyst, 0444, show_temp_crit_hyst, NULL, 1), 484 store_temp_max, 1),
440 SENSOR_ATTR(temp2_fault, 0444, show_status, NULL, 485 SENSOR_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_temp_crit,
486 store_temp_crit, 1),
487 SENSOR_ATTR(temp2_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL, 1),
488 SENSOR_ATTR(temp2_fault, S_IRUGO, show_status, NULL,
441 TMP401_STATUS_REMOTE_OPEN), 489 TMP401_STATUS_REMOTE_OPEN),
442 SENSOR_ATTR(temp2_min_alarm, 0444, show_status, NULL, 490 SENSOR_ATTR(temp2_min_alarm, S_IRUGO, show_status, NULL,
443 TMP401_STATUS_REMOTE_LOW), 491 TMP401_STATUS_REMOTE_LOW),
444 SENSOR_ATTR(temp2_max_alarm, 0444, show_status, NULL, 492 SENSOR_ATTR(temp2_max_alarm, S_IRUGO, show_status, NULL,
445 TMP401_STATUS_REMOTE_HIGH), 493 TMP401_STATUS_REMOTE_HIGH),
446 SENSOR_ATTR(temp2_crit_alarm, 0444, show_status, NULL, 494 SENSOR_ATTR(temp2_crit_alarm, S_IRUGO, show_status, NULL,
447 TMP401_STATUS_REMOTE_CRIT), 495 TMP401_STATUS_REMOTE_CRIT),
448}; 496};
449 497
@@ -455,11 +503,11 @@ static struct sensor_device_attribute tmp401_attr[] = {
455 * and remote channels. 503 * and remote channels.
456 */ 504 */
457static struct sensor_device_attribute tmp411_attr[] = { 505static struct sensor_device_attribute tmp411_attr[] = {
458 SENSOR_ATTR(temp1_highest, 0444, show_temp_highest, NULL, 0), 506 SENSOR_ATTR(temp1_highest, S_IRUGO, show_temp_highest, NULL, 0),
459 SENSOR_ATTR(temp1_lowest, 0444, show_temp_lowest, NULL, 0), 507 SENSOR_ATTR(temp1_lowest, S_IRUGO, show_temp_lowest, NULL, 0),
460 SENSOR_ATTR(temp2_highest, 0444, show_temp_highest, NULL, 1), 508 SENSOR_ATTR(temp2_highest, S_IRUGO, show_temp_highest, NULL, 1),
461 SENSOR_ATTR(temp2_lowest, 0444, show_temp_lowest, NULL, 1), 509 SENSOR_ATTR(temp2_lowest, S_IRUGO, show_temp_lowest, NULL, 1),
462 SENSOR_ATTR(temp_reset_history, 0200, NULL, reset_temp_history, 0), 510 SENSOR_ATTR(temp_reset_history, S_IWUSR, NULL, reset_temp_history, 0),
463}; 511};
464 512
465/* 513/*
@@ -529,6 +577,27 @@ static int tmp401_detect(struct i2c_client *client,
529 return 0; 577 return 0;
530} 578}
531 579
580static int tmp401_remove(struct i2c_client *client)
581{
582 struct tmp401_data *data = i2c_get_clientdata(client);
583 int i;
584
585 if (data->hwmon_dev)
586 hwmon_device_unregister(data->hwmon_dev);
587
588 for (i = 0; i < ARRAY_SIZE(tmp401_attr); i++)
589 device_remove_file(&client->dev, &tmp401_attr[i].dev_attr);
590
591 if (data->kind == tmp411) {
592 for (i = 0; i < ARRAY_SIZE(tmp411_attr); i++)
593 device_remove_file(&client->dev,
594 &tmp411_attr[i].dev_attr);
595 }
596
597 kfree(data);
598 return 0;
599}
600
532static int tmp401_probe(struct i2c_client *client, 601static int tmp401_probe(struct i2c_client *client,
533 const struct i2c_device_id *id) 602 const struct i2c_device_id *id)
534{ 603{
@@ -581,91 +650,17 @@ exit_remove:
581 return err; 650 return err;
582} 651}
583 652
584static int tmp401_remove(struct i2c_client *client) 653static struct i2c_driver tmp401_driver = {
585{ 654 .class = I2C_CLASS_HWMON,
586 struct tmp401_data *data = i2c_get_clientdata(client); 655 .driver = {
587 int i; 656 .name = "tmp401",
588 657 },
589 if (data->hwmon_dev) 658 .probe = tmp401_probe,
590 hwmon_device_unregister(data->hwmon_dev); 659 .remove = tmp401_remove,
591 660 .id_table = tmp401_id,
592 for (i = 0; i < ARRAY_SIZE(tmp401_attr); i++) 661 .detect = tmp401_detect,
593 device_remove_file(&client->dev, &tmp401_attr[i].dev_attr); 662 .address_list = normal_i2c,
594 663};
595 if (data->kind == tmp411) {
596 for (i = 0; i < ARRAY_SIZE(tmp411_attr); i++)
597 device_remove_file(&client->dev,
598 &tmp411_attr[i].dev_attr);
599 }
600
601 kfree(data);
602 return 0;
603}
604
605static struct tmp401_data *tmp401_update_device_reg16(
606 struct i2c_client *client, struct tmp401_data *data)
607{
608 int i;
609
610 for (i = 0; i < 2; i++) {
611 /*
612 * High byte must be read first immediately followed
613 * by the low byte
614 */
615 data->temp[i] = i2c_smbus_read_byte_data(client,
616 TMP401_TEMP_MSB[i]) << 8;
617 data->temp[i] |= i2c_smbus_read_byte_data(client,
618 TMP401_TEMP_LSB[i]);
619 data->temp_low[i] = i2c_smbus_read_byte_data(client,
620 TMP401_TEMP_LOW_LIMIT_MSB_READ[i]) << 8;
621 data->temp_low[i] |= i2c_smbus_read_byte_data(client,
622 TMP401_TEMP_LOW_LIMIT_LSB[i]);
623 data->temp_high[i] = i2c_smbus_read_byte_data(client,
624 TMP401_TEMP_HIGH_LIMIT_MSB_READ[i]) << 8;
625 data->temp_high[i] |= i2c_smbus_read_byte_data(client,
626 TMP401_TEMP_HIGH_LIMIT_LSB[i]);
627 data->temp_crit[i] = i2c_smbus_read_byte_data(client,
628 TMP401_TEMP_CRIT_LIMIT[i]);
629
630 if (data->kind == tmp411) {
631 data->temp_lowest[i] = i2c_smbus_read_byte_data(client,
632 TMP411_TEMP_LOWEST_MSB[i]) << 8;
633 data->temp_lowest[i] |= i2c_smbus_read_byte_data(
634 client, TMP411_TEMP_LOWEST_LSB[i]);
635
636 data->temp_highest[i] = i2c_smbus_read_byte_data(
637 client, TMP411_TEMP_HIGHEST_MSB[i]) << 8;
638 data->temp_highest[i] |= i2c_smbus_read_byte_data(
639 client, TMP411_TEMP_HIGHEST_LSB[i]);
640 }
641 }
642 return data;
643}
644
645static struct tmp401_data *tmp401_update_device(struct device *dev)
646{
647 struct i2c_client *client = to_i2c_client(dev);
648 struct tmp401_data *data = i2c_get_clientdata(client);
649
650 mutex_lock(&data->update_lock);
651
652 if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
653 data->status = i2c_smbus_read_byte_data(client, TMP401_STATUS);
654 data->config = i2c_smbus_read_byte_data(client,
655 TMP401_CONFIG_READ);
656 tmp401_update_device_reg16(client, data);
657
658 data->temp_crit_hyst = i2c_smbus_read_byte_data(client,
659 TMP401_TEMP_CRIT_HYST);
660
661 data->last_updated = jiffies;
662 data->valid = 1;
663 }
664
665 mutex_unlock(&data->update_lock);
666
667 return data;
668}
669 664
670static int __init tmp401_init(void) 665static int __init tmp401_init(void)
671{ 666{
diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c
index 738c472ece27..6b4165c12092 100644
--- a/drivers/hwmon/tmp421.c
+++ b/drivers/hwmon/tmp421.c
@@ -295,7 +295,6 @@ exit_remove:
295 sysfs_remove_group(&client->dev.kobj, &tmp421_group); 295 sysfs_remove_group(&client->dev.kobj, &tmp421_group);
296 296
297exit_free: 297exit_free:
298 i2c_set_clientdata(client, NULL);
299 kfree(data); 298 kfree(data);
300 299
301 return err; 300 return err;
@@ -308,7 +307,6 @@ static int tmp421_remove(struct i2c_client *client)
308 hwmon_device_unregister(data->hwmon_dev); 307 hwmon_device_unregister(data->hwmon_dev);
309 sysfs_remove_group(&client->dev.kobj, &tmp421_group); 308 sysfs_remove_group(&client->dev.kobj, &tmp421_group);
310 309
311 i2c_set_clientdata(client, NULL);
312 kfree(data); 310 kfree(data);
313 311
314 return 0; 312 return 0;
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index 32d4adee73db..c84b9b4e6960 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -1197,7 +1197,6 @@ ERROR4:
1197 if (data->lm75[1]) 1197 if (data->lm75[1])
1198 i2c_unregister_device(data->lm75[1]); 1198 i2c_unregister_device(data->lm75[1]);
1199ERROR3: 1199ERROR3:
1200 i2c_set_clientdata(client, NULL);
1201 kfree(data); 1200 kfree(data);
1202ERROR1: 1201ERROR1:
1203 return err; 1202 return err;
@@ -1219,7 +1218,6 @@ w83781d_remove(struct i2c_client *client)
1219 if (data->lm75[1]) 1218 if (data->lm75[1])
1220 i2c_unregister_device(data->lm75[1]); 1219 i2c_unregister_device(data->lm75[1]);
1221 1220
1222 i2c_set_clientdata(client, NULL);
1223 kfree(data); 1221 kfree(data);
1224 1222
1225 return 0; 1223 return 0;
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 87ab0568bb0e..bceafbfa7268 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -475,6 +475,26 @@ config I2C_PASEMI
475 help 475 help
476 Supports the PA Semi PWRficient on-chip SMBus interfaces. 476 Supports the PA Semi PWRficient on-chip SMBus interfaces.
477 477
478config I2C_PCA_PLATFORM
479 tristate "PCA9564/PCA9665 as platform device"
480 select I2C_ALGOPCA
481 default n
482 help
483 This driver supports a memory mapped Philips PCA9564/PCA9665
484 parallel bus to I2C bus controller.
485
486 This driver can also be built as a module. If so, the module
487 will be called i2c-pca-platform.
488
489config I2C_PMCMSP
490 tristate "PMC MSP I2C TWI Controller"
491 depends on PMC_MSP
492 help
493 This driver supports the PMC TWI controller on MSP devices.
494
495 This driver can also be built as module. If so, the module
496 will be called i2c-pmcmsp.
497
478config I2C_PNX 498config I2C_PNX
479 tristate "I2C bus support for Philips PNX targets" 499 tristate "I2C bus support for Philips PNX targets"
480 depends on ARCH_PNX4008 500 depends on ARCH_PNX4008
@@ -711,26 +731,6 @@ config I2C_PCA_ISA
711 delays when I2C/SMBus chip drivers are loaded (e.g. at boot 731 delays when I2C/SMBus chip drivers are loaded (e.g. at boot
712 time). If unsure, say N. 732 time). If unsure, say N.
713 733
714config I2C_PCA_PLATFORM
715 tristate "PCA9564/PCA9665 as platform device"
716 select I2C_ALGOPCA
717 default n
718 help
719 This driver supports a memory mapped Philips PCA9564/PCA9665
720 parallel bus to I2C bus controller.
721
722 This driver can also be built as a module. If so, the module
723 will be called i2c-pca-platform.
724
725config I2C_PMCMSP
726 tristate "PMC MSP I2C TWI Controller"
727 depends on PMC_MSP
728 help
729 This driver supports the PMC TWI controller on MSP devices.
730
731 This driver can also be built as module. If so, the module
732 will be called i2c-pmcmsp.
733
734config I2C_SIBYTE 734config I2C_SIBYTE
735 tristate "SiByte SMBus interface" 735 tristate "SiByte SMBus interface"
736 depends on SIBYTE_SB1xxx_SOC 736 depends on SIBYTE_SB1xxx_SOC
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 097236f631e8..936880bd1dc5 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -27,7 +27,7 @@ obj-$(CONFIG_I2C_VIAPRO) += i2c-viapro.o
27obj-$(CONFIG_I2C_HYDRA) += i2c-hydra.o 27obj-$(CONFIG_I2C_HYDRA) += i2c-hydra.o
28obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o 28obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o
29 29
30# Embebbed system I2C/SMBus host controller drivers 30# Embedded system I2C/SMBus host controller drivers
31obj-$(CONFIG_I2C_AT91) += i2c-at91.o 31obj-$(CONFIG_I2C_AT91) += i2c-at91.o
32obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o 32obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o
33obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o 33obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o
@@ -46,6 +46,8 @@ obj-$(CONFIG_I2C_NOMADIK) += i2c-nomadik.o
46obj-$(CONFIG_I2C_OCORES) += i2c-ocores.o 46obj-$(CONFIG_I2C_OCORES) += i2c-ocores.o
47obj-$(CONFIG_I2C_OMAP) += i2c-omap.o 47obj-$(CONFIG_I2C_OMAP) += i2c-omap.o
48obj-$(CONFIG_I2C_PASEMI) += i2c-pasemi.o 48obj-$(CONFIG_I2C_PASEMI) += i2c-pasemi.o
49obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pca-platform.o
50obj-$(CONFIG_I2C_PMCMSP) += i2c-pmcmsp.o
49obj-$(CONFIG_I2C_PNX) += i2c-pnx.o 51obj-$(CONFIG_I2C_PNX) += i2c-pnx.o
50obj-$(CONFIG_I2C_PXA) += i2c-pxa.o 52obj-$(CONFIG_I2C_PXA) += i2c-pxa.o
51obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o 53obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o
@@ -68,8 +70,6 @@ obj-$(CONFIG_I2C_TINY_USB) += i2c-tiny-usb.o
68obj-$(CONFIG_I2C_ACORN) += i2c-acorn.o 70obj-$(CONFIG_I2C_ACORN) += i2c-acorn.o
69obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o 71obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o
70obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o 72obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o
71obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pca-platform.o
72obj-$(CONFIG_I2C_PMCMSP) += i2c-pmcmsp.o
73obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o 73obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o
74obj-$(CONFIG_I2C_STUB) += i2c-stub.o 74obj-$(CONFIG_I2C_STUB) += i2c-stub.o
75obj-$(CONFIG_SCx200_ACB) += scx200_acb.o 75obj-$(CONFIG_SCx200_ACB) += scx200_acb.o
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index e0f833cca3f1..1cca2631e5b3 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -47,7 +47,6 @@ static DEFINE_MUTEX(core_lock);
47static DEFINE_IDR(i2c_adapter_idr); 47static DEFINE_IDR(i2c_adapter_idr);
48 48
49static struct device_type i2c_client_type; 49static struct device_type i2c_client_type;
50static int i2c_check_addr(struct i2c_adapter *adapter, int addr);
51static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver); 50static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver);
52 51
53/* ------------------------------------------------------------------------- */ 52/* ------------------------------------------------------------------------- */
@@ -371,6 +370,59 @@ struct i2c_client *i2c_verify_client(struct device *dev)
371EXPORT_SYMBOL(i2c_verify_client); 370EXPORT_SYMBOL(i2c_verify_client);
372 371
373 372
373/* This is a permissive address validity check, I2C address map constraints
374 * are purposedly not enforced, except for the general call address. */
375static int i2c_check_client_addr_validity(const struct i2c_client *client)
376{
377 if (client->flags & I2C_CLIENT_TEN) {
378 /* 10-bit address, all values are valid */
379 if (client->addr > 0x3ff)
380 return -EINVAL;
381 } else {
382 /* 7-bit address, reject the general call address */
383 if (client->addr == 0x00 || client->addr > 0x7f)
384 return -EINVAL;
385 }
386 return 0;
387}
388
389/* And this is a strict address validity check, used when probing. If a
390 * device uses a reserved address, then it shouldn't be probed. 7-bit
391 * addressing is assumed, 10-bit address devices are rare and should be
392 * explicitly enumerated. */
393static int i2c_check_addr_validity(unsigned short addr)
394{
395 /*
396 * Reserved addresses per I2C specification:
397 * 0x00 General call address / START byte
398 * 0x01 CBUS address
399 * 0x02 Reserved for different bus format
400 * 0x03 Reserved for future purposes
401 * 0x04-0x07 Hs-mode master code
402 * 0x78-0x7b 10-bit slave addressing
403 * 0x7c-0x7f Reserved for future purposes
404 */
405 if (addr < 0x08 || addr > 0x77)
406 return -EINVAL;
407 return 0;
408}
409
410static int __i2c_check_addr_busy(struct device *dev, void *addrp)
411{
412 struct i2c_client *client = i2c_verify_client(dev);
413 int addr = *(int *)addrp;
414
415 if (client && client->addr == addr)
416 return -EBUSY;
417 return 0;
418}
419
420static int i2c_check_addr_busy(struct i2c_adapter *adapter, int addr)
421{
422 return device_for_each_child(&adapter->dev, &addr,
423 __i2c_check_addr_busy);
424}
425
374/** 426/**
375 * i2c_new_device - instantiate an i2c device 427 * i2c_new_device - instantiate an i2c device
376 * @adap: the adapter managing the device 428 * @adap: the adapter managing the device
@@ -410,8 +462,16 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
410 462
411 strlcpy(client->name, info->type, sizeof(client->name)); 463 strlcpy(client->name, info->type, sizeof(client->name));
412 464
465 /* Check for address validity */
466 status = i2c_check_client_addr_validity(client);
467 if (status) {
468 dev_err(&adap->dev, "Invalid %d-bit I2C address 0x%02hx\n",
469 client->flags & I2C_CLIENT_TEN ? 10 : 7, client->addr);
470 goto out_err_silent;
471 }
472
413 /* Check for address business */ 473 /* Check for address business */
414 status = i2c_check_addr(adap, client->addr); 474 status = i2c_check_addr_busy(adap, client->addr);
415 if (status) 475 if (status)
416 goto out_err; 476 goto out_err;
417 477
@@ -436,6 +496,7 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
436out_err: 496out_err:
437 dev_err(&adap->dev, "Failed to register i2c client %s at 0x%02x " 497 dev_err(&adap->dev, "Failed to register i2c client %s at 0x%02x "
438 "(%d)\n", client->name, client->addr, status); 498 "(%d)\n", client->name, client->addr, status);
499out_err_silent:
439 kfree(client); 500 kfree(client);
440 return NULL; 501 return NULL;
441} 502}
@@ -561,15 +622,9 @@ i2c_sysfs_new_device(struct device *dev, struct device_attribute *attr,
561 return -EINVAL; 622 return -EINVAL;
562 } 623 }
563 624
564 if (info.addr < 0x03 || info.addr > 0x77) {
565 dev_err(dev, "%s: Invalid I2C address 0x%hx\n", "new_device",
566 info.addr);
567 return -EINVAL;
568 }
569
570 client = i2c_new_device(adap, &info); 625 client = i2c_new_device(adap, &info);
571 if (!client) 626 if (!client)
572 return -EEXIST; 627 return -EINVAL;
573 628
574 /* Keep track of the added device */ 629 /* Keep track of the added device */
575 i2c_lock_adapter(adap); 630 i2c_lock_adapter(adap);
@@ -1024,21 +1079,6 @@ EXPORT_SYMBOL(i2c_del_driver);
1024 1079
1025/* ------------------------------------------------------------------------- */ 1080/* ------------------------------------------------------------------------- */
1026 1081
1027static int __i2c_check_addr(struct device *dev, void *addrp)
1028{
1029 struct i2c_client *client = i2c_verify_client(dev);
1030 int addr = *(int *)addrp;
1031
1032 if (client && client->addr == addr)
1033 return -EBUSY;
1034 return 0;
1035}
1036
1037static int i2c_check_addr(struct i2c_adapter *adapter, int addr)
1038{
1039 return device_for_each_child(&adapter->dev, &addr, __i2c_check_addr);
1040}
1041
1042/** 1082/**
1043 * i2c_use_client - increments the reference count of the i2c client structure 1083 * i2c_use_client - increments the reference count of the i2c client structure
1044 * @client: the client being referenced 1084 * @client: the client being referenced
@@ -1277,6 +1317,41 @@ EXPORT_SYMBOL(i2c_master_recv);
1277 * ---------------------------------------------------- 1317 * ----------------------------------------------------
1278 */ 1318 */
1279 1319
1320/*
1321 * Legacy default probe function, mostly relevant for SMBus. The default
1322 * probe method is a quick write, but it is known to corrupt the 24RF08
1323 * EEPROMs due to a state machine bug, and could also irreversibly
1324 * write-protect some EEPROMs, so for address ranges 0x30-0x37 and 0x50-0x5f,
1325 * we use a short byte read instead. Also, some bus drivers don't implement
1326 * quick write, so we fallback to a byte read in that case too.
1327 * On x86, there is another special case for FSC hardware monitoring chips,
1328 * which want regular byte reads (address 0x73.) Fortunately, these are the
1329 * only known chips using this I2C address on PC hardware.
1330 * Returns 1 if probe succeeded, 0 if not.
1331 */
1332static int i2c_default_probe(struct i2c_adapter *adap, unsigned short addr)
1333{
1334 int err;
1335 union i2c_smbus_data dummy;
1336
1337#ifdef CONFIG_X86
1338 if (addr == 0x73 && (adap->class & I2C_CLASS_HWMON)
1339 && i2c_check_functionality(adap, I2C_FUNC_SMBUS_READ_BYTE_DATA))
1340 err = i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_READ, 0,
1341 I2C_SMBUS_BYTE_DATA, &dummy);
1342 else
1343#endif
1344 if ((addr & ~0x07) == 0x30 || (addr & ~0x0f) == 0x50
1345 || !i2c_check_functionality(adap, I2C_FUNC_SMBUS_QUICK))
1346 err = i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_READ, 0,
1347 I2C_SMBUS_BYTE, &dummy);
1348 else
1349 err = i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_WRITE, 0,
1350 I2C_SMBUS_QUICK, NULL);
1351
1352 return err >= 0;
1353}
1354
1280static int i2c_detect_address(struct i2c_client *temp_client, 1355static int i2c_detect_address(struct i2c_client *temp_client,
1281 struct i2c_driver *driver) 1356 struct i2c_driver *driver)
1282{ 1357{
@@ -1286,34 +1361,20 @@ static int i2c_detect_address(struct i2c_client *temp_client,
1286 int err; 1361 int err;
1287 1362
1288 /* Make sure the address is valid */ 1363 /* Make sure the address is valid */
1289 if (addr < 0x03 || addr > 0x77) { 1364 err = i2c_check_addr_validity(addr);
1365 if (err) {
1290 dev_warn(&adapter->dev, "Invalid probe address 0x%02x\n", 1366 dev_warn(&adapter->dev, "Invalid probe address 0x%02x\n",
1291 addr); 1367 addr);
1292 return -EINVAL; 1368 return err;
1293 } 1369 }
1294 1370
1295 /* Skip if already in use */ 1371 /* Skip if already in use */
1296 if (i2c_check_addr(adapter, addr)) 1372 if (i2c_check_addr_busy(adapter, addr))
1297 return 0; 1373 return 0;
1298 1374
1299 /* Make sure there is something at this address */ 1375 /* Make sure there is something at this address */
1300 if (addr == 0x73 && (adapter->class & I2C_CLASS_HWMON)) { 1376 if (!i2c_default_probe(adapter, addr))
1301 /* Special probe for FSC hwmon chips */ 1377 return 0;
1302 union i2c_smbus_data dummy;
1303
1304 if (i2c_smbus_xfer(adapter, addr, 0, I2C_SMBUS_READ, 0,
1305 I2C_SMBUS_BYTE_DATA, &dummy) < 0)
1306 return 0;
1307 } else {
1308 if (i2c_smbus_xfer(adapter, addr, 0, I2C_SMBUS_WRITE, 0,
1309 I2C_SMBUS_QUICK, NULL) < 0)
1310 return 0;
1311
1312 /* Prevent 24RF08 corruption */
1313 if ((addr & ~0x0f) == 0x50)
1314 i2c_smbus_xfer(adapter, addr, 0, I2C_SMBUS_WRITE, 0,
1315 I2C_SMBUS_QUICK, NULL);
1316 }
1317 1378
1318 /* Finally call the custom detection function */ 1379 /* Finally call the custom detection function */
1319 memset(&info, 0, sizeof(struct i2c_board_info)); 1380 memset(&info, 0, sizeof(struct i2c_board_info));
@@ -1407,42 +1468,22 @@ i2c_new_probed_device(struct i2c_adapter *adap,
1407 1468
1408 for (i = 0; addr_list[i] != I2C_CLIENT_END; i++) { 1469 for (i = 0; addr_list[i] != I2C_CLIENT_END; i++) {
1409 /* Check address validity */ 1470 /* Check address validity */
1410 if (addr_list[i] < 0x03 || addr_list[i] > 0x77) { 1471 if (i2c_check_addr_validity(addr_list[i]) < 0) {
1411 dev_warn(&adap->dev, "Invalid 7-bit address " 1472 dev_warn(&adap->dev, "Invalid 7-bit address "
1412 "0x%02x\n", addr_list[i]); 1473 "0x%02x\n", addr_list[i]);
1413 continue; 1474 continue;
1414 } 1475 }
1415 1476
1416 /* Check address availability */ 1477 /* Check address availability */
1417 if (i2c_check_addr(adap, addr_list[i])) { 1478 if (i2c_check_addr_busy(adap, addr_list[i])) {
1418 dev_dbg(&adap->dev, "Address 0x%02x already in " 1479 dev_dbg(&adap->dev, "Address 0x%02x already in "
1419 "use, not probing\n", addr_list[i]); 1480 "use, not probing\n", addr_list[i]);
1420 continue; 1481 continue;
1421 } 1482 }
1422 1483
1423 /* Test address responsiveness 1484 /* Test address responsiveness */
1424 The default probe method is a quick write, but it is known 1485 if (i2c_default_probe(adap, addr_list[i]))
1425 to corrupt the 24RF08 EEPROMs due to a state machine bug, 1486 break;
1426 and could also irreversibly write-protect some EEPROMs, so
1427 for address ranges 0x30-0x37 and 0x50-0x5f, we use a byte
1428 read instead. Also, some bus drivers don't implement
1429 quick write, so we fallback to a byte read it that case
1430 too. */
1431 if ((addr_list[i] & ~0x07) == 0x30
1432 || (addr_list[i] & ~0x0f) == 0x50
1433 || !i2c_check_functionality(adap, I2C_FUNC_SMBUS_QUICK)) {
1434 union i2c_smbus_data data;
1435
1436 if (i2c_smbus_xfer(adap, addr_list[i], 0,
1437 I2C_SMBUS_READ, 0,
1438 I2C_SMBUS_BYTE, &data) >= 0)
1439 break;
1440 } else {
1441 if (i2c_smbus_xfer(adap, addr_list[i], 0,
1442 I2C_SMBUS_WRITE, 0,
1443 I2C_SMBUS_QUICK, NULL) >= 0)
1444 break;
1445 }
1446 } 1487 }
1447 1488
1448 if (addr_list[i] == I2C_CLIENT_END) { 1489 if (addr_list[i] == I2C_CLIENT_END) {
diff --git a/drivers/i2c/i2c-smbus.c b/drivers/i2c/i2c-smbus.c
index a24e0bfe9201..f61ccc1e5ea3 100644
--- a/drivers/i2c/i2c-smbus.c
+++ b/drivers/i2c/i2c-smbus.c
@@ -173,7 +173,6 @@ static int smbalert_remove(struct i2c_client *ara)
173 173
174 cancel_work_sync(&alert->alert); 174 cancel_work_sync(&alert->alert);
175 175
176 i2c_set_clientdata(ara, NULL);
177 kfree(alert); 176 kfree(alert);
178 return 0; 177 return 0;
179} 178}
diff --git a/drivers/ide/gayle.c b/drivers/ide/gayle.c
index b9e517de6a82..3feaa26410be 100644
--- a/drivers/ide/gayle.c
+++ b/drivers/ide/gayle.c
@@ -16,6 +16,7 @@
16#include <linux/init.h> 16#include <linux/init.h>
17#include <linux/zorro.h> 17#include <linux/zorro.h>
18#include <linux/module.h> 18#include <linux/module.h>
19#include <linux/platform_device.h>
19 20
20#include <asm/setup.h> 21#include <asm/setup.h>
21#include <asm/amigahw.h> 22#include <asm/amigahw.h>
@@ -24,15 +25,6 @@
24 25
25 26
26 /* 27 /*
27 * Bases of the IDE interfaces
28 */
29
30#define GAYLE_BASE_4000 0xdd2020 /* A4000/A4000T */
31#define GAYLE_BASE_1200 0xda0000 /* A1200/A600 and E-Matrix 530 */
32
33#define GAYLE_IDEREG_SIZE 0x2000
34
35 /*
36 * Offsets from one of the above bases 28 * Offsets from one of the above bases
37 */ 29 */
38 30
@@ -68,20 +60,20 @@ MODULE_PARM_DESC(doubler, "enable support for IDE doublers");
68 60
69static int gayle_test_irq(ide_hwif_t *hwif) 61static int gayle_test_irq(ide_hwif_t *hwif)
70{ 62{
71 unsigned char ch; 63 unsigned char ch;
72 64
73 ch = z_readb(hwif->io_ports.irq_addr); 65 ch = z_readb(hwif->io_ports.irq_addr);
74 if (!(ch & GAYLE_IRQ_IDE)) 66 if (!(ch & GAYLE_IRQ_IDE))
75 return 0; 67 return 0;
76 return 1; 68 return 1;
77} 69}
78 70
79static void gayle_a1200_clear_irq(ide_drive_t *drive) 71static void gayle_a1200_clear_irq(ide_drive_t *drive)
80{ 72{
81 ide_hwif_t *hwif = drive->hwif; 73 ide_hwif_t *hwif = drive->hwif;
82 74
83 (void)z_readb(hwif->io_ports.status_addr); 75 (void)z_readb(hwif->io_ports.status_addr);
84 z_writeb(0x7c, hwif->io_ports.irq_addr); 76 z_writeb(0x7c, hwif->io_ports.irq_addr);
85} 77}
86 78
87static void __init gayle_setup_ports(struct ide_hw *hw, unsigned long base, 79static void __init gayle_setup_ports(struct ide_hw *hw, unsigned long base,
@@ -122,64 +114,89 @@ static const struct ide_port_info gayle_port_info = {
122 * Probe for a Gayle IDE interface (and optionally for an IDE doubler) 114 * Probe for a Gayle IDE interface (and optionally for an IDE doubler)
123 */ 115 */
124 116
125static int __init gayle_init(void) 117static int __init amiga_gayle_ide_probe(struct platform_device *pdev)
126{ 118{
127 unsigned long phys_base, res_start, res_n; 119 struct resource *res;
128 unsigned long base, ctrlport, irqport; 120 struct gayle_ide_platform_data *pdata;
129 int a4000, i, rc; 121 unsigned long base, ctrlport, irqport;
130 struct ide_hw hw[GAYLE_NUM_HWIFS], *hws[GAYLE_NUM_HWIFS]; 122 unsigned int i;
131 struct ide_port_info d = gayle_port_info; 123 int error;
132 124 struct ide_hw hw[GAYLE_NUM_HWIFS], *hws[GAYLE_NUM_HWIFS];
133 if (!MACH_IS_AMIGA) 125 struct ide_port_info d = gayle_port_info;
134 return -ENODEV; 126 struct ide_host *host;
135 127
136 if ((a4000 = AMIGAHW_PRESENT(A4000_IDE)) || AMIGAHW_PRESENT(A1200_IDE)) 128 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
137 goto found; 129 if (!res)
138 130 return -ENODEV;
139#ifdef CONFIG_ZORRO 131
140 if (zorro_find_device(ZORRO_PROD_MTEC_VIPER_MK_V_E_MATRIX_530_SCSI_IDE, 132 if (!request_mem_region(res->start, resource_size(res), "IDE"))
141 NULL)) 133 return -EBUSY;
142 goto found; 134
143#endif 135 pdata = pdev->dev.platform_data;
144 return -ENODEV; 136 pr_info("ide: Gayle IDE controller (A%u style%s)\n",
145 137 pdata->explicit_ack ? 1200 : 4000,
146found: 138 ide_doubler ? ", IDE doubler" : "");
147 printk(KERN_INFO "ide: Gayle IDE controller (A%d style%s)\n", 139
148 a4000 ? 4000 : 1200, 140 base = (unsigned long)ZTWO_VADDR(pdata->base);
149 ide_doubler ? ", IDE doubler" : ""); 141 ctrlport = 0;
150 142 irqport = (unsigned long)ZTWO_VADDR(pdata->irqport);
151 if (a4000) { 143 if (pdata->explicit_ack)
152 phys_base = GAYLE_BASE_4000; 144 d.port_ops = &gayle_a1200_port_ops;
153 irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_4000); 145 else
154 d.port_ops = &gayle_a4000_port_ops; 146 d.port_ops = &gayle_a4000_port_ops;
155 } else { 147
156 phys_base = GAYLE_BASE_1200; 148 for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++, base += GAYLE_NEXT_PORT) {
157 irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_1200); 149 if (GAYLE_HAS_CONTROL_REG)
158 d.port_ops = &gayle_a1200_port_ops; 150 ctrlport = base + GAYLE_CONTROL;
151
152 gayle_setup_ports(&hw[i], base, ctrlport, irqport);
153 hws[i] = &hw[i];
159 } 154 }
160 155
161 res_start = ((unsigned long)phys_base) & ~(GAYLE_NEXT_PORT-1); 156 error = ide_host_add(&d, hws, i, &host);
162 res_n = GAYLE_IDEREG_SIZE; 157 if (error)
158 goto out;
163 159
164 if (!request_mem_region(res_start, res_n, "IDE")) 160 platform_set_drvdata(pdev, host);
165 return -EBUSY; 161 return 0;
166 162
167 for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) { 163out:
168 base = (unsigned long)ZTWO_VADDR(phys_base + i * GAYLE_NEXT_PORT); 164 release_mem_region(res->start, resource_size(res));
169 ctrlport = GAYLE_HAS_CONTROL_REG ? (base + GAYLE_CONTROL) : 0; 165 return error;
166}
167
168static int __exit amiga_gayle_ide_remove(struct platform_device *pdev)
169{
170 struct ide_host *host = platform_get_drvdata(pdev);
171 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
172
173 ide_host_remove(host);
174 release_mem_region(res->start, resource_size(res));
175 return 0;
176}
170 177
171 gayle_setup_ports(&hw[i], base, ctrlport, irqport); 178static struct platform_driver amiga_gayle_ide_driver = {
179 .remove = __exit_p(amiga_gayle_ide_remove),
180 .driver = {
181 .name = "amiga-gayle-ide",
182 .owner = THIS_MODULE,
183 },
184};
172 185
173 hws[i] = &hw[i]; 186static int __init amiga_gayle_ide_init(void)
174 } 187{
188 return platform_driver_probe(&amiga_gayle_ide_driver,
189 amiga_gayle_ide_probe);
190}
175 191
176 rc = ide_host_add(&d, hws, i, NULL); 192module_init(amiga_gayle_ide_init);
177 if (rc)
178 release_mem_region(res_start, res_n);
179 193
180 return rc; 194static void __exit amiga_gayle_ide_exit(void)
195{
196 platform_driver_unregister(&amiga_gayle_ide_driver);
181} 197}
182 198
183module_init(gayle_init); 199module_exit(amiga_gayle_ide_exit);
184 200
185MODULE_LICENSE("GPL"); 201MODULE_LICENSE("GPL");
202MODULE_ALIAS("platform:amiga-gayle-ide");
diff --git a/drivers/ide/pmac.c b/drivers/ide/pmac.c
index 183fa38760d8..ebcf8e470a97 100644
--- a/drivers/ide/pmac.c
+++ b/drivers/ide/pmac.c
@@ -1400,8 +1400,11 @@ static struct of_device_id pmac_ide_macio_match[] =
1400 1400
1401static struct macio_driver pmac_ide_macio_driver = 1401static struct macio_driver pmac_ide_macio_driver =
1402{ 1402{
1403 .name = "ide-pmac", 1403 .driver = {
1404 .match_table = pmac_ide_macio_match, 1404 .name = "ide-pmac",
1405 .owner = THIS_MODULE,
1406 .of_match_table = pmac_ide_macio_match,
1407 },
1405 .probe = pmac_ide_macio_attach, 1408 .probe = pmac_ide_macio_attach,
1406 .suspend = pmac_ide_macio_suspend, 1409 .suspend = pmac_ide_macio_suspend,
1407 .resume = pmac_ide_macio_resume, 1410 .resume = pmac_ide_macio_resume,
diff --git a/drivers/idle/Kconfig b/drivers/idle/Kconfig
index f15e90a453d1..fb5c5186d4aa 100644
--- a/drivers/idle/Kconfig
+++ b/drivers/idle/Kconfig
@@ -1,3 +1,14 @@
1config INTEL_IDLE
2 tristate "Cpuidle Driver for Intel Processors"
3 depends on CPU_IDLE
4 depends on X86
5 depends on CPU_SUP_INTEL
6 depends on EXPERIMENTAL
7 help
8 Enable intel_idle, a cpuidle driver that includes knowledge of
9 native Intel hardware idle features. The acpi_idle driver
10 can be configured at the same time, in order to handle
11 processors intel_idle does not support.
1 12
2menu "Memory power savings" 13menu "Memory power savings"
3depends on X86_64 14depends on X86_64
diff --git a/drivers/idle/Makefile b/drivers/idle/Makefile
index 5f68fc377e21..23d295cf10f2 100644
--- a/drivers/idle/Makefile
+++ b/drivers/idle/Makefile
@@ -1,2 +1,3 @@
1obj-$(CONFIG_I7300_IDLE) += i7300_idle.o 1obj-$(CONFIG_I7300_IDLE) += i7300_idle.o
2obj-$(CONFIG_INTEL_IDLE) += intel_idle.o
2 3
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
new file mode 100755
index 000000000000..54f0fb4cd5d2
--- /dev/null
+++ b/drivers/idle/intel_idle.c
@@ -0,0 +1,461 @@
1/*
2 * intel_idle.c - native hardware idle loop for modern Intel processors
3 *
4 * Copyright (c) 2010, Intel Corporation.
5 * Len Brown <len.brown@intel.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21/*
22 * intel_idle is a cpuidle driver that loads on specific Intel processors
23 * in lieu of the legacy ACPI processor_idle driver. The intent is to
24 * make Linux more efficient on these processors, as intel_idle knows
25 * more than ACPI, as well as make Linux more immune to ACPI BIOS bugs.
26 */
27
28/*
29 * Design Assumptions
30 *
31 * All CPUs have same idle states as boot CPU
32 *
33 * Chipset BM_STS (bus master status) bit is a NOP
34 * for preventing entry into deep C-stats
35 */
36
37/*
38 * Known limitations
39 *
40 * The driver currently initializes for_each_online_cpu() upon modprobe.
41 * It it unaware of subsequent processors hot-added to the system.
42 * This means that if you boot with maxcpus=n and later online
43 * processors above n, those processors will use C1 only.
44 *
45 * ACPI has a .suspend hack to turn off deep c-statees during suspend
46 * to avoid complications with the lapic timer workaround.
47 * Have not seen issues with suspend, but may need same workaround here.
48 *
49 * There is currently no kernel-based automatic probing/loading mechanism
50 * if the driver is built as a module.
51 */
52
53/* un-comment DEBUG to enable pr_debug() statements */
54#define DEBUG
55
56#include <linux/kernel.h>
57#include <linux/cpuidle.h>
58#include <linux/clockchips.h>
59#include <linux/hrtimer.h> /* ktime_get_real() */
60#include <trace/events/power.h>
61#include <linux/sched.h>
62
63#define INTEL_IDLE_VERSION "0.4"
64#define PREFIX "intel_idle: "
65
66#define MWAIT_SUBSTATE_MASK (0xf)
67#define MWAIT_CSTATE_MASK (0xf)
68#define MWAIT_SUBSTATE_SIZE (4)
69#define MWAIT_MAX_NUM_CSTATES 8
70#define CPUID_MWAIT_LEAF (5)
71#define CPUID5_ECX_EXTENSIONS_SUPPORTED (0x1)
72#define CPUID5_ECX_INTERRUPT_BREAK (0x2)
73
74static struct cpuidle_driver intel_idle_driver = {
75 .name = "intel_idle",
76 .owner = THIS_MODULE,
77};
78/* intel_idle.max_cstate=0 disables driver */
79static int max_cstate = MWAIT_MAX_NUM_CSTATES - 1;
80static int power_policy = 7; /* 0 = max perf; 15 = max powersave */
81
82static unsigned int substates;
83static int (*choose_substate)(int);
84
85/* Reliable LAPIC Timer States, bit 1 for C1 etc. */
86static unsigned int lapic_timer_reliable_states;
87
88static struct cpuidle_device *intel_idle_cpuidle_devices;
89static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state);
90
91static struct cpuidle_state *cpuidle_state_table;
92
93/*
94 * States are indexed by the cstate number,
95 * which is also the index into the MWAIT hint array.
96 * Thus C0 is a dummy.
97 */
98static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = {
99 { /* MWAIT C0 */ },
100 { /* MWAIT C1 */
101 .name = "NHM-C1",
102 .desc = "MWAIT 0x00",
103 .driver_data = (void *) 0x00,
104 .flags = CPUIDLE_FLAG_TIME_VALID,
105 .exit_latency = 3,
106 .power_usage = 1000,
107 .target_residency = 6,
108 .enter = &intel_idle },
109 { /* MWAIT C2 */
110 .name = "NHM-C3",
111 .desc = "MWAIT 0x10",
112 .driver_data = (void *) 0x10,
113 .flags = CPUIDLE_FLAG_TIME_VALID,
114 .exit_latency = 20,
115 .power_usage = 500,
116 .target_residency = 80,
117 .enter = &intel_idle },
118 { /* MWAIT C3 */
119 .name = "NHM-C6",
120 .desc = "MWAIT 0x20",
121 .driver_data = (void *) 0x20,
122 .flags = CPUIDLE_FLAG_TIME_VALID,
123 .exit_latency = 200,
124 .power_usage = 350,
125 .target_residency = 800,
126 .enter = &intel_idle },
127};
128
129static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
130 { /* MWAIT C0 */ },
131 { /* MWAIT C1 */
132 .name = "ATM-C1",
133 .desc = "MWAIT 0x00",
134 .driver_data = (void *) 0x00,
135 .flags = CPUIDLE_FLAG_TIME_VALID,
136 .exit_latency = 1,
137 .power_usage = 1000,
138 .target_residency = 4,
139 .enter = &intel_idle },
140 { /* MWAIT C2 */
141 .name = "ATM-C2",
142 .desc = "MWAIT 0x10",
143 .driver_data = (void *) 0x10,
144 .flags = CPUIDLE_FLAG_TIME_VALID,
145 .exit_latency = 20,
146 .power_usage = 500,
147 .target_residency = 80,
148 .enter = &intel_idle },
149 { /* MWAIT C3 */ },
150 { /* MWAIT C4 */
151 .name = "ATM-C4",
152 .desc = "MWAIT 0x30",
153 .driver_data = (void *) 0x30,
154 .flags = CPUIDLE_FLAG_TIME_VALID,
155 .exit_latency = 100,
156 .power_usage = 250,
157 .target_residency = 400,
158 .enter = &intel_idle },
159 { /* MWAIT C5 */ },
160 { /* MWAIT C6 */
161 .name = "ATM-C6",
162 .desc = "MWAIT 0x40",
163 .driver_data = (void *) 0x40,
164 .flags = CPUIDLE_FLAG_TIME_VALID,
165 .exit_latency = 200,
166 .power_usage = 150,
167 .target_residency = 800,
168 .enter = NULL }, /* disabled */
169};
170
171/*
172 * choose_tunable_substate()
173 *
174 * Run-time decision on which C-state substate to invoke
175 * If power_policy = 0, choose shallowest substate (0)
176 * If power_policy = 15, choose deepest substate
177 * If power_policy = middle, choose middle substate etc.
178 */
179static int choose_tunable_substate(int cstate)
180{
181 unsigned int num_substates;
182 unsigned int substate_choice;
183
184 power_policy &= 0xF; /* valid range: 0-15 */
185 cstate &= 7; /* valid range: 0-7 */
186
187 num_substates = (substates >> ((cstate) * 4)) & MWAIT_SUBSTATE_MASK;
188
189 if (num_substates <= 1)
190 return 0;
191
192 substate_choice = ((power_policy + (power_policy + 1) *
193 (num_substates - 1)) / 16);
194
195 return substate_choice;
196}
197
198/*
199 * choose_zero_substate()
200 */
201static int choose_zero_substate(int cstate)
202{
203 return 0;
204}
205
206/**
207 * intel_idle
208 * @dev: cpuidle_device
209 * @state: cpuidle state
210 *
211 */
212static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state)
213{
214 unsigned long ecx = 1; /* break on interrupt flag */
215 unsigned long eax = (unsigned long)cpuidle_get_statedata(state);
216 unsigned int cstate;
217 ktime_t kt_before, kt_after;
218 s64 usec_delta;
219 int cpu = smp_processor_id();
220
221 cstate = (((eax) >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK) + 1;
222
223 eax = eax + (choose_substate)(cstate);
224
225 local_irq_disable();
226
227 if (!(lapic_timer_reliable_states & (1 << (cstate))))
228 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
229
230 kt_before = ktime_get_real();
231
232 stop_critical_timings();
233#ifndef MODULE
234 trace_power_start(POWER_CSTATE, (eax >> 4) + 1);
235#endif
236 if (!need_resched()) {
237
238 __monitor((void *)&current_thread_info()->flags, 0, 0);
239 smp_mb();
240 if (!need_resched())
241 __mwait(eax, ecx);
242 }
243
244 start_critical_timings();
245
246 kt_after = ktime_get_real();
247 usec_delta = ktime_to_us(ktime_sub(kt_after, kt_before));
248
249 local_irq_enable();
250
251 if (!(lapic_timer_reliable_states & (1 << (cstate))))
252 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
253
254 return usec_delta;
255}
256
257/*
258 * intel_idle_probe()
259 */
260static int intel_idle_probe(void)
261{
262 unsigned int eax, ebx, ecx, edx;
263
264 if (max_cstate == 0) {
265 pr_debug(PREFIX "disabled\n");
266 return -EPERM;
267 }
268
269 if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
270 return -ENODEV;
271
272 if (!boot_cpu_has(X86_FEATURE_MWAIT))
273 return -ENODEV;
274
275 if (boot_cpu_data.cpuid_level < CPUID_MWAIT_LEAF)
276 return -ENODEV;
277
278 cpuid(CPUID_MWAIT_LEAF, &eax, &ebx, &ecx, &edx);
279
280 if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED) ||
281 !(ecx & CPUID5_ECX_INTERRUPT_BREAK))
282 return -ENODEV;
283#ifdef DEBUG
284 if (substates == 0) /* can over-ride via modparam */
285#endif
286 substates = edx;
287
288 pr_debug(PREFIX "MWAIT substates: 0x%x\n", substates);
289
290 if (boot_cpu_has(X86_FEATURE_ARAT)) /* Always Reliable APIC Timer */
291 lapic_timer_reliable_states = 0xFFFFFFFF;
292
293 if (boot_cpu_data.x86 != 6) /* family 6 */
294 return -ENODEV;
295
296 switch (boot_cpu_data.x86_model) {
297
298 case 0x1A: /* Core i7, Xeon 5500 series */
299 case 0x1E: /* Core i7 and i5 Processor - Lynnfield Jasper Forest */
300 case 0x1F: /* Core i7 and i5 Processor - Nehalem */
301 case 0x2E: /* Nehalem-EX Xeon */
302 lapic_timer_reliable_states = (1 << 1); /* C1 */
303
304 case 0x25: /* Westmere */
305 case 0x2C: /* Westmere */
306 cpuidle_state_table = nehalem_cstates;
307 choose_substate = choose_tunable_substate;
308 break;
309
310 case 0x1C: /* 28 - Atom Processor */
311 lapic_timer_reliable_states = (1 << 2) | (1 << 1); /* C2, C1 */
312 cpuidle_state_table = atom_cstates;
313 choose_substate = choose_zero_substate;
314 break;
315#ifdef FUTURE_USE
316 case 0x17: /* 23 - Core 2 Duo */
317 lapic_timer_reliable_states = (1 << 2) | (1 << 1); /* C2, C1 */
318#endif
319
320 default:
321 pr_debug(PREFIX "does not run on family %d model %d\n",
322 boot_cpu_data.x86, boot_cpu_data.x86_model);
323 return -ENODEV;
324 }
325
326 pr_debug(PREFIX "v" INTEL_IDLE_VERSION
327 " model 0x%X\n", boot_cpu_data.x86_model);
328
329 pr_debug(PREFIX "lapic_timer_reliable_states 0x%x\n",
330 lapic_timer_reliable_states);
331 return 0;
332}
333
334/*
335 * intel_idle_cpuidle_devices_uninit()
336 * unregister, free cpuidle_devices
337 */
338static void intel_idle_cpuidle_devices_uninit(void)
339{
340 int i;
341 struct cpuidle_device *dev;
342
343 for_each_online_cpu(i) {
344 dev = per_cpu_ptr(intel_idle_cpuidle_devices, i);
345 cpuidle_unregister_device(dev);
346 }
347
348 free_percpu(intel_idle_cpuidle_devices);
349 return;
350}
351/*
352 * intel_idle_cpuidle_devices_init()
353 * allocate, initialize, register cpuidle_devices
354 */
355static int intel_idle_cpuidle_devices_init(void)
356{
357 int i, cstate;
358 struct cpuidle_device *dev;
359
360 intel_idle_cpuidle_devices = alloc_percpu(struct cpuidle_device);
361 if (intel_idle_cpuidle_devices == NULL)
362 return -ENOMEM;
363
364 for_each_online_cpu(i) {
365 dev = per_cpu_ptr(intel_idle_cpuidle_devices, i);
366
367 dev->state_count = 1;
368
369 for (cstate = 1; cstate < MWAIT_MAX_NUM_CSTATES; ++cstate) {
370 int num_substates;
371
372 if (cstate > max_cstate) {
373 printk(PREFIX "max_cstate %d reached\n",
374 max_cstate);
375 break;
376 }
377
378 /* does the state exist in CPUID.MWAIT? */
379 num_substates = (substates >> ((cstate) * 4))
380 & MWAIT_SUBSTATE_MASK;
381 if (num_substates == 0)
382 continue;
383 /* is the state not enabled? */
384 if (cpuidle_state_table[cstate].enter == NULL) {
385 /* does the driver not know about the state? */
386 if (*cpuidle_state_table[cstate].name == '\0')
387 pr_debug(PREFIX "unaware of model 0x%x"
388 " MWAIT %d please"
389 " contact lenb@kernel.org",
390 boot_cpu_data.x86_model, cstate);
391 continue;
392 }
393
394 if ((cstate > 2) &&
395 !boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
396 mark_tsc_unstable("TSC halts in idle"
397 " states deeper than C2");
398
399 dev->states[dev->state_count] = /* structure copy */
400 cpuidle_state_table[cstate];
401
402 dev->state_count += 1;
403 }
404
405 dev->cpu = i;
406 if (cpuidle_register_device(dev)) {
407 pr_debug(PREFIX "cpuidle_register_device %d failed!\n",
408 i);
409 intel_idle_cpuidle_devices_uninit();
410 return -EIO;
411 }
412 }
413
414 return 0;
415}
416
417
418static int __init intel_idle_init(void)
419{
420 int retval;
421
422 retval = intel_idle_probe();
423 if (retval)
424 return retval;
425
426 retval = cpuidle_register_driver(&intel_idle_driver);
427 if (retval) {
428 printk(KERN_DEBUG PREFIX "intel_idle yielding to %s",
429 cpuidle_get_driver()->name);
430 return retval;
431 }
432
433 retval = intel_idle_cpuidle_devices_init();
434 if (retval) {
435 cpuidle_unregister_driver(&intel_idle_driver);
436 return retval;
437 }
438
439 return 0;
440}
441
442static void __exit intel_idle_exit(void)
443{
444 intel_idle_cpuidle_devices_uninit();
445 cpuidle_unregister_driver(&intel_idle_driver);
446
447 return;
448}
449
450module_init(intel_idle_init);
451module_exit(intel_idle_exit);
452
453module_param(power_policy, int, 0644);
454module_param(max_cstate, int, 0444);
455#ifdef DEBUG
456module_param(substates, int, 0444);
457#endif
458
459MODULE_AUTHOR("Len Brown <len.brown@intel.com>");
460MODULE_DESCRIPTION("Cpuidle driver for Intel Hardware v" INTEL_IDLE_VERSION);
461MODULE_LICENSE("GPL");
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
index 9fd4a0d3206e..adaefabc40e9 100644
--- a/drivers/ieee1394/dv1394.c
+++ b/drivers/ieee1394/dv1394.c
@@ -1824,7 +1824,7 @@ static int dv1394_open(struct inode *inode, struct file *file)
1824 "and will not be available in the new firewire driver stack. " 1824 "and will not be available in the new firewire driver stack. "
1825 "Try libraw1394 based programs instead.\n", current->comm); 1825 "Try libraw1394 based programs instead.\n", current->comm);
1826 1826
1827 return 0; 1827 return nonseekable_open(inode, file);
1828} 1828}
1829 1829
1830 1830
@@ -2153,17 +2153,18 @@ static struct cdev dv1394_cdev;
2153static const struct file_operations dv1394_fops= 2153static const struct file_operations dv1394_fops=
2154{ 2154{
2155 .owner = THIS_MODULE, 2155 .owner = THIS_MODULE,
2156 .poll = dv1394_poll, 2156 .poll = dv1394_poll,
2157 .unlocked_ioctl = dv1394_ioctl, 2157 .unlocked_ioctl = dv1394_ioctl,
2158#ifdef CONFIG_COMPAT 2158#ifdef CONFIG_COMPAT
2159 .compat_ioctl = dv1394_compat_ioctl, 2159 .compat_ioctl = dv1394_compat_ioctl,
2160#endif 2160#endif
2161 .mmap = dv1394_mmap, 2161 .mmap = dv1394_mmap,
2162 .open = dv1394_open, 2162 .open = dv1394_open,
2163 .write = dv1394_write, 2163 .write = dv1394_write,
2164 .read = dv1394_read, 2164 .read = dv1394_read,
2165 .release = dv1394_release, 2165 .release = dv1394_release,
2166 .fasync = dv1394_fasync, 2166 .fasync = dv1394_fasync,
2167 .llseek = no_llseek,
2167}; 2168};
2168 2169
2169 2170
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
index 8aa56ac07e29..b563d5e9fa2e 100644
--- a/drivers/ieee1394/raw1394.c
+++ b/drivers/ieee1394/raw1394.c
@@ -2834,7 +2834,7 @@ static int raw1394_open(struct inode *inode, struct file *file)
2834 2834
2835 file->private_data = fi; 2835 file->private_data = fi;
2836 2836
2837 return 0; 2837 return nonseekable_open(inode, file);
2838} 2838}
2839 2839
2840static int raw1394_release(struct inode *inode, struct file *file) 2840static int raw1394_release(struct inode *inode, struct file *file)
@@ -3035,6 +3035,7 @@ static const struct file_operations raw1394_fops = {
3035 .poll = raw1394_poll, 3035 .poll = raw1394_poll,
3036 .open = raw1394_open, 3036 .open = raw1394_open,
3037 .release = raw1394_release, 3037 .release = raw1394_release,
3038 .llseek = no_llseek,
3038}; 3039};
3039 3040
3040static int __init init_raw1394(void) 3041static int __init init_raw1394(void)
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
index 949064a05675..a42bd6893bcf 100644
--- a/drivers/ieee1394/video1394.c
+++ b/drivers/ieee1394/video1394.c
@@ -1239,7 +1239,7 @@ static int video1394_open(struct inode *inode, struct file *file)
1239 ctx->current_ctx = NULL; 1239 ctx->current_ctx = NULL;
1240 file->private_data = ctx; 1240 file->private_data = ctx;
1241 1241
1242 return 0; 1242 return nonseekable_open(inode, file);
1243} 1243}
1244 1244
1245static int video1394_release(struct inode *inode, struct file *file) 1245static int video1394_release(struct inode *inode, struct file *file)
@@ -1287,7 +1287,8 @@ static const struct file_operations video1394_fops=
1287 .poll = video1394_poll, 1287 .poll = video1394_poll,
1288 .mmap = video1394_mmap, 1288 .mmap = video1394_mmap,
1289 .open = video1394_open, 1289 .open = video1394_open,
1290 .release = video1394_release 1290 .release = video1394_release,
1291 .llseek = no_llseek,
1291}; 1292};
1292 1293
1293/*** HOTPLUG STUFF **********************************************************/ 1294/*** HOTPLUG STUFF **********************************************************/
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
index 46474842cfe9..08f948df8fa9 100644
--- a/drivers/infiniband/core/ucm.c
+++ b/drivers/infiniband/core/ucm.c
@@ -706,14 +706,9 @@ static int ib_ucm_alloc_data(const void **dest, u64 src, u32 len)
706 if (!len) 706 if (!len)
707 return 0; 707 return 0;
708 708
709 data = kmalloc(len, GFP_KERNEL); 709 data = memdup_user((void __user *)(unsigned long)src, len);
710 if (!data) 710 if (IS_ERR(data))
711 return -ENOMEM; 711 return PTR_ERR(data);
712
713 if (copy_from_user(data, (void __user *)(unsigned long)src, len)) {
714 kfree(data);
715 return -EFAULT;
716 }
717 712
718 *dest = data; 713 *dest = data;
719 return 0; 714 return 0;
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c
index 07cae552cafb..e571e60ecb88 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.c
+++ b/drivers/infiniband/hw/ehca/ehca_irq.c
@@ -847,7 +847,7 @@ static int __cpuinit comp_pool_callback(struct notifier_block *nfb,
847 ehca_gen_dbg("CPU: %x (CPU_PREPARE)", cpu); 847 ehca_gen_dbg("CPU: %x (CPU_PREPARE)", cpu);
848 if (!create_comp_task(pool, cpu)) { 848 if (!create_comp_task(pool, cpu)) {
849 ehca_gen_err("Can't create comp_task for cpu: %x", cpu); 849 ehca_gen_err("Can't create comp_task for cpu: %x", cpu);
850 return NOTIFY_BAD; 850 return notifier_from_errno(-ENOMEM);
851 } 851 }
852 break; 852 break;
853 case CPU_UP_CANCELED: 853 case CPU_UP_CANCELED:
diff --git a/drivers/infiniband/hw/qib/qib_fs.c b/drivers/infiniband/hw/qib/qib_fs.c
index 755470440ef1..844954bf417b 100644
--- a/drivers/infiniband/hw/qib/qib_fs.c
+++ b/drivers/infiniband/hw/qib/qib_fs.c
@@ -144,10 +144,11 @@ static ssize_t dev_counters_read(struct file *file, char __user *buf,
144 size_t count, loff_t *ppos) 144 size_t count, loff_t *ppos)
145{ 145{
146 u64 *counters; 146 u64 *counters;
147 size_t avail;
147 struct qib_devdata *dd = private2dd(file); 148 struct qib_devdata *dd = private2dd(file);
148 149
149 return simple_read_from_buffer(buf, count, ppos, counters, 150 avail = dd->f_read_cntrs(dd, *ppos, NULL, &counters);
150 dd->f_read_cntrs(dd, *ppos, NULL, &counters)); 151 return simple_read_from_buffer(buf, count, ppos, counters, avail);
151} 152}
152 153
153/* read the per-device counters */ 154/* read the per-device counters */
@@ -155,10 +156,11 @@ static ssize_t dev_names_read(struct file *file, char __user *buf,
155 size_t count, loff_t *ppos) 156 size_t count, loff_t *ppos)
156{ 157{
157 char *names; 158 char *names;
159 size_t avail;
158 struct qib_devdata *dd = private2dd(file); 160 struct qib_devdata *dd = private2dd(file);
159 161
160 return simple_read_from_buffer(buf, count, ppos, names, 162 avail = dd->f_read_cntrs(dd, *ppos, &names, NULL);
161 dd->f_read_cntrs(dd, *ppos, &names, NULL)); 163 return simple_read_from_buffer(buf, count, ppos, names, avail);
162} 164}
163 165
164static const struct file_operations cntr_ops[] = { 166static const struct file_operations cntr_ops[] = {
@@ -176,10 +178,11 @@ static ssize_t portnames_read(struct file *file, char __user *buf,
176 size_t count, loff_t *ppos) 178 size_t count, loff_t *ppos)
177{ 179{
178 char *names; 180 char *names;
181 size_t avail;
179 struct qib_devdata *dd = private2dd(file); 182 struct qib_devdata *dd = private2dd(file);
180 183
181 return simple_read_from_buffer(buf, count, ppos, names, 184 avail = dd->f_read_portcntrs(dd, *ppos, 0, &names, NULL);
182 dd->f_read_portcntrs(dd, *ppos, 0, &names, NULL)); 185 return simple_read_from_buffer(buf, count, ppos, names, avail);
183} 186}
184 187
185/* read the per-port counters for port 1 (pidx 0) */ 188/* read the per-port counters for port 1 (pidx 0) */
@@ -187,10 +190,11 @@ static ssize_t portcntrs_1_read(struct file *file, char __user *buf,
187 size_t count, loff_t *ppos) 190 size_t count, loff_t *ppos)
188{ 191{
189 u64 *counters; 192 u64 *counters;
193 size_t avail;
190 struct qib_devdata *dd = private2dd(file); 194 struct qib_devdata *dd = private2dd(file);
191 195
192 return simple_read_from_buffer(buf, count, ppos, counters, 196 avail = dd->f_read_portcntrs(dd, *ppos, 0, NULL, &counters);
193 dd->f_read_portcntrs(dd, *ppos, 0, NULL, &counters)); 197 return simple_read_from_buffer(buf, count, ppos, counters, avail);
194} 198}
195 199
196/* read the per-port counters for port 2 (pidx 1) */ 200/* read the per-port counters for port 2 (pidx 1) */
@@ -198,10 +202,11 @@ static ssize_t portcntrs_2_read(struct file *file, char __user *buf,
198 size_t count, loff_t *ppos) 202 size_t count, loff_t *ppos)
199{ 203{
200 u64 *counters; 204 u64 *counters;
205 size_t avail;
201 struct qib_devdata *dd = private2dd(file); 206 struct qib_devdata *dd = private2dd(file);
202 207
203 return simple_read_from_buffer(buf, count, ppos, counters, 208 avail = dd->f_read_portcntrs(dd, *ppos, 1, NULL, &counters);
204 dd->f_read_portcntrs(dd, *ppos, 1, NULL, &counters)); 209 return simple_read_from_buffer(buf, count, ppos, counters, avail);
205} 210}
206 211
207static const struct file_operations portcntr_ops[] = { 212static const struct file_operations portcntr_ops[] = {
@@ -537,10 +542,8 @@ static int qibfs_fill_super(struct super_block *sb, void *data, int silent)
537 list_for_each_entry_safe(dd, tmp, &qib_dev_list, list) { 542 list_for_each_entry_safe(dd, tmp, &qib_dev_list, list) {
538 spin_unlock_irqrestore(&qib_devs_lock, flags); 543 spin_unlock_irqrestore(&qib_devs_lock, flags);
539 ret = add_cntr_files(sb, dd); 544 ret = add_cntr_files(sb, dd);
540 if (ret) { 545 if (ret)
541 deactivate_super(sb);
542 goto bail; 546 goto bail;
543 }
544 spin_lock_irqsave(&qib_devs_lock, flags); 547 spin_lock_irqsave(&qib_devs_lock, flags);
545 } 548 }
546 549
diff --git a/drivers/infiniband/hw/qib/qib_iba6120.c b/drivers/infiniband/hw/qib/qib_iba6120.c
index 7b6549fd429b..1eadadc13da8 100644
--- a/drivers/infiniband/hw/qib/qib_iba6120.c
+++ b/drivers/infiniband/hw/qib/qib_iba6120.c
@@ -3475,14 +3475,6 @@ struct qib_devdata *qib_init_iba6120_funcs(struct pci_dev *pdev,
3475 struct qib_devdata *dd; 3475 struct qib_devdata *dd;
3476 int ret; 3476 int ret;
3477 3477
3478#ifndef CONFIG_PCI_MSI
3479 qib_early_err(&pdev->dev, "QLogic PCIE device 0x%x cannot "
3480 "work if CONFIG_PCI_MSI is not enabled\n",
3481 ent->device);
3482 dd = ERR_PTR(-ENODEV);
3483 goto bail;
3484#endif
3485
3486 dd = qib_alloc_devdata(pdev, sizeof(struct qib_pportdata) + 3478 dd = qib_alloc_devdata(pdev, sizeof(struct qib_pportdata) +
3487 sizeof(struct qib_chip_specific)); 3479 sizeof(struct qib_chip_specific));
3488 if (IS_ERR(dd)) 3480 if (IS_ERR(dd))
@@ -3554,10 +3546,6 @@ struct qib_devdata *qib_init_iba6120_funcs(struct pci_dev *pdev,
3554 if (qib_mini_init) 3546 if (qib_mini_init)
3555 goto bail; 3547 goto bail;
3556 3548
3557#ifndef CONFIG_PCI_MSI
3558 qib_dev_err(dd, "PCI_MSI not configured, NO interrupts\n");
3559#endif
3560
3561 if (qib_pcie_params(dd, 8, NULL, NULL)) 3549 if (qib_pcie_params(dd, 8, NULL, NULL))
3562 qib_dev_err(dd, "Failed to setup PCIe or interrupts; " 3550 qib_dev_err(dd, "Failed to setup PCIe or interrupts; "
3563 "continuing anyway\n"); 3551 "continuing anyway\n");
diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c
index 2c24eab35b54..503992d9c5ce 100644
--- a/drivers/infiniband/hw/qib/qib_iba7322.c
+++ b/drivers/infiniband/hw/qib/qib_iba7322.c
@@ -42,9 +42,6 @@
42#include <linux/jiffies.h> 42#include <linux/jiffies.h>
43#include <rdma/ib_verbs.h> 43#include <rdma/ib_verbs.h>
44#include <rdma/ib_smi.h> 44#include <rdma/ib_smi.h>
45#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
46#include <linux/dca.h>
47#endif
48 45
49#include "qib.h" 46#include "qib.h"
50#include "qib_7322_regs.h" 47#include "qib_7322_regs.h"
@@ -114,40 +111,18 @@ static ushort qib_singleport;
114module_param_named(singleport, qib_singleport, ushort, S_IRUGO); 111module_param_named(singleport, qib_singleport, ushort, S_IRUGO);
115MODULE_PARM_DESC(singleport, "Use only IB port 1; more per-port buffer space"); 112MODULE_PARM_DESC(singleport, "Use only IB port 1; more per-port buffer space");
116 113
117
118/*
119 * Setup QMH7342 receive and transmit parameters, necessary because
120 * each bay, Mez connector, and IB port need different tuning, beyond
121 * what the switch and HCA can do automatically.
122 * It's expected to be done by cat'ing files to the modules file,
123 * rather than setting up as a module parameter.
124 * It's a "write-only" file, returns 0 when read back.
125 * The unit, port, bay (if given), and values MUST be done as a single write.
126 * The unit, port, and bay must precede the values to be effective.
127 */
128static int setup_qmh_params(const char *, struct kernel_param *);
129static unsigned dummy_qmh_params;
130module_param_call(qmh_serdes_setup, setup_qmh_params, param_get_uint,
131 &dummy_qmh_params, S_IWUSR | S_IRUGO);
132
133/* similarly for QME7342, but it's simpler */
134static int setup_qme_params(const char *, struct kernel_param *);
135static unsigned dummy_qme_params;
136module_param_call(qme_serdes_setup, setup_qme_params, param_get_uint,
137 &dummy_qme_params, S_IWUSR | S_IRUGO);
138
139#define MAX_ATTEN_LEN 64 /* plenty for any real system */ 114#define MAX_ATTEN_LEN 64 /* plenty for any real system */
140/* for read back, default index is ~5m copper cable */ 115/* for read back, default index is ~5m copper cable */
141static char cable_atten_list[MAX_ATTEN_LEN] = "10"; 116static char txselect_list[MAX_ATTEN_LEN] = "10";
142static struct kparam_string kp_cable_atten = { 117static struct kparam_string kp_txselect = {
143 .string = cable_atten_list, 118 .string = txselect_list,
144 .maxlen = MAX_ATTEN_LEN 119 .maxlen = MAX_ATTEN_LEN
145}; 120};
146static int setup_cable_atten(const char *, struct kernel_param *); 121static int setup_txselect(const char *, struct kernel_param *);
147module_param_call(cable_atten, setup_cable_atten, param_get_string, 122module_param_call(txselect, setup_txselect, param_get_string,
148 &kp_cable_atten, S_IWUSR | S_IRUGO); 123 &kp_txselect, S_IWUSR | S_IRUGO);
149MODULE_PARM_DESC(cable_atten, \ 124MODULE_PARM_DESC(txselect, \
150 "cable attenuation indices for cables with invalid EEPROM"); 125 "Tx serdes indices (for no QSFP or invalid QSFP data)");
151 126
152#define BOARD_QME7342 5 127#define BOARD_QME7342 5
153#define BOARD_QMH7342 6 128#define BOARD_QMH7342 6
@@ -540,12 +515,6 @@ struct qib_chip_specific {
540 u32 lastbuf_for_pio; 515 u32 lastbuf_for_pio;
541 u32 stay_in_freeze; 516 u32 stay_in_freeze;
542 u32 recovery_ports_initted; 517 u32 recovery_ports_initted;
543#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
544 u32 dca_ctrl;
545 int rhdr_cpu[18];
546 int sdma_cpu[2];
547 u64 dca_rcvhdr_ctrl[5]; /* B, C, D, E, F */
548#endif
549 struct msix_entry *msix_entries; 518 struct msix_entry *msix_entries;
550 void **msix_arg; 519 void **msix_arg;
551 unsigned long *sendchkenable; 520 unsigned long *sendchkenable;
@@ -574,11 +543,12 @@ struct vendor_txdds_ent {
574static void write_tx_serdes_param(struct qib_pportdata *, struct txdds_ent *); 543static void write_tx_serdes_param(struct qib_pportdata *, struct txdds_ent *);
575 544
576#define TXDDS_TABLE_SZ 16 /* number of entries per speed in onchip table */ 545#define TXDDS_TABLE_SZ 16 /* number of entries per speed in onchip table */
546#define TXDDS_EXTRA_SZ 11 /* number of extra tx settings entries */
577#define SERDES_CHANS 4 /* yes, it's obvious, but one less magic number */ 547#define SERDES_CHANS 4 /* yes, it's obvious, but one less magic number */
578 548
579#define H1_FORCE_VAL 8 549#define H1_FORCE_VAL 8
580#define H1_FORCE_QME 1 /* may be overridden via setup_qme_params() */ 550#define H1_FORCE_QME 1 /* may be overridden via setup_txselect() */
581#define H1_FORCE_QMH 7 /* may be overridden via setup_qmh_params() */ 551#define H1_FORCE_QMH 7 /* may be overridden via setup_txselect() */
582 552
583/* The static and dynamic registers are paired, and the pairs indexed by spd */ 553/* The static and dynamic registers are paired, and the pairs indexed by spd */
584#define krp_static_adapt_dis(spd) (KREG_IBPORT_IDX(ADAPT_DISABLE_STATIC_SDR) \ 554#define krp_static_adapt_dis(spd) (KREG_IBPORT_IDX(ADAPT_DISABLE_STATIC_SDR) \
@@ -590,15 +560,6 @@ static void write_tx_serdes_param(struct qib_pportdata *, struct txdds_ent *);
590#define QDR_STATIC_ADAPT_INIT 0xffffffffffULL /* up, disable H0,H1-8, LE */ 560#define QDR_STATIC_ADAPT_INIT 0xffffffffffULL /* up, disable H0,H1-8, LE */
591#define QDR_STATIC_ADAPT_INIT_R1 0xf0ffffffffULL /* r1 up, disable H0,H1-8 */ 561#define QDR_STATIC_ADAPT_INIT_R1 0xf0ffffffffULL /* r1 up, disable H0,H1-8 */
592 562
593static const struct txdds_ent qmh_sdr_txdds = { 11, 0, 5, 6 };
594static const struct txdds_ent qmh_ddr_txdds = { 7, 0, 2, 8 };
595static const struct txdds_ent qmh_qdr_txdds = { 0, 1, 3, 10 };
596
597/* this is used for unknown mez cards also */
598static const struct txdds_ent qme_sdr_txdds = { 11, 0, 4, 4 };
599static const struct txdds_ent qme_ddr_txdds = { 7, 0, 2, 7 };
600static const struct txdds_ent qme_qdr_txdds = { 0, 1, 12, 11 };
601
602struct qib_chippport_specific { 563struct qib_chippport_specific {
603 u64 __iomem *kpregbase; 564 u64 __iomem *kpregbase;
604 u64 __iomem *cpregbase; 565 u64 __iomem *cpregbase;
@@ -637,12 +598,8 @@ struct qib_chippport_specific {
637 * Per-bay per-channel rcv QMH H1 values and Tx values for QDR. 598 * Per-bay per-channel rcv QMH H1 values and Tx values for QDR.
638 * entry zero is unused, to simplify indexing 599 * entry zero is unused, to simplify indexing
639 */ 600 */
640 u16 h1_val; 601 u8 h1_val;
641 u8 amp[SERDES_CHANS]; 602 u8 no_eep; /* txselect table index to use if no qsfp info */
642 u8 pre[SERDES_CHANS];
643 u8 mainv[SERDES_CHANS];
644 u8 post[SERDES_CHANS];
645 u8 no_eep; /* attenuation index to use if no qsfp info */
646 u8 ipg_tries; 603 u8 ipg_tries;
647 u8 ibmalfusesnap; 604 u8 ibmalfusesnap;
648 struct qib_qsfp_data qsfp_data; 605 struct qib_qsfp_data qsfp_data;
@@ -676,52 +633,6 @@ static struct {
676 SYM_LSB(IntStatus, SDmaCleanupDone_1), 2 }, 633 SYM_LSB(IntStatus, SDmaCleanupDone_1), 2 },
677}; 634};
678 635
679#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
680static const struct dca_reg_map {
681 int shadow_inx;
682 int lsb;
683 u64 mask;
684 u16 regno;
685} dca_rcvhdr_reg_map[] = {
686 { 0, SYM_LSB(DCACtrlB, RcvHdrq0DCAOPH),
687 ~SYM_MASK(DCACtrlB, RcvHdrq0DCAOPH) , KREG_IDX(DCACtrlB) },
688 { 0, SYM_LSB(DCACtrlB, RcvHdrq1DCAOPH),
689 ~SYM_MASK(DCACtrlB, RcvHdrq1DCAOPH) , KREG_IDX(DCACtrlB) },
690 { 0, SYM_LSB(DCACtrlB, RcvHdrq2DCAOPH),
691 ~SYM_MASK(DCACtrlB, RcvHdrq2DCAOPH) , KREG_IDX(DCACtrlB) },
692 { 0, SYM_LSB(DCACtrlB, RcvHdrq3DCAOPH),
693 ~SYM_MASK(DCACtrlB, RcvHdrq3DCAOPH) , KREG_IDX(DCACtrlB) },
694 { 1, SYM_LSB(DCACtrlC, RcvHdrq4DCAOPH),
695 ~SYM_MASK(DCACtrlC, RcvHdrq4DCAOPH) , KREG_IDX(DCACtrlC) },
696 { 1, SYM_LSB(DCACtrlC, RcvHdrq5DCAOPH),
697 ~SYM_MASK(DCACtrlC, RcvHdrq5DCAOPH) , KREG_IDX(DCACtrlC) },
698 { 1, SYM_LSB(DCACtrlC, RcvHdrq6DCAOPH),
699 ~SYM_MASK(DCACtrlC, RcvHdrq6DCAOPH) , KREG_IDX(DCACtrlC) },
700 { 1, SYM_LSB(DCACtrlC, RcvHdrq7DCAOPH),
701 ~SYM_MASK(DCACtrlC, RcvHdrq7DCAOPH) , KREG_IDX(DCACtrlC) },
702 { 2, SYM_LSB(DCACtrlD, RcvHdrq8DCAOPH),
703 ~SYM_MASK(DCACtrlD, RcvHdrq8DCAOPH) , KREG_IDX(DCACtrlD) },
704 { 2, SYM_LSB(DCACtrlD, RcvHdrq9DCAOPH),
705 ~SYM_MASK(DCACtrlD, RcvHdrq9DCAOPH) , KREG_IDX(DCACtrlD) },
706 { 2, SYM_LSB(DCACtrlD, RcvHdrq10DCAOPH),
707 ~SYM_MASK(DCACtrlD, RcvHdrq10DCAOPH) , KREG_IDX(DCACtrlD) },
708 { 2, SYM_LSB(DCACtrlD, RcvHdrq11DCAOPH),
709 ~SYM_MASK(DCACtrlD, RcvHdrq11DCAOPH) , KREG_IDX(DCACtrlD) },
710 { 3, SYM_LSB(DCACtrlE, RcvHdrq12DCAOPH),
711 ~SYM_MASK(DCACtrlE, RcvHdrq12DCAOPH) , KREG_IDX(DCACtrlE) },
712 { 3, SYM_LSB(DCACtrlE, RcvHdrq13DCAOPH),
713 ~SYM_MASK(DCACtrlE, RcvHdrq13DCAOPH) , KREG_IDX(DCACtrlE) },
714 { 3, SYM_LSB(DCACtrlE, RcvHdrq14DCAOPH),
715 ~SYM_MASK(DCACtrlE, RcvHdrq14DCAOPH) , KREG_IDX(DCACtrlE) },
716 { 3, SYM_LSB(DCACtrlE, RcvHdrq15DCAOPH),
717 ~SYM_MASK(DCACtrlE, RcvHdrq15DCAOPH) , KREG_IDX(DCACtrlE) },
718 { 4, SYM_LSB(DCACtrlF, RcvHdrq16DCAOPH),
719 ~SYM_MASK(DCACtrlF, RcvHdrq16DCAOPH) , KREG_IDX(DCACtrlF) },
720 { 4, SYM_LSB(DCACtrlF, RcvHdrq17DCAOPH),
721 ~SYM_MASK(DCACtrlF, RcvHdrq17DCAOPH) , KREG_IDX(DCACtrlF) },
722};
723#endif
724
725/* ibcctrl bits */ 636/* ibcctrl bits */
726#define QLOGIC_IB_IBCC_LINKINITCMD_DISABLE 1 637#define QLOGIC_IB_IBCC_LINKINITCMD_DISABLE 1
727/* cycle through TS1/TS2 till OK */ 638/* cycle through TS1/TS2 till OK */
@@ -2572,95 +2483,6 @@ static void qib_setup_7322_setextled(struct qib_pportdata *ppd, u32 on)
2572 qib_write_kreg_port(ppd, krp_rcvpktledcnt, ledblink); 2483 qib_write_kreg_port(ppd, krp_rcvpktledcnt, ledblink);
2573} 2484}
2574 2485
2575#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
2576static void qib_update_rhdrq_dca(struct qib_ctxtdata *rcd)
2577{
2578 struct qib_devdata *dd = rcd->dd;
2579 struct qib_chip_specific *cspec = dd->cspec;
2580 int cpu = get_cpu();
2581
2582 if (cspec->rhdr_cpu[rcd->ctxt] != cpu) {
2583 const struct dca_reg_map *rmp;
2584
2585 cspec->rhdr_cpu[rcd->ctxt] = cpu;
2586 rmp = &dca_rcvhdr_reg_map[rcd->ctxt];
2587 cspec->dca_rcvhdr_ctrl[rmp->shadow_inx] &= rmp->mask;
2588 cspec->dca_rcvhdr_ctrl[rmp->shadow_inx] |=
2589 (u64) dca3_get_tag(&dd->pcidev->dev, cpu) << rmp->lsb;
2590 qib_write_kreg(dd, rmp->regno,
2591 cspec->dca_rcvhdr_ctrl[rmp->shadow_inx]);
2592 cspec->dca_ctrl |= SYM_MASK(DCACtrlA, RcvHdrqDCAEnable);
2593 qib_write_kreg(dd, KREG_IDX(DCACtrlA), cspec->dca_ctrl);
2594 }
2595 put_cpu();
2596}
2597
2598static void qib_update_sdma_dca(struct qib_pportdata *ppd)
2599{
2600 struct qib_devdata *dd = ppd->dd;
2601 struct qib_chip_specific *cspec = dd->cspec;
2602 int cpu = get_cpu();
2603 unsigned pidx = ppd->port - 1;
2604
2605 if (cspec->sdma_cpu[pidx] != cpu) {
2606 cspec->sdma_cpu[pidx] = cpu;
2607 cspec->dca_rcvhdr_ctrl[4] &= ~(ppd->hw_pidx ?
2608 SYM_MASK(DCACtrlF, SendDma1DCAOPH) :
2609 SYM_MASK(DCACtrlF, SendDma0DCAOPH));
2610 cspec->dca_rcvhdr_ctrl[4] |=
2611 (u64) dca3_get_tag(&dd->pcidev->dev, cpu) <<
2612 (ppd->hw_pidx ?
2613 SYM_LSB(DCACtrlF, SendDma1DCAOPH) :
2614 SYM_LSB(DCACtrlF, SendDma0DCAOPH));
2615 qib_write_kreg(dd, KREG_IDX(DCACtrlF),
2616 cspec->dca_rcvhdr_ctrl[4]);
2617 cspec->dca_ctrl |= ppd->hw_pidx ?
2618 SYM_MASK(DCACtrlA, SendDMAHead1DCAEnable) :
2619 SYM_MASK(DCACtrlA, SendDMAHead0DCAEnable);
2620 qib_write_kreg(dd, KREG_IDX(DCACtrlA), cspec->dca_ctrl);
2621 }
2622 put_cpu();
2623}
2624
2625static void qib_setup_dca(struct qib_devdata *dd)
2626{
2627 struct qib_chip_specific *cspec = dd->cspec;
2628 int i;
2629
2630 for (i = 0; i < ARRAY_SIZE(cspec->rhdr_cpu); i++)
2631 cspec->rhdr_cpu[i] = -1;
2632 for (i = 0; i < ARRAY_SIZE(cspec->sdma_cpu); i++)
2633 cspec->sdma_cpu[i] = -1;
2634 cspec->dca_rcvhdr_ctrl[0] =
2635 (1ULL << SYM_LSB(DCACtrlB, RcvHdrq0DCAXfrCnt)) |
2636 (1ULL << SYM_LSB(DCACtrlB, RcvHdrq1DCAXfrCnt)) |
2637 (1ULL << SYM_LSB(DCACtrlB, RcvHdrq2DCAXfrCnt)) |
2638 (1ULL << SYM_LSB(DCACtrlB, RcvHdrq3DCAXfrCnt));
2639 cspec->dca_rcvhdr_ctrl[1] =
2640 (1ULL << SYM_LSB(DCACtrlC, RcvHdrq4DCAXfrCnt)) |
2641 (1ULL << SYM_LSB(DCACtrlC, RcvHdrq5DCAXfrCnt)) |
2642 (1ULL << SYM_LSB(DCACtrlC, RcvHdrq6DCAXfrCnt)) |
2643 (1ULL << SYM_LSB(DCACtrlC, RcvHdrq7DCAXfrCnt));
2644 cspec->dca_rcvhdr_ctrl[2] =
2645 (1ULL << SYM_LSB(DCACtrlD, RcvHdrq8DCAXfrCnt)) |
2646 (1ULL << SYM_LSB(DCACtrlD, RcvHdrq9DCAXfrCnt)) |
2647 (1ULL << SYM_LSB(DCACtrlD, RcvHdrq10DCAXfrCnt)) |
2648 (1ULL << SYM_LSB(DCACtrlD, RcvHdrq11DCAXfrCnt));
2649 cspec->dca_rcvhdr_ctrl[3] =
2650 (1ULL << SYM_LSB(DCACtrlE, RcvHdrq12DCAXfrCnt)) |
2651 (1ULL << SYM_LSB(DCACtrlE, RcvHdrq13DCAXfrCnt)) |
2652 (1ULL << SYM_LSB(DCACtrlE, RcvHdrq14DCAXfrCnt)) |
2653 (1ULL << SYM_LSB(DCACtrlE, RcvHdrq15DCAXfrCnt));
2654 cspec->dca_rcvhdr_ctrl[4] =
2655 (1ULL << SYM_LSB(DCACtrlF, RcvHdrq16DCAXfrCnt)) |
2656 (1ULL << SYM_LSB(DCACtrlF, RcvHdrq17DCAXfrCnt));
2657 for (i = 0; i < ARRAY_SIZE(cspec->sdma_cpu); i++)
2658 qib_write_kreg(dd, KREG_IDX(DCACtrlB) + i,
2659 cspec->dca_rcvhdr_ctrl[i]);
2660}
2661
2662#endif
2663
2664/* 2486/*
2665 * Disable MSIx interrupt if enabled, call generic MSIx code 2487 * Disable MSIx interrupt if enabled, call generic MSIx code
2666 * to cleanup, and clear pending MSIx interrupts. 2488 * to cleanup, and clear pending MSIx interrupts.
@@ -2701,15 +2523,6 @@ static void qib_setup_7322_cleanup(struct qib_devdata *dd)
2701{ 2523{
2702 int i; 2524 int i;
2703 2525
2704#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
2705 if (dd->flags & QIB_DCA_ENABLED) {
2706 dca_remove_requester(&dd->pcidev->dev);
2707 dd->flags &= ~QIB_DCA_ENABLED;
2708 dd->cspec->dca_ctrl = 0;
2709 qib_write_kreg(dd, KREG_IDX(DCACtrlA), dd->cspec->dca_ctrl);
2710 }
2711#endif
2712
2713 qib_7322_free_irq(dd); 2526 qib_7322_free_irq(dd);
2714 kfree(dd->cspec->cntrs); 2527 kfree(dd->cspec->cntrs);
2715 kfree(dd->cspec->sendchkenable); 2528 kfree(dd->cspec->sendchkenable);
@@ -3017,11 +2830,6 @@ static irqreturn_t qib_7322pintr(int irq, void *data)
3017 if (dd->int_counter != (u32) -1) 2830 if (dd->int_counter != (u32) -1)
3018 dd->int_counter++; 2831 dd->int_counter++;
3019 2832
3020#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
3021 if (dd->flags & QIB_DCA_ENABLED)
3022 qib_update_rhdrq_dca(rcd);
3023#endif
3024
3025 /* Clear the interrupt bit we expect to be set. */ 2833 /* Clear the interrupt bit we expect to be set. */
3026 qib_write_kreg(dd, kr_intclear, ((1ULL << QIB_I_RCVAVAIL_LSB) | 2834 qib_write_kreg(dd, kr_intclear, ((1ULL << QIB_I_RCVAVAIL_LSB) |
3027 (1ULL << QIB_I_RCVURG_LSB)) << rcd->ctxt); 2835 (1ULL << QIB_I_RCVURG_LSB)) << rcd->ctxt);
@@ -3085,11 +2893,6 @@ static irqreturn_t sdma_intr(int irq, void *data)
3085 if (dd->int_counter != (u32) -1) 2893 if (dd->int_counter != (u32) -1)
3086 dd->int_counter++; 2894 dd->int_counter++;
3087 2895
3088#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
3089 if (dd->flags & QIB_DCA_ENABLED)
3090 qib_update_sdma_dca(ppd);
3091#endif
3092
3093 /* Clear the interrupt bit we expect to be set. */ 2896 /* Clear the interrupt bit we expect to be set. */
3094 qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ? 2897 qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ?
3095 INT_MASK_P(SDma, 1) : INT_MASK_P(SDma, 0)); 2898 INT_MASK_P(SDma, 1) : INT_MASK_P(SDma, 0));
@@ -3119,11 +2922,6 @@ static irqreturn_t sdma_idle_intr(int irq, void *data)
3119 if (dd->int_counter != (u32) -1) 2922 if (dd->int_counter != (u32) -1)
3120 dd->int_counter++; 2923 dd->int_counter++;
3121 2924
3122#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
3123 if (dd->flags & QIB_DCA_ENABLED)
3124 qib_update_sdma_dca(ppd);
3125#endif
3126
3127 /* Clear the interrupt bit we expect to be set. */ 2925 /* Clear the interrupt bit we expect to be set. */
3128 qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ? 2926 qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ?
3129 INT_MASK_P(SDmaIdle, 1) : INT_MASK_P(SDmaIdle, 0)); 2927 INT_MASK_P(SDmaIdle, 1) : INT_MASK_P(SDmaIdle, 0));
@@ -3153,11 +2951,6 @@ static irqreturn_t sdma_progress_intr(int irq, void *data)
3153 if (dd->int_counter != (u32) -1) 2951 if (dd->int_counter != (u32) -1)
3154 dd->int_counter++; 2952 dd->int_counter++;
3155 2953
3156#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
3157 if (dd->flags & QIB_DCA_ENABLED)
3158 qib_update_sdma_dca(ppd);
3159#endif
3160
3161 /* Clear the interrupt bit we expect to be set. */ 2954 /* Clear the interrupt bit we expect to be set. */
3162 qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ? 2955 qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ?
3163 INT_MASK_P(SDmaProgress, 1) : 2956 INT_MASK_P(SDmaProgress, 1) :
@@ -3188,11 +2981,6 @@ static irqreturn_t sdma_cleanup_intr(int irq, void *data)
3188 if (dd->int_counter != (u32) -1) 2981 if (dd->int_counter != (u32) -1)
3189 dd->int_counter++; 2982 dd->int_counter++;
3190 2983
3191#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
3192 if (dd->flags & QIB_DCA_ENABLED)
3193 qib_update_sdma_dca(ppd);
3194#endif
3195
3196 /* Clear the interrupt bit we expect to be set. */ 2984 /* Clear the interrupt bit we expect to be set. */
3197 qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ? 2985 qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ?
3198 INT_MASK_PM(SDmaCleanupDone, 1) : 2986 INT_MASK_PM(SDmaCleanupDone, 1) :
@@ -4299,10 +4087,6 @@ static void rcvctrl_7322_mod(struct qib_pportdata *ppd, unsigned int op,
4299 qib_write_kreg_ctxt(dd, krc_rcvhdraddr, ctxt, 4087 qib_write_kreg_ctxt(dd, krc_rcvhdraddr, ctxt,
4300 rcd->rcvhdrq_phys); 4088 rcd->rcvhdrq_phys);
4301 rcd->seq_cnt = 1; 4089 rcd->seq_cnt = 1;
4302#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
4303 if (dd->flags & QIB_DCA_ENABLED)
4304 qib_update_rhdrq_dca(rcd);
4305#endif
4306 } 4090 }
4307 if (op & QIB_RCVCTRL_CTXT_DIS) 4091 if (op & QIB_RCVCTRL_CTXT_DIS)
4308 ppd->p_rcvctrl &= 4092 ppd->p_rcvctrl &=
@@ -5360,7 +5144,13 @@ static int qib_7322_ib_updown(struct qib_pportdata *ppd, int ibup, u64 ibcs)
5360 QIBL_IB_AUTONEG_INPROG))) 5144 QIBL_IB_AUTONEG_INPROG)))
5361 set_7322_ibspeed_fast(ppd, ppd->link_speed_enabled); 5145 set_7322_ibspeed_fast(ppd, ppd->link_speed_enabled);
5362 if (!(ppd->lflags & QIBL_IB_AUTONEG_INPROG)) { 5146 if (!(ppd->lflags & QIBL_IB_AUTONEG_INPROG)) {
5147 /* unlock the Tx settings, speed may change */
5148 qib_write_kreg_port(ppd, krp_tx_deemph_override,
5149 SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
5150 reset_tx_deemphasis_override));
5363 qib_cancel_sends(ppd); 5151 qib_cancel_sends(ppd);
5152 /* on link down, ensure sane pcs state */
5153 qib_7322_mini_pcs_reset(ppd);
5364 spin_lock_irqsave(&ppd->sdma_lock, flags); 5154 spin_lock_irqsave(&ppd->sdma_lock, flags);
5365 if (__qib_sdma_running(ppd)) 5155 if (__qib_sdma_running(ppd))
5366 __qib_sdma_process_event(ppd, 5156 __qib_sdma_process_event(ppd,
@@ -5766,26 +5556,28 @@ static void qib_init_7322_qsfp(struct qib_pportdata *ppd)
5766} 5556}
5767 5557
5768/* 5558/*
5769 * called at device initialization time, and also if the cable_atten 5559 * called at device initialization time, and also if the txselect
5770 * module parameter is changed. This is used for cables that don't 5560 * module parameter is changed. This is used for cables that don't
5771 * have valid QSFP EEPROMs (not present, or attenuation is zero). 5561 * have valid QSFP EEPROMs (not present, or attenuation is zero).
5772 * We initialize to the default, then if there is a specific 5562 * We initialize to the default, then if there is a specific
5773 * unit,port match, we use that. 5563 * unit,port match, we use that (and set it immediately, for the
5564 * current speed, if the link is at INIT or better).
5774 * String format is "default# unit#,port#=# ... u,p=#", separators must 5565 * String format is "default# unit#,port#=# ... u,p=#", separators must
5775 * be a SPACE character. A newline terminates. 5566 * be a SPACE character. A newline terminates. The u,p=# tuples may
5567 * optionally have "u,p=#,#", where the final # is the H1 value
5776 * The last specific match is used (actually, all are used, but last 5568 * The last specific match is used (actually, all are used, but last
5777 * one is the one that winds up set); if none at all, fall back on default. 5569 * one is the one that winds up set); if none at all, fall back on default.
5778 */ 5570 */
5779static void set_no_qsfp_atten(struct qib_devdata *dd, int change) 5571static void set_no_qsfp_atten(struct qib_devdata *dd, int change)
5780{ 5572{
5781 char *nxt, *str; 5573 char *nxt, *str;
5782 int pidx, unit, port, deflt; 5574 u32 pidx, unit, port, deflt, h1;
5783 unsigned long val; 5575 unsigned long val;
5784 int any = 0; 5576 int any = 0, seth1;
5785 5577
5786 str = cable_atten_list; 5578 str = txselect_list;
5787 5579
5788 /* default number is validated in setup_cable_atten() */ 5580 /* default number is validated in setup_txselect() */
5789 deflt = simple_strtoul(str, &nxt, 0); 5581 deflt = simple_strtoul(str, &nxt, 0);
5790 for (pidx = 0; pidx < dd->num_pports; ++pidx) 5582 for (pidx = 0; pidx < dd->num_pports; ++pidx)
5791 dd->pport[pidx].cpspec->no_eep = deflt; 5583 dd->pport[pidx].cpspec->no_eep = deflt;
@@ -5812,16 +5604,28 @@ static void set_no_qsfp_atten(struct qib_devdata *dd, int change)
5812 ; 5604 ;
5813 continue; 5605 continue;
5814 } 5606 }
5815 if (val >= TXDDS_TABLE_SZ) 5607 if (val >= TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ)
5816 continue; 5608 continue;
5609 seth1 = 0;
5610 h1 = 0; /* gcc thinks it might be used uninitted */
5611 if (*nxt == ',' && nxt[1]) {
5612 str = ++nxt;
5613 h1 = (u32)simple_strtoul(str, &nxt, 0);
5614 if (nxt == str)
5615 while (*nxt && *nxt++ != ' ') /* skip */
5616 ;
5617 else
5618 seth1 = 1;
5619 }
5817 for (pidx = 0; dd->unit == unit && pidx < dd->num_pports; 5620 for (pidx = 0; dd->unit == unit && pidx < dd->num_pports;
5818 ++pidx) { 5621 ++pidx) {
5819 if (dd->pport[pidx].port != port || 5622 struct qib_pportdata *ppd = &dd->pport[pidx];
5820 !dd->pport[pidx].link_speed_supported) 5623
5624 if (ppd->port != port || !ppd->link_speed_supported)
5821 continue; 5625 continue;
5822 dd->pport[pidx].cpspec->no_eep = val; 5626 ppd->cpspec->no_eep = val;
5823 /* now change the IBC and serdes, overriding generic */ 5627 /* now change the IBC and serdes, overriding generic */
5824 init_txdds_table(&dd->pport[pidx], 1); 5628 init_txdds_table(ppd, 1);
5825 any++; 5629 any++;
5826 } 5630 }
5827 if (*nxt == '\n') 5631 if (*nxt == '\n')
@@ -5832,35 +5636,35 @@ static void set_no_qsfp_atten(struct qib_devdata *dd, int change)
5832 * Change the IBC and serdes, but since it's 5636 * Change the IBC and serdes, but since it's
5833 * general, don't override specific settings. 5637 * general, don't override specific settings.
5834 */ 5638 */
5835 for (pidx = 0; pidx < dd->num_pports; ++pidx) { 5639 for (pidx = 0; pidx < dd->num_pports; ++pidx)
5836 if (!dd->pport[pidx].link_speed_supported) 5640 if (dd->pport[pidx].link_speed_supported)
5837 continue; 5641 init_txdds_table(&dd->pport[pidx], 0);
5838 init_txdds_table(&dd->pport[pidx], 0);
5839 }
5840 } 5642 }
5841} 5643}
5842 5644
5843/* handle the cable_atten parameter changing */ 5645/* handle the txselect parameter changing */
5844static int setup_cable_atten(const char *str, struct kernel_param *kp) 5646static int setup_txselect(const char *str, struct kernel_param *kp)
5845{ 5647{
5846 struct qib_devdata *dd; 5648 struct qib_devdata *dd;
5847 unsigned long val; 5649 unsigned long val;
5848 char *n; 5650 char *n;
5849 if (strlen(str) >= MAX_ATTEN_LEN) { 5651 if (strlen(str) >= MAX_ATTEN_LEN) {
5850 printk(KERN_INFO QIB_DRV_NAME " cable_atten_values string " 5652 printk(KERN_INFO QIB_DRV_NAME " txselect_values string "
5851 "too long\n"); 5653 "too long\n");
5852 return -ENOSPC; 5654 return -ENOSPC;
5853 } 5655 }
5854 val = simple_strtoul(str, &n, 0); 5656 val = simple_strtoul(str, &n, 0);
5855 if (n == str || val >= TXDDS_TABLE_SZ) { 5657 if (n == str || val >= (TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ)) {
5856 printk(KERN_INFO QIB_DRV_NAME 5658 printk(KERN_INFO QIB_DRV_NAME
5857 "cable_atten_values must start with a number\n"); 5659 "txselect_values must start with a number < %d\n",
5660 TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ);
5858 return -EINVAL; 5661 return -EINVAL;
5859 } 5662 }
5860 strcpy(cable_atten_list, str); 5663 strcpy(txselect_list, str);
5861 5664
5862 list_for_each_entry(dd, &qib_dev_list, list) 5665 list_for_each_entry(dd, &qib_dev_list, list)
5863 set_no_qsfp_atten(dd, 1); 5666 if (dd->deviceid == PCI_DEVICE_ID_QLOGIC_IB_7322)
5667 set_no_qsfp_atten(dd, 1);
5864 return 0; 5668 return 0;
5865} 5669}
5866 5670
@@ -6261,28 +6065,17 @@ static int qib_init_7322_variables(struct qib_devdata *dd)
6261 * in adapter-specific routines. 6065 * in adapter-specific routines.
6262 */ 6066 */
6263 if (!(ppd->dd->flags & QIB_HAS_QSFP)) { 6067 if (!(ppd->dd->flags & QIB_HAS_QSFP)) {
6264 int i;
6265 const struct txdds_ent *txdds;
6266
6267 if (!IS_QMH(ppd->dd) && !IS_QME(ppd->dd)) 6068 if (!IS_QMH(ppd->dd) && !IS_QME(ppd->dd))
6268 qib_devinfo(ppd->dd->pcidev, "IB%u:%u: " 6069 qib_devinfo(ppd->dd->pcidev, "IB%u:%u: "
6269 "Unknown mezzanine card type\n", 6070 "Unknown mezzanine card type\n",
6270 ppd->dd->unit, ppd->port); 6071 dd->unit, ppd->port);
6271 txdds = IS_QMH(ppd->dd) ? &qmh_qdr_txdds : 6072 cp->h1_val = IS_QMH(dd) ? H1_FORCE_QMH : H1_FORCE_QME;
6272 &qme_qdr_txdds;
6273
6274 /* 6073 /*
6275 * set values in case link comes up 6074 * Choose center value as default tx serdes setting
6276 * before table is written to driver. 6075 * until changed through module parameter.
6277 */ 6076 */
6278 cp->h1_val = IS_QMH(ppd->dd) ? H1_FORCE_QMH : 6077 ppd->cpspec->no_eep = IS_QMH(dd) ?
6279 H1_FORCE_QME; 6078 TXDDS_TABLE_SZ + 2 : TXDDS_TABLE_SZ + 4;
6280 for (i = 0; i < SERDES_CHANS; i++) {
6281 cp->amp[i] = txdds->amp;
6282 cp->pre[i] = txdds->pre;
6283 cp->mainv[i] = txdds->main;
6284 cp->post[i] = txdds->post;
6285 }
6286 } else 6079 } else
6287 cp->h1_val = H1_FORCE_VAL; 6080 cp->h1_val = H1_FORCE_VAL;
6288 6081
@@ -6299,8 +6092,7 @@ static int qib_init_7322_variables(struct qib_devdata *dd)
6299 6092
6300 dd->rcvhdrentsize = QIB_RCVHDR_ENTSIZE; 6093 dd->rcvhdrentsize = QIB_RCVHDR_ENTSIZE;
6301 dd->rcvhdrsize = QIB_DFLT_RCVHDRSIZE; 6094 dd->rcvhdrsize = QIB_DFLT_RCVHDRSIZE;
6302 dd->rhf_offset = 6095 dd->rhf_offset = dd->rcvhdrentsize - sizeof(u64) / sizeof(u32);
6303 dd->rcvhdrentsize - sizeof(u64) / sizeof(u32);
6304 6096
6305 /* we always allocate at least 2048 bytes for eager buffers */ 6097 /* we always allocate at least 2048 bytes for eager buffers */
6306 dd->rcvegrbufsize = max(mtu, 2048); 6098 dd->rcvegrbufsize = max(mtu, 2048);
@@ -6919,13 +6711,6 @@ struct qib_devdata *qib_init_iba7322_funcs(struct pci_dev *pdev,
6919 /* clear diagctrl register, in case diags were running and crashed */ 6711 /* clear diagctrl register, in case diags were running and crashed */
6920 qib_write_kreg(dd, kr_hwdiagctrl, 0); 6712 qib_write_kreg(dd, kr_hwdiagctrl, 0);
6921 6713
6922#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
6923 ret = dca_add_requester(&pdev->dev);
6924 if (!ret) {
6925 dd->flags |= QIB_DCA_ENABLED;
6926 qib_setup_dca(dd);
6927 }
6928#endif
6929 goto bail; 6714 goto bail;
6930 6715
6931bail_cleanup: 6716bail_cleanup:
@@ -7111,8 +6896,8 @@ static const struct txdds_ent txdds_ddr[TXDDS_TABLE_SZ] = {
7111static const struct txdds_ent txdds_qdr[TXDDS_TABLE_SZ] = { 6896static const struct txdds_ent txdds_qdr[TXDDS_TABLE_SZ] = {
7112 /* amp, pre, main, post */ 6897 /* amp, pre, main, post */
7113 { 2, 2, 15, 6 }, /* Loopback */ 6898 { 2, 2, 15, 6 }, /* Loopback */
7114 { 0, 1, 0, 7 }, /* 2 dB */ 6899 { 0, 1, 0, 7 }, /* 2 dB (also QMH7342) */
7115 { 0, 1, 0, 9 }, /* 3 dB */ 6900 { 0, 1, 0, 9 }, /* 3 dB (also QMH7342) */
7116 { 0, 1, 0, 11 }, /* 4 dB */ 6901 { 0, 1, 0, 11 }, /* 4 dB */
7117 { 0, 1, 0, 13 }, /* 5 dB */ 6902 { 0, 1, 0, 13 }, /* 5 dB */
7118 { 0, 1, 0, 15 }, /* 6 dB */ 6903 { 0, 1, 0, 15 }, /* 6 dB */
@@ -7128,6 +6913,57 @@ static const struct txdds_ent txdds_qdr[TXDDS_TABLE_SZ] = {
7128 { 0, 2, 9, 15 }, /* 16 dB */ 6913 { 0, 2, 9, 15 }, /* 16 dB */
7129}; 6914};
7130 6915
6916/*
6917 * extra entries for use with txselect, for indices >= TXDDS_TABLE_SZ.
6918 * These are mostly used for mez cards going through connectors
6919 * and backplane traces, but can be used to add other "unusual"
6920 * table values as well.
6921 */
6922static const struct txdds_ent txdds_extra_sdr[TXDDS_EXTRA_SZ] = {
6923 /* amp, pre, main, post */
6924 { 0, 0, 0, 1 }, /* QMH7342 backplane settings */
6925 { 0, 0, 0, 1 }, /* QMH7342 backplane settings */
6926 { 0, 0, 0, 2 }, /* QMH7342 backplane settings */
6927 { 0, 0, 0, 2 }, /* QMH7342 backplane settings */
6928 { 0, 0, 0, 11 }, /* QME7342 backplane settings */
6929 { 0, 0, 0, 11 }, /* QME7342 backplane settings */
6930 { 0, 0, 0, 11 }, /* QME7342 backplane settings */
6931 { 0, 0, 0, 11 }, /* QME7342 backplane settings */
6932 { 0, 0, 0, 11 }, /* QME7342 backplane settings */
6933 { 0, 0, 0, 11 }, /* QME7342 backplane settings */
6934 { 0, 0, 0, 11 }, /* QME7342 backplane settings */
6935};
6936
6937static const struct txdds_ent txdds_extra_ddr[TXDDS_EXTRA_SZ] = {
6938 /* amp, pre, main, post */
6939 { 0, 0, 0, 7 }, /* QMH7342 backplane settings */
6940 { 0, 0, 0, 7 }, /* QMH7342 backplane settings */
6941 { 0, 0, 0, 8 }, /* QMH7342 backplane settings */
6942 { 0, 0, 0, 8 }, /* QMH7342 backplane settings */
6943 { 0, 0, 0, 13 }, /* QME7342 backplane settings */
6944 { 0, 0, 0, 13 }, /* QME7342 backplane settings */
6945 { 0, 0, 0, 13 }, /* QME7342 backplane settings */
6946 { 0, 0, 0, 13 }, /* QME7342 backplane settings */
6947 { 0, 0, 0, 13 }, /* QME7342 backplane settings */
6948 { 0, 0, 0, 13 }, /* QME7342 backplane settings */
6949 { 0, 0, 0, 13 }, /* QME7342 backplane settings */
6950};
6951
6952static const struct txdds_ent txdds_extra_qdr[TXDDS_EXTRA_SZ] = {
6953 /* amp, pre, main, post */
6954 { 0, 1, 0, 4 }, /* QMH7342 backplane settings */
6955 { 0, 1, 0, 5 }, /* QMH7342 backplane settings */
6956 { 0, 1, 0, 6 }, /* QMH7342 backplane settings */
6957 { 0, 1, 0, 8 }, /* QMH7342 backplane settings */
6958 { 0, 1, 12, 10 }, /* QME7342 backplane setting */
6959 { 0, 1, 12, 11 }, /* QME7342 backplane setting */
6960 { 0, 1, 12, 12 }, /* QME7342 backplane setting */
6961 { 0, 1, 12, 14 }, /* QME7342 backplane setting */
6962 { 0, 1, 12, 6 }, /* QME7342 backplane setting */
6963 { 0, 1, 12, 7 }, /* QME7342 backplane setting */
6964 { 0, 1, 12, 8 }, /* QME7342 backplane setting */
6965};
6966
7131static const struct txdds_ent *get_atten_table(const struct txdds_ent *txdds, 6967static const struct txdds_ent *get_atten_table(const struct txdds_ent *txdds,
7132 unsigned atten) 6968 unsigned atten)
7133{ 6969{
@@ -7145,7 +6981,7 @@ static const struct txdds_ent *get_atten_table(const struct txdds_ent *txdds,
7145} 6981}
7146 6982
7147/* 6983/*
7148 * if override is set, the module parameter cable_atten has a value 6984 * if override is set, the module parameter txselect has a value
7149 * for this specific port, so use it, rather than our normal mechanism. 6985 * for this specific port, so use it, rather than our normal mechanism.
7150 */ 6986 */
7151static void find_best_ent(struct qib_pportdata *ppd, 6987static void find_best_ent(struct qib_pportdata *ppd,
@@ -7184,15 +7020,28 @@ static void find_best_ent(struct qib_pportdata *ppd,
7184 *ddr_dds = get_atten_table(txdds_ddr, qd->atten[0]); 7020 *ddr_dds = get_atten_table(txdds_ddr, qd->atten[0]);
7185 *qdr_dds = get_atten_table(txdds_qdr, qd->atten[1]); 7021 *qdr_dds = get_atten_table(txdds_qdr, qd->atten[1]);
7186 return; 7022 return;
7187 } else { 7023 } else if (ppd->cpspec->no_eep < TXDDS_TABLE_SZ) {
7188 /* 7024 /*
7189 * If we have no (or incomplete) data from the cable 7025 * If we have no (or incomplete) data from the cable
7190 * EEPROM, or no QSFP, use the module parameter value 7026 * EEPROM, or no QSFP, or override is set, use the
7191 * to index into the attentuation table. 7027 * module parameter value to index into the attentuation
7028 * table.
7192 */ 7029 */
7193 *sdr_dds = &txdds_sdr[ppd->cpspec->no_eep]; 7030 idx = ppd->cpspec->no_eep;
7194 *ddr_dds = &txdds_ddr[ppd->cpspec->no_eep]; 7031 *sdr_dds = &txdds_sdr[idx];
7195 *qdr_dds = &txdds_qdr[ppd->cpspec->no_eep]; 7032 *ddr_dds = &txdds_ddr[idx];
7033 *qdr_dds = &txdds_qdr[idx];
7034 } else if (ppd->cpspec->no_eep < (TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ)) {
7035 /* similar to above, but index into the "extra" table. */
7036 idx = ppd->cpspec->no_eep - TXDDS_TABLE_SZ;
7037 *sdr_dds = &txdds_extra_sdr[idx];
7038 *ddr_dds = &txdds_extra_ddr[idx];
7039 *qdr_dds = &txdds_extra_qdr[idx];
7040 } else {
7041 /* this shouldn't happen, it's range checked */
7042 *sdr_dds = txdds_sdr + qib_long_atten;
7043 *ddr_dds = txdds_ddr + qib_long_atten;
7044 *qdr_dds = txdds_qdr + qib_long_atten;
7196 } 7045 }
7197} 7046}
7198 7047
@@ -7203,33 +7052,24 @@ static void init_txdds_table(struct qib_pportdata *ppd, int override)
7203 int idx; 7052 int idx;
7204 int single_ent = 0; 7053 int single_ent = 0;
7205 7054
7206 if (IS_QMH(ppd->dd)) { 7055 find_best_ent(ppd, &sdr_dds, &ddr_dds, &qdr_dds, override);
7207 /* normally will be overridden, via setup_qmh() */ 7056
7208 sdr_dds = &qmh_sdr_txdds; 7057 /* for mez cards or override, use the selected value for all entries */
7209 ddr_dds = &qmh_ddr_txdds; 7058 if (!(ppd->dd->flags & QIB_HAS_QSFP) || override)
7210 qdr_dds = &qmh_qdr_txdds;
7211 single_ent = 1;
7212 } else if (IS_QME(ppd->dd)) {
7213 sdr_dds = &qme_sdr_txdds;
7214 ddr_dds = &qme_ddr_txdds;
7215 qdr_dds = &qme_qdr_txdds;
7216 single_ent = 1; 7059 single_ent = 1;
7217 } else
7218 find_best_ent(ppd, &sdr_dds, &ddr_dds, &qdr_dds, override);
7219 7060
7220 /* Fill in the first entry with the best entry found. */ 7061 /* Fill in the first entry with the best entry found. */
7221 set_txdds(ppd, 0, sdr_dds); 7062 set_txdds(ppd, 0, sdr_dds);
7222 set_txdds(ppd, TXDDS_TABLE_SZ, ddr_dds); 7063 set_txdds(ppd, TXDDS_TABLE_SZ, ddr_dds);
7223 set_txdds(ppd, 2 * TXDDS_TABLE_SZ, qdr_dds); 7064 set_txdds(ppd, 2 * TXDDS_TABLE_SZ, qdr_dds);
7224 7065 if (ppd->lflags & (QIBL_LINKINIT | QIBL_LINKARMED |
7225 /* 7066 QIBL_LINKACTIVE)) {
7226 * for our current speed, also write that value into the 7067 dds = (struct txdds_ent *)(ppd->link_speed_active ==
7227 * tx serdes registers. 7068 QIB_IB_QDR ? qdr_dds :
7228 */ 7069 (ppd->link_speed_active ==
7229 dds = (struct txdds_ent *)(ppd->link_speed_active == QIB_IB_QDR ? 7070 QIB_IB_DDR ? ddr_dds : sdr_dds));
7230 qdr_dds : (ppd->link_speed_active == 7071 write_tx_serdes_param(ppd, dds);
7231 QIB_IB_DDR ? ddr_dds : sdr_dds)); 7072 }
7232 write_tx_serdes_param(ppd, dds);
7233 7073
7234 /* Fill in the remaining entries with the default table values. */ 7074 /* Fill in the remaining entries with the default table values. */
7235 for (idx = 1; idx < ARRAY_SIZE(txdds_sdr); ++idx) { 7075 for (idx = 1; idx < ARRAY_SIZE(txdds_sdr); ++idx) {
@@ -7352,6 +7192,11 @@ static int serdes_7322_init(struct qib_pportdata *ppd)
7352 */ 7192 */
7353 init_txdds_table(ppd, 0); 7193 init_txdds_table(ppd, 0);
7354 7194
7195 /* ensure no tx overrides from earlier driver loads */
7196 qib_write_kreg_port(ppd, krp_tx_deemph_override,
7197 SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
7198 reset_tx_deemphasis_override));
7199
7355 /* Patch some SerDes defaults to "Better for IB" */ 7200 /* Patch some SerDes defaults to "Better for IB" */
7356 /* Timing Loop Bandwidth: cdr_timing[11:9] = 0 */ 7201 /* Timing Loop Bandwidth: cdr_timing[11:9] = 0 */
7357 ibsd_wr_allchans(ppd, 2, 0, BMASK(11, 9)); 7202 ibsd_wr_allchans(ppd, 2, 0, BMASK(11, 9));
@@ -7421,7 +7266,7 @@ static int serdes_7322_init(struct qib_pportdata *ppd)
7421 QDR_STATIC_ADAPT_DOWN_R1 : QDR_STATIC_ADAPT_DOWN); 7266 QDR_STATIC_ADAPT_DOWN_R1 : QDR_STATIC_ADAPT_DOWN);
7422 ppd->cpspec->qdr_dfe_on = 1; 7267 ppd->cpspec->qdr_dfe_on = 1;
7423 7268
7424 /* (FLoop LOS gate: PPM filter enabled */ 7269 /* FLoop LOS gate: PPM filter enabled */
7425 ibsd_wr_allchans(ppd, 38, 0 << 10, 1 << 10); 7270 ibsd_wr_allchans(ppd, 38, 0 << 10, 1 << 10);
7426 7271
7427 /* rx offset center enabled */ 7272 /* rx offset center enabled */
@@ -7486,68 +7331,39 @@ static void write_tx_serdes_param(struct qib_pportdata *ppd,
7486 SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, txc0_ena) | 7331 SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, txc0_ena) |
7487 SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, txcp1_ena) | 7332 SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, txcp1_ena) |
7488 SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, txcn1_ena)); 7333 SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, txcn1_ena));
7489 deemph |= 1ULL << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0, 7334
7490 tx_override_deemphasis_select); 7335 deemph |= SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
7491 deemph |= txdds->amp << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0, 7336 tx_override_deemphasis_select);
7492 txampcntl_d2a); 7337 deemph |= (txdds->amp & SYM_RMASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
7493 deemph |= txdds->main << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0, 7338 txampcntl_d2a)) << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
7494 txc0_ena); 7339 txampcntl_d2a);
7495 deemph |= txdds->post << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0, 7340 deemph |= (txdds->main & SYM_RMASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
7496 txcp1_ena); 7341 txc0_ena)) << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
7497 deemph |= txdds->pre << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0, 7342 txc0_ena);
7343 deemph |= (txdds->post & SYM_RMASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
7344 txcp1_ena)) << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
7345 txcp1_ena);
7346 deemph |= (txdds->pre & SYM_RMASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
7347 txcn1_ena)) << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
7498 txcn1_ena); 7348 txcn1_ena);
7499 qib_write_kreg_port(ppd, krp_tx_deemph_override, deemph); 7349 qib_write_kreg_port(ppd, krp_tx_deemph_override, deemph);
7500} 7350}
7501 7351
7502/* 7352/*
7503 * set per-bay, per channel parameters. For now, we ignore 7353 * Set the parameters for mez cards on link bounce, so they are
7504 * do_tx, and always set tx parameters, and set them with the same value 7354 * always exactly what was requested. Similar logic to init_txdds
7505 * for all channels, using the channel 0 value. We may switch to 7355 * but does just the serdes.
7506 * per-channel settings in the future, and that method only needs
7507 * to be done once.
7508 * Because this also writes the IBC txdds table with a single set
7509 * of values, it should be called only for cases where we want to completely
7510 * force a specific setting, typically only for mez cards.
7511 */ 7356 */
7512static void adj_tx_serdes(struct qib_pportdata *ppd) 7357static void adj_tx_serdes(struct qib_pportdata *ppd)
7513{ 7358{
7514 struct txdds_ent txdds; 7359 const struct txdds_ent *sdr_dds, *ddr_dds, *qdr_dds;
7515 int i; 7360 struct txdds_ent *dds;
7516 u8 *amp, *pre, *mainv, *post;
7517
7518 /*
7519 * Because we use TX_DEEMPHASIS_OVERRIDE, we need to
7520 * always do tx side, just like H1, since it is cleared
7521 * by link down
7522 */
7523 amp = ppd->cpspec->amp;
7524 pre = ppd->cpspec->pre;
7525 mainv = ppd->cpspec->mainv;
7526 post = ppd->cpspec->post;
7527
7528 amp[0] &= SYM_RMASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
7529 txampcntl_d2a);
7530 mainv[0] &= SYM_RMASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
7531 txc0_ena);
7532 post[0] &= SYM_RMASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
7533 txcp1_ena);
7534 pre[0] &= SYM_RMASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
7535 txcn1_ena);
7536
7537 /*
7538 * Use the channel zero values, only, for now, for
7539 * all channels
7540 */
7541 txdds.amp = amp[0];
7542 txdds.pre = pre[0];
7543 txdds.main = mainv[0];
7544 txdds.post = post[0];
7545
7546 /* write the QDR table for IBC use, as backup for link down */
7547 for (i = 0; i < ARRAY_SIZE(txdds_qdr); ++i)
7548 set_txdds(ppd, i + 32, &txdds);
7549 7361
7550 write_tx_serdes_param(ppd, &txdds); 7362 find_best_ent(ppd, &sdr_dds, &ddr_dds, &qdr_dds, 1);
7363 dds = (struct txdds_ent *)(ppd->link_speed_active == QIB_IB_QDR ?
7364 qdr_dds : (ppd->link_speed_active == QIB_IB_DDR ?
7365 ddr_dds : sdr_dds));
7366 write_tx_serdes_param(ppd, dds);
7551} 7367}
7552 7368
7553/* set QDR forced value for H1, if needed */ 7369/* set QDR forced value for H1, if needed */
@@ -7567,235 +7383,6 @@ static void force_h1(struct qib_pportdata *ppd)
7567 } 7383 }
7568} 7384}
7569 7385
7570/*
7571 * Parse the parameters for the QMH7342, to get rx and tx serdes
7572 * settings for that Bay, for both possible mez connectors (PCIe bus)
7573 * and IB link (one link on mez1, two possible on mez2).
7574 *
7575 * Data is comma or white space separated.
7576 *
7577 * A set of data has 7 groups, rx and tx groups have SERDES_CHANS values,
7578 * one per IB lane (serdes channel).
7579 * The groups are Bay, bus# H1 rcv, and amp, pre, post, main Tx values (QDR).
7580 * The Bay # is used only for debugging currently.
7581 * H1 values are set whenever the link goes down, or is at cfg_test or
7582 * cfg_wait_enh. Tx values are programmed once, when this routine is called
7583 * (and with default values at chip initialization). Values are any base, in
7584 * strtoul style, and values are seperated by comma, or any white space
7585 * (space, tab, newline).
7586 *
7587 * An example set might look like this (white space vs
7588 * comma used for human ease of reading)
7589 * The ordering is a set of Bay# Bus# H1, amp, pre, post, and main for mez1 IB1,
7590 * repeat for mez2 IB1, then mez2 IB2.
7591 *
7592 * B B H1:0 amp:0 pre:0 post: 0 main:0
7593 * a u H1: 1 amp: 1 pre: 1 post: 1 main: 1
7594 * y s H1: 2 amp: 2 pre: 2 post: 2 main: 2
7595 * H1: 4 amp: 3 pre: 3 post: 3 main: 3
7596 * 1 3 8,6,5,6 0,0,0,0 1,1,1,1 10,10,10,10 3,3,3,3
7597 * 1 6 7,6,6,7 0,0,0,0 1,1,1,1 10,10,10,10 3,3,3,3
7598 * 1 6 9,7,7,8 0,0,0,0 1,1,1,1 10,10,10,10 3,3,3,3
7599 */
7600#define N_QMH_FIELDS 22
7601static int setup_qmh_params(const char *str, struct kernel_param *kp)
7602{
7603 char *abuf, *v, *nv, *nvp;
7604 struct qib_devdata *dd;
7605 struct qib_pportdata *ppd;
7606 u32 mez, vlen, nf, port, bay;
7607 int ret = 0, found = 0;
7608
7609 vlen = strlen(str) + 1;
7610 abuf = kmalloc(vlen, GFP_KERNEL);
7611 if (!abuf) {
7612 printk(KERN_INFO QIB_DRV_NAME
7613 " Unable to allocate QMH param buffer; ignoring\n");
7614 return 0;
7615 }
7616 memcpy(abuf, str, vlen);
7617 v = abuf;
7618
7619 /* these 3 are because gcc can't know they are set before used */
7620 port = 1;
7621 mez = 1; /* used only for debugging */
7622 bay = 0; /* used only for debugging */
7623 ppd = NULL;
7624 for (nf = 0; (nv = strsep(&v, ", \t\n\r")) &&
7625 nf < (N_QMH_FIELDS * 3);) {
7626 u32 val;
7627
7628 if (!*nv)
7629 /* allow for multiple separators */
7630 continue;
7631
7632 val = simple_strtoul(nv, &nvp, 0);
7633 if (nv == nvp) {
7634 printk(KERN_INFO QIB_DRV_NAME
7635 " Bay%u, mez%u IB%u non-numeric value (%s) "
7636 "field #%u, ignoring rest\n", bay, mez,
7637 port, nv, nf % (N_QMH_FIELDS * 3));
7638 ret = -EINVAL;
7639 goto bail;
7640 }
7641 if (!(nf % N_QMH_FIELDS)) {
7642 ppd = NULL;
7643 bay = val;
7644 if (!bay || bay > 16) {
7645 printk(KERN_INFO QIB_DRV_NAME
7646 " Invalid bay # %u, field %u, "
7647 "ignoring rest\n", bay, nf);
7648 ret = -EINVAL;
7649 goto bail;
7650 }
7651 } else if ((nf % N_QMH_FIELDS) == 1) {
7652 u32 bus = val;
7653 if (nf == 1) {
7654 mez = 1;
7655 port = 1;
7656 } else if (nf == (N_QMH_FIELDS + 1)) {
7657 mez = 2;
7658 port = 1;
7659 } else {
7660 mez = 2;
7661 port = 2;
7662 }
7663 list_for_each_entry(dd, &qib_dev_list, list) {
7664 if (dd->deviceid != PCI_DEVICE_ID_QLOGIC_IB_7322
7665 || !IS_QMH(dd))
7666 continue; /* only for QMH cards */
7667 if (dd->pcidev->bus->number == bus) {
7668 found++;
7669 ppd = &dd->pport[port - 1];
7670 }
7671 }
7672 } else if (ppd) {
7673 u32 parm = (nf % N_QMH_FIELDS) - 2;
7674 if (parm < SERDES_CHANS && !(parm % SERDES_CHANS))
7675 ppd->cpspec->h1_val = val;
7676 else if (parm < (2 * SERDES_CHANS))
7677 ppd->cpspec->amp[parm % SERDES_CHANS] = val;
7678 else if (parm < (3 * SERDES_CHANS))
7679 ppd->cpspec->pre[parm % SERDES_CHANS] = val;
7680 else if (parm < (4 * SERDES_CHANS))
7681 ppd->cpspec->post[parm % SERDES_CHANS] = val;
7682 else {
7683 ppd->cpspec->mainv[parm % SERDES_CHANS] = val;
7684 /* At the end of a port, set params */
7685 if (parm == ((5 * SERDES_CHANS) - 1))
7686 adj_tx_serdes(ppd);
7687 }
7688 }
7689 nf++;
7690 }
7691 if (!found) {
7692 printk(KERN_ERR QIB_DRV_NAME
7693 ": No match found for qmh_serdes_setup parameter\n");
7694 ret = -EINVAL;
7695 }
7696bail:
7697 kfree(abuf);
7698 return ret;
7699}
7700
7701/*
7702 * Similarly for QME7342, but the format is simpler, values are the
7703 * same for all mez card positions in a blade (2 or 4 per blade), but
7704 * are different for some blades vs others, and we don't need to
7705 * specify different parameters for different serdes channels or different
7706 * IB ports.
7707 * Format is: h1 amp,pre,post,main
7708 * Alternate format (so ports can be different): Pport# h1 amp,pre,post,main
7709 */
7710#define N_QME_FIELDS 5
7711static int setup_qme_params(const char *str, struct kernel_param *kp)
7712{
7713 char *abuf, *v, *nv, *nvp;
7714 struct qib_devdata *dd;
7715 u32 vlen, nf, port = 0;
7716 u8 h1, tx[4]; /* amp, pre, post, main */
7717 int ret = -EINVAL;
7718 char *seplist;
7719
7720 vlen = strlen(str) + 1;
7721 abuf = kmalloc(vlen, GFP_KERNEL);
7722 if (!abuf) {
7723 printk(KERN_INFO QIB_DRV_NAME
7724 " Unable to allocate QME param buffer; ignoring\n");
7725 return 0;
7726 }
7727 strncpy(abuf, str, vlen);
7728
7729 v = abuf;
7730 seplist = " \t";
7731 h1 = H1_FORCE_QME; /* gcc can't figure out always set before used */
7732
7733 for (nf = 0; (nv = strsep(&v, seplist)); ) {
7734 u32 val;
7735
7736 if (!*nv)
7737 /* allow for multiple separators */
7738 continue;
7739
7740 if (!nf && *nv == 'P') {
7741 /* alternate format with port */
7742 val = simple_strtoul(++nv, &nvp, 0);
7743 if (nv == nvp || port >= NUM_IB_PORTS) {
7744 printk(KERN_INFO QIB_DRV_NAME
7745 " %s: non-numeric port value (%s) "
7746 "ignoring rest\n", __func__, nv);
7747 goto done;
7748 }
7749 port = val;
7750 continue; /* without incrementing nf */
7751 }
7752 val = simple_strtoul(nv, &nvp, 0);
7753 if (nv == nvp) {
7754 printk(KERN_INFO QIB_DRV_NAME
7755 " %s: non-numeric value (%s) "
7756 "field #%u, ignoring rest\n", __func__,
7757 nv, nf);
7758 goto done;
7759 }
7760 if (!nf) {
7761 h1 = val;
7762 seplist = ",";
7763 } else
7764 tx[nf - 1] = val;
7765 if (++nf == N_QME_FIELDS) {
7766 list_for_each_entry(dd, &qib_dev_list, list) {
7767 int pidx, i;
7768 if (dd->deviceid != PCI_DEVICE_ID_QLOGIC_IB_7322
7769 || !IS_QME(dd))
7770 continue; /* only for QME cards */
7771 for (pidx = 0; pidx < dd->num_pports; ++pidx) {
7772 struct qib_pportdata *ppd;
7773 ppd = &dd->pport[pidx];
7774 if ((port && ppd->port != port) ||
7775 !ppd->link_speed_supported)
7776 continue;
7777 ppd->cpspec->h1_val = h1;
7778 for (i = 0; i < SERDES_CHANS; i++) {
7779 ppd->cpspec->amp[i] = tx[0];
7780 ppd->cpspec->pre[i] = tx[1];
7781 ppd->cpspec->post[i] = tx[2];
7782 ppd->cpspec->mainv[i] = tx[3];
7783 }
7784 adj_tx_serdes(ppd);
7785 }
7786 }
7787 ret = 0;
7788 goto done;
7789 }
7790 }
7791 printk(KERN_INFO QIB_DRV_NAME
7792 " %s: Only %u of %u fields provided, skipping\n",
7793 __func__, nf, N_QME_FIELDS);
7794done:
7795 kfree(abuf);
7796 return ret;
7797}
7798
7799#define SJA_EN SYM_MASK(SPC_JTAG_ACCESS_REG, SPC_JTAG_ACCESS_EN) 7386#define SJA_EN SYM_MASK(SPC_JTAG_ACCESS_REG, SPC_JTAG_ACCESS_EN)
7800#define BISTEN_LSB SYM_LSB(SPC_JTAG_ACCESS_REG, bist_en) 7387#define BISTEN_LSB SYM_LSB(SPC_JTAG_ACCESS_REG, bist_en)
7801 7388
diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c
index c0139c07e97e..9b40f345ac3f 100644
--- a/drivers/infiniband/hw/qib/qib_init.c
+++ b/drivers/infiniband/hw/qib/qib_init.c
@@ -1237,7 +1237,13 @@ static int __devinit qib_init_one(struct pci_dev *pdev,
1237 */ 1237 */
1238 switch (ent->device) { 1238 switch (ent->device) {
1239 case PCI_DEVICE_ID_QLOGIC_IB_6120: 1239 case PCI_DEVICE_ID_QLOGIC_IB_6120:
1240#ifdef CONFIG_PCI_MSI
1240 dd = qib_init_iba6120_funcs(pdev, ent); 1241 dd = qib_init_iba6120_funcs(pdev, ent);
1242#else
1243 qib_early_err(&pdev->dev, "QLogic PCIE device 0x%x cannot "
1244 "work if CONFIG_PCI_MSI is not enabled\n",
1245 ent->device);
1246#endif
1241 break; 1247 break;
1242 1248
1243 case PCI_DEVICE_ID_QLOGIC_IB_7220: 1249 case PCI_DEVICE_ID_QLOGIC_IB_7220:
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index 423e0e6031ab..34157bb97ed6 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -47,15 +47,15 @@ struct joydev {
47 struct mutex mutex; 47 struct mutex mutex;
48 struct device dev; 48 struct device dev;
49 49
50 struct js_corr corr[ABS_MAX + 1]; 50 struct js_corr corr[ABS_CNT];
51 struct JS_DATA_SAVE_TYPE glue; 51 struct JS_DATA_SAVE_TYPE glue;
52 int nabs; 52 int nabs;
53 int nkey; 53 int nkey;
54 __u16 keymap[KEY_MAX - BTN_MISC + 1]; 54 __u16 keymap[KEY_MAX - BTN_MISC + 1];
55 __u16 keypam[KEY_MAX - BTN_MISC + 1]; 55 __u16 keypam[KEY_MAX - BTN_MISC + 1];
56 __u8 absmap[ABS_MAX + 1]; 56 __u8 absmap[ABS_CNT];
57 __u8 abspam[ABS_MAX + 1]; 57 __u8 abspam[ABS_CNT];
58 __s16 abs[ABS_MAX + 1]; 58 __s16 abs[ABS_CNT];
59}; 59};
60 60
61struct joydev_client { 61struct joydev_client {
@@ -826,7 +826,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
826 joydev->handle.handler = handler; 826 joydev->handle.handler = handler;
827 joydev->handle.private = joydev; 827 joydev->handle.private = joydev;
828 828
829 for (i = 0; i < ABS_MAX + 1; i++) 829 for (i = 0; i < ABS_CNT; i++)
830 if (test_bit(i, dev->absbit)) { 830 if (test_bit(i, dev->absbit)) {
831 joydev->absmap[i] = joydev->nabs; 831 joydev->absmap[i] = joydev->nabs;
832 joydev->abspam[joydev->nabs] = i; 832 joydev->abspam[joydev->nabs] = i;
diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c
index 4771ab172b59..744600eff222 100644
--- a/drivers/input/keyboard/adp5588-keys.c
+++ b/drivers/input/keyboard/adp5588-keys.c
@@ -287,7 +287,6 @@ static int __devexit adp5588_remove(struct i2c_client *client)
287 free_irq(client->irq, kpad); 287 free_irq(client->irq, kpad);
288 cancel_delayed_work_sync(&kpad->work); 288 cancel_delayed_work_sync(&kpad->work);
289 input_unregister_device(kpad->input); 289 input_unregister_device(kpad->input);
290 i2c_set_clientdata(client, NULL);
291 kfree(kpad); 290 kfree(kpad);
292 291
293 return 0; 292 return 0;
diff --git a/drivers/input/keyboard/amikbd.c b/drivers/input/keyboard/amikbd.c
index 35149ec455a9..79172af164f2 100644
--- a/drivers/input/keyboard/amikbd.c
+++ b/drivers/input/keyboard/amikbd.c
@@ -35,6 +35,7 @@
35#include <linux/delay.h> 35#include <linux/delay.h>
36#include <linux/interrupt.h> 36#include <linux/interrupt.h>
37#include <linux/keyboard.h> 37#include <linux/keyboard.h>
38#include <linux/platform_device.h>
38 39
39#include <asm/amigaints.h> 40#include <asm/amigaints.h>
40#include <asm/amigahw.h> 41#include <asm/amigahw.h>
@@ -154,10 +155,9 @@ static const char *amikbd_messages[8] = {
154 [7] = KERN_WARNING "amikbd: keyboard interrupt\n" 155 [7] = KERN_WARNING "amikbd: keyboard interrupt\n"
155}; 156};
156 157
157static struct input_dev *amikbd_dev; 158static irqreturn_t amikbd_interrupt(int irq, void *data)
158
159static irqreturn_t amikbd_interrupt(int irq, void *dummy)
160{ 159{
160 struct input_dev *dev = data;
161 unsigned char scancode, down; 161 unsigned char scancode, down;
162 162
163 scancode = ~ciaa.sdr; /* get and invert scancode (keyboard is active low) */ 163 scancode = ~ciaa.sdr; /* get and invert scancode (keyboard is active low) */
@@ -170,47 +170,42 @@ static irqreturn_t amikbd_interrupt(int irq, void *dummy)
170 170
171 if (scancode < 0x78) { /* scancodes < 0x78 are keys */ 171 if (scancode < 0x78) { /* scancodes < 0x78 are keys */
172 if (scancode == 98) { /* CapsLock is a toggle switch key on Amiga */ 172 if (scancode == 98) { /* CapsLock is a toggle switch key on Amiga */
173 input_report_key(amikbd_dev, scancode, 1); 173 input_report_key(dev, scancode, 1);
174 input_report_key(amikbd_dev, scancode, 0); 174 input_report_key(dev, scancode, 0);
175 } else { 175 } else {
176 input_report_key(amikbd_dev, scancode, down); 176 input_report_key(dev, scancode, down);
177 } 177 }
178 178
179 input_sync(amikbd_dev); 179 input_sync(dev);
180 } else /* scancodes >= 0x78 are error codes */ 180 } else /* scancodes >= 0x78 are error codes */
181 printk(amikbd_messages[scancode - 0x78]); 181 printk(amikbd_messages[scancode - 0x78]);
182 182
183 return IRQ_HANDLED; 183 return IRQ_HANDLED;
184} 184}
185 185
186static int __init amikbd_init(void) 186static int __init amikbd_probe(struct platform_device *pdev)
187{ 187{
188 struct input_dev *dev;
188 int i, j, err; 189 int i, j, err;
189 190
190 if (!AMIGAHW_PRESENT(AMI_KEYBOARD)) 191 dev = input_allocate_device();
191 return -ENODEV; 192 if (!dev) {
192 193 dev_err(&pdev->dev, "Not enough memory for input device\n");
193 if (!request_mem_region(CIAA_PHYSADDR-1+0xb00, 0x100, "amikeyb")) 194 return -ENOMEM;
194 return -EBUSY;
195
196 amikbd_dev = input_allocate_device();
197 if (!amikbd_dev) {
198 printk(KERN_ERR "amikbd: not enough memory for input device\n");
199 err = -ENOMEM;
200 goto fail1;
201 } 195 }
202 196
203 amikbd_dev->name = "Amiga Keyboard"; 197 dev->name = pdev->name;
204 amikbd_dev->phys = "amikbd/input0"; 198 dev->phys = "amikbd/input0";
205 amikbd_dev->id.bustype = BUS_AMIGA; 199 dev->id.bustype = BUS_AMIGA;
206 amikbd_dev->id.vendor = 0x0001; 200 dev->id.vendor = 0x0001;
207 amikbd_dev->id.product = 0x0001; 201 dev->id.product = 0x0001;
208 amikbd_dev->id.version = 0x0100; 202 dev->id.version = 0x0100;
203 dev->dev.parent = &pdev->dev;
209 204
210 amikbd_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); 205 dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
211 206
212 for (i = 0; i < 0x78; i++) 207 for (i = 0; i < 0x78; i++)
213 set_bit(i, amikbd_dev->keybit); 208 set_bit(i, dev->keybit);
214 209
215 for (i = 0; i < MAX_NR_KEYMAPS; i++) { 210 for (i = 0; i < MAX_NR_KEYMAPS; i++) {
216 static u_short temp_map[NR_KEYS] __initdata; 211 static u_short temp_map[NR_KEYS] __initdata;
@@ -229,30 +224,54 @@ static int __init amikbd_init(void)
229 memcpy(key_maps[i], temp_map, sizeof(temp_map)); 224 memcpy(key_maps[i], temp_map, sizeof(temp_map));
230 } 225 }
231 ciaa.cra &= ~0x41; /* serial data in, turn off TA */ 226 ciaa.cra &= ~0x41; /* serial data in, turn off TA */
232 if (request_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt, 0, "amikbd", 227 err = request_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt, 0, "amikbd",
233 amikbd_interrupt)) { 228 dev);
234 err = -EBUSY; 229 if (err)
235 goto fail2; 230 goto fail2;
236 }
237 231
238 err = input_register_device(amikbd_dev); 232 err = input_register_device(dev);
239 if (err) 233 if (err)
240 goto fail3; 234 goto fail3;
241 235
236 platform_set_drvdata(pdev, dev);
237
242 return 0; 238 return 0;
243 239
244 fail3: free_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt); 240 fail3: free_irq(IRQ_AMIGA_CIAA_SP, dev);
245 fail2: input_free_device(amikbd_dev); 241 fail2: input_free_device(dev);
246 fail1: release_mem_region(CIAA_PHYSADDR - 1 + 0xb00, 0x100);
247 return err; 242 return err;
248} 243}
249 244
250static void __exit amikbd_exit(void) 245static int __exit amikbd_remove(struct platform_device *pdev)
246{
247 struct input_dev *dev = platform_get_drvdata(pdev);
248
249 platform_set_drvdata(pdev, NULL);
250 free_irq(IRQ_AMIGA_CIAA_SP, dev);
251 input_unregister_device(dev);
252 return 0;
253}
254
255static struct platform_driver amikbd_driver = {
256 .remove = __exit_p(amikbd_remove),
257 .driver = {
258 .name = "amiga-keyboard",
259 .owner = THIS_MODULE,
260 },
261};
262
263static int __init amikbd_init(void)
251{ 264{
252 free_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt); 265 return platform_driver_probe(&amikbd_driver, amikbd_probe);
253 input_unregister_device(amikbd_dev);
254 release_mem_region(CIAA_PHYSADDR - 1 + 0xb00, 0x100);
255} 266}
256 267
257module_init(amikbd_init); 268module_init(amikbd_init);
269
270static void __exit amikbd_exit(void)
271{
272 platform_driver_unregister(&amikbd_driver);
273}
274
258module_exit(amikbd_exit); 275module_exit(amikbd_exit);
276
277MODULE_ALIAS("platform:amiga-keyboard");
diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c
index bc696931fed7..40b032f0e32c 100644
--- a/drivers/input/keyboard/lm8323.c
+++ b/drivers/input/keyboard/lm8323.c
@@ -778,8 +778,6 @@ static int __devexit lm8323_remove(struct i2c_client *client)
778 struct lm8323_chip *lm = i2c_get_clientdata(client); 778 struct lm8323_chip *lm = i2c_get_clientdata(client);
779 int i; 779 int i;
780 780
781 i2c_set_clientdata(client, NULL);
782
783 disable_irq_wake(client->irq); 781 disable_irq_wake(client->irq);
784 free_irq(client->irq, lm); 782 free_irq(client->irq, lm);
785 cancel_work_sync(&lm->work); 783 cancel_work_sync(&lm->work);
diff --git a/drivers/input/keyboard/max7359_keypad.c b/drivers/input/keyboard/max7359_keypad.c
index 7fc8185e5c1b..9091ff5ea808 100644
--- a/drivers/input/keyboard/max7359_keypad.c
+++ b/drivers/input/keyboard/max7359_keypad.c
@@ -265,7 +265,6 @@ static int __devexit max7359_remove(struct i2c_client *client)
265 265
266 free_irq(client->irq, keypad); 266 free_irq(client->irq, keypad);
267 input_unregister_device(keypad->input_dev); 267 input_unregister_device(keypad->input_dev);
268 i2c_set_clientdata(client, NULL);
269 kfree(keypad); 268 kfree(keypad);
270 269
271 return 0; 270 return 0;
diff --git a/drivers/input/keyboard/qt2160.c b/drivers/input/keyboard/qt2160.c
index 31f30087b591..fac695157e8a 100644
--- a/drivers/input/keyboard/qt2160.c
+++ b/drivers/input/keyboard/qt2160.c
@@ -358,7 +358,6 @@ static int __devexit qt2160_remove(struct i2c_client *client)
358 input_unregister_device(qt2160->input); 358 input_unregister_device(qt2160->input);
359 kfree(qt2160); 359 kfree(qt2160);
360 360
361 i2c_set_clientdata(client, NULL);
362 return 0; 361 return 0;
363} 362}
364 363
diff --git a/drivers/input/keyboard/tca6416-keypad.c b/drivers/input/keyboard/tca6416-keypad.c
index 493c93f25e2a..00137bebcf97 100644
--- a/drivers/input/keyboard/tca6416-keypad.c
+++ b/drivers/input/keyboard/tca6416-keypad.c
@@ -316,8 +316,6 @@ static int __devexit tca6416_keypad_remove(struct i2c_client *client)
316 input_unregister_device(chip->input); 316 input_unregister_device(chip->input);
317 kfree(chip); 317 kfree(chip);
318 318
319 i2c_set_clientdata(client, NULL);
320
321 return 0; 319 return 0;
322} 320}
323 321
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 48cdabec372a..c44b9eafc556 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -80,6 +80,16 @@ config INPUT_M68K_BEEP
80 tristate "M68k Beeper support" 80 tristate "M68k Beeper support"
81 depends on M68K 81 depends on M68K
82 82
83config INPUT_MAX8925_ONKEY
84 tristate "MAX8925 ONKEY support"
85 depends on MFD_MAX8925
86 help
87 Support the ONKEY of MAX8925 PMICs as an input device
88 reporting power button status.
89
90 To compile this driver as a module, choose M here: the module
91 will be called max8925_onkey.
92
83config INPUT_APANEL 93config INPUT_APANEL
84 tristate "Fujitsu Lifebook Application Panel buttons" 94 tristate "Fujitsu Lifebook Application Panel buttons"
85 depends on X86 && I2C && LEDS_CLASS 95 depends on X86 && I2C && LEDS_CLASS
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index f9f577031e06..71fe57d8023f 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o
20obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o 20obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o
21obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o 21obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o
22obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o 22obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o
23obj-$(CONFIG_INPUT_MAX8925_ONKEY) += max8925_onkey.o
23obj-$(CONFIG_INPUT_PCAP) += pcap_keys.o 24obj-$(CONFIG_INPUT_PCAP) += pcap_keys.o
24obj-$(CONFIG_INPUT_PCF50633_PMU) += pcf50633-input.o 25obj-$(CONFIG_INPUT_PCF50633_PMU) += pcf50633-input.o
25obj-$(CONFIG_INPUT_PCF8574) += pcf8574_keypad.o 26obj-$(CONFIG_INPUT_PCF8574) += pcf8574_keypad.o
diff --git a/drivers/input/misc/ad714x-i2c.c b/drivers/input/misc/ad714x-i2c.c
index e9adbe49f6a4..2bef8fa56c94 100644
--- a/drivers/input/misc/ad714x-i2c.c
+++ b/drivers/input/misc/ad714x-i2c.c
@@ -97,7 +97,6 @@ static int __devexit ad714x_i2c_remove(struct i2c_client *client)
97 struct ad714x_chip *chip = i2c_get_clientdata(client); 97 struct ad714x_chip *chip = i2c_get_clientdata(client);
98 98
99 ad714x_remove(chip); 99 ad714x_remove(chip);
100 i2c_set_clientdata(client, NULL);
101 100
102 return 0; 101 return 0;
103} 102}
diff --git a/drivers/input/misc/hp_sdc_rtc.c b/drivers/input/misc/hp_sdc_rtc.c
index e00a1cc79c0a..c19066479057 100644
--- a/drivers/input/misc/hp_sdc_rtc.c
+++ b/drivers/input/misc/hp_sdc_rtc.c
@@ -678,7 +678,7 @@ static const struct file_operations hp_sdc_rtc_fops = {
678 .llseek = no_llseek, 678 .llseek = no_llseek,
679 .read = hp_sdc_rtc_read, 679 .read = hp_sdc_rtc_read,
680 .poll = hp_sdc_rtc_poll, 680 .poll = hp_sdc_rtc_poll,
681 .unlocked_ioctl = hp_sdc_rtc_ioctl, 681 .unlocked_ioctl = hp_sdc_rtc_unlocked_ioctl,
682 .open = hp_sdc_rtc_open, 682 .open = hp_sdc_rtc_open,
683 .fasync = hp_sdc_rtc_fasync, 683 .fasync = hp_sdc_rtc_fasync,
684}; 684};
diff --git a/drivers/input/misc/max8925_onkey.c b/drivers/input/misc/max8925_onkey.c
new file mode 100644
index 000000000000..80af44608018
--- /dev/null
+++ b/drivers/input/misc/max8925_onkey.c
@@ -0,0 +1,148 @@
1/**
2 * max8925_onkey.c - MAX8925 ONKEY driver
3 *
4 * Copyright (C) 2009 Marvell International Ltd.
5 * Haojian Zhuang <haojian.zhuang@marvell.com>
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file "COPYING" in the main directory of this
9 * archive for more details.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include <linux/kernel.h>
22#include <linux/module.h>
23#include <linux/platform_device.h>
24#include <linux/i2c.h>
25#include <linux/input.h>
26#include <linux/interrupt.h>
27#include <linux/mfd/max8925.h>
28#include <linux/slab.h>
29
30#define HARDRESET_EN (1 << 7)
31#define PWREN_EN (1 << 7)
32
33struct max8925_onkey_info {
34 struct input_dev *idev;
35 struct i2c_client *i2c;
36 int irq;
37};
38
39/*
40 * MAX8925 gives us an interrupt when ONKEY is held for 3 seconds.
41 * max8925_set_bits() operates I2C bus and may sleep. So implement
42 * it in thread IRQ handler.
43 */
44static irqreturn_t max8925_onkey_handler(int irq, void *data)
45{
46 struct max8925_onkey_info *info = data;
47
48 input_report_key(info->idev, KEY_POWER, 1);
49 input_sync(info->idev);
50
51 /* Enable hardreset to halt if system isn't shutdown on time */
52 max8925_set_bits(info->i2c, MAX8925_SYSENSEL,
53 HARDRESET_EN, HARDRESET_EN);
54
55 return IRQ_HANDLED;
56}
57
58static int __devinit max8925_onkey_probe(struct platform_device *pdev)
59{
60 struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
61 struct max8925_onkey_info *info;
62 int error;
63
64 info = kzalloc(sizeof(struct max8925_onkey_info), GFP_KERNEL);
65 if (!info)
66 return -ENOMEM;
67
68 info->i2c = chip->i2c;
69 info->irq = chip->irq_base + MAX8925_IRQ_GPM_SW_3SEC;
70
71 info->idev = input_allocate_device();
72 if (!info->idev) {
73 dev_err(chip->dev, "Failed to allocate input dev\n");
74 error = -ENOMEM;
75 goto out_input;
76 }
77
78 info->idev->name = "max8925_on";
79 info->idev->phys = "max8925_on/input0";
80 info->idev->id.bustype = BUS_I2C;
81 info->idev->dev.parent = &pdev->dev;
82 info->idev->evbit[0] = BIT_MASK(EV_KEY);
83 info->idev->keybit[BIT_WORD(KEY_POWER)] = BIT_MASK(KEY_POWER);
84
85 error = request_threaded_irq(info->irq, NULL, max8925_onkey_handler,
86 IRQF_ONESHOT, "onkey", info);
87 if (error < 0) {
88 dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n",
89 info->irq, error);
90 goto out_irq;
91 }
92
93 error = input_register_device(info->idev);
94 if (error) {
95 dev_err(chip->dev, "Can't register input device: %d\n", error);
96 goto out;
97 }
98
99 platform_set_drvdata(pdev, info);
100
101 return 0;
102
103out:
104 free_irq(info->irq, info);
105out_irq:
106 input_free_device(info->idev);
107out_input:
108 kfree(info);
109 return error;
110}
111
112static int __devexit max8925_onkey_remove(struct platform_device *pdev)
113{
114 struct max8925_onkey_info *info = platform_get_drvdata(pdev);
115
116 free_irq(info->irq, info);
117 input_unregister_device(info->idev);
118 kfree(info);
119
120 platform_set_drvdata(pdev, NULL);
121
122 return 0;
123}
124
125static struct platform_driver max8925_onkey_driver = {
126 .driver = {
127 .name = "max8925-onkey",
128 .owner = THIS_MODULE,
129 },
130 .probe = max8925_onkey_probe,
131 .remove = __devexit_p(max8925_onkey_remove),
132};
133
134static int __init max8925_onkey_init(void)
135{
136 return platform_driver_register(&max8925_onkey_driver);
137}
138module_init(max8925_onkey_init);
139
140static void __exit max8925_onkey_exit(void)
141{
142 platform_driver_unregister(&max8925_onkey_driver);
143}
144module_exit(max8925_onkey_exit);
145
146MODULE_DESCRIPTION("Maxim MAX8925 ONKEY driver");
147MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
148MODULE_LICENSE("GPL");
diff --git a/drivers/input/misc/pcf8574_keypad.c b/drivers/input/misc/pcf8574_keypad.c
index 5c3ac4e0b055..0ac47d2898ec 100644
--- a/drivers/input/misc/pcf8574_keypad.c
+++ b/drivers/input/misc/pcf8574_keypad.c
@@ -168,8 +168,6 @@ static int __devexit pcf8574_kp_remove(struct i2c_client *client)
168 input_unregister_device(lp->idev); 168 input_unregister_device(lp->idev);
169 kfree(lp); 169 kfree(lp);
170 170
171 i2c_set_clientdata(client, NULL);
172
173 return 0; 171 return 0;
174} 172}
175 173
diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c
index fee9eac8e04a..4f9b2afc24e8 100644
--- a/drivers/input/misc/twl4030-vibra.c
+++ b/drivers/input/misc/twl4030-vibra.c
@@ -90,8 +90,8 @@ static void vibra_disable(struct vibra_info *info)
90 twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, 90 twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
91 (reg & ~TWL4030_VIBRA_EN), TWL4030_REG_VIBRA_CTL); 91 (reg & ~TWL4030_VIBRA_EN), TWL4030_REG_VIBRA_CTL);
92 92
93 twl4030_codec_disable_resource(TWL4030_CODEC_RES_POWER);
94 twl4030_codec_disable_resource(TWL4030_CODEC_RES_APLL); 93 twl4030_codec_disable_resource(TWL4030_CODEC_RES_APLL);
94 twl4030_codec_disable_resource(TWL4030_CODEC_RES_POWER);
95 95
96 info->enabled = false; 96 info->enabled = false;
97} 97}
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index 1477466076ad..b71eb55f2dbc 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -300,7 +300,7 @@ static int uinput_validate_absbits(struct input_dev *dev)
300 unsigned int cnt; 300 unsigned int cnt;
301 int retval = 0; 301 int retval = 0;
302 302
303 for (cnt = 0; cnt < ABS_MAX + 1; cnt++) { 303 for (cnt = 0; cnt < ABS_CNT; cnt++) {
304 if (!test_bit(cnt, dev->absbit)) 304 if (!test_bit(cnt, dev->absbit))
305 continue; 305 continue;
306 306
@@ -387,7 +387,7 @@ static int uinput_setup_device(struct uinput_device *udev, const char __user *bu
387 dev->id.product = user_dev->id.product; 387 dev->id.product = user_dev->id.product;
388 dev->id.version = user_dev->id.version; 388 dev->id.version = user_dev->id.version;
389 389
390 size = sizeof(int) * (ABS_MAX + 1); 390 size = sizeof(int) * ABS_CNT;
391 memcpy(dev->absmax, user_dev->absmax, size); 391 memcpy(dev->absmax, user_dev->absmax, size);
392 memcpy(dev->absmin, user_dev->absmin, size); 392 memcpy(dev->absmin, user_dev->absmin, size);
393 memcpy(dev->absfuzz, user_dev->absfuzz, size); 393 memcpy(dev->absfuzz, user_dev->absfuzz, size);
diff --git a/drivers/input/mouse/amimouse.c b/drivers/input/mouse/amimouse.c
index a185ac78a42c..ff5f61a0fd3a 100644
--- a/drivers/input/mouse/amimouse.c
+++ b/drivers/input/mouse/amimouse.c
@@ -21,6 +21,7 @@
21#include <linux/init.h> 21#include <linux/init.h>
22#include <linux/input.h> 22#include <linux/input.h>
23#include <linux/interrupt.h> 23#include <linux/interrupt.h>
24#include <linux/platform_device.h>
24 25
25#include <asm/irq.h> 26#include <asm/irq.h>
26#include <asm/setup.h> 27#include <asm/setup.h>
@@ -34,10 +35,10 @@ MODULE_DESCRIPTION("Amiga mouse driver");
34MODULE_LICENSE("GPL"); 35MODULE_LICENSE("GPL");
35 36
36static int amimouse_lastx, amimouse_lasty; 37static int amimouse_lastx, amimouse_lasty;
37static struct input_dev *amimouse_dev;
38 38
39static irqreturn_t amimouse_interrupt(int irq, void *dummy) 39static irqreturn_t amimouse_interrupt(int irq, void *data)
40{ 40{
41 struct input_dev *dev = data;
41 unsigned short joy0dat, potgor; 42 unsigned short joy0dat, potgor;
42 int nx, ny, dx, dy; 43 int nx, ny, dx, dy;
43 44
@@ -59,14 +60,14 @@ static irqreturn_t amimouse_interrupt(int irq, void *dummy)
59 60
60 potgor = amiga_custom.potgor; 61 potgor = amiga_custom.potgor;
61 62
62 input_report_rel(amimouse_dev, REL_X, dx); 63 input_report_rel(dev, REL_X, dx);
63 input_report_rel(amimouse_dev, REL_Y, dy); 64 input_report_rel(dev, REL_Y, dy);
64 65
65 input_report_key(amimouse_dev, BTN_LEFT, ciaa.pra & 0x40); 66 input_report_key(dev, BTN_LEFT, ciaa.pra & 0x40);
66 input_report_key(amimouse_dev, BTN_MIDDLE, potgor & 0x0100); 67 input_report_key(dev, BTN_MIDDLE, potgor & 0x0100);
67 input_report_key(amimouse_dev, BTN_RIGHT, potgor & 0x0400); 68 input_report_key(dev, BTN_RIGHT, potgor & 0x0400);
68 69
69 input_sync(amimouse_dev); 70 input_sync(dev);
70 71
71 return IRQ_HANDLED; 72 return IRQ_HANDLED;
72} 73}
@@ -74,63 +75,90 @@ static irqreturn_t amimouse_interrupt(int irq, void *dummy)
74static int amimouse_open(struct input_dev *dev) 75static int amimouse_open(struct input_dev *dev)
75{ 76{
76 unsigned short joy0dat; 77 unsigned short joy0dat;
78 int error;
77 79
78 joy0dat = amiga_custom.joy0dat; 80 joy0dat = amiga_custom.joy0dat;
79 81
80 amimouse_lastx = joy0dat & 0xff; 82 amimouse_lastx = joy0dat & 0xff;
81 amimouse_lasty = joy0dat >> 8; 83 amimouse_lasty = joy0dat >> 8;
82 84
83 if (request_irq(IRQ_AMIGA_VERTB, amimouse_interrupt, 0, "amimouse", amimouse_interrupt)) { 85 error = request_irq(IRQ_AMIGA_VERTB, amimouse_interrupt, 0, "amimouse",
84 printk(KERN_ERR "amimouse.c: Can't allocate irq %d\n", IRQ_AMIGA_VERTB); 86 dev);
85 return -EBUSY; 87 if (error)
86 } 88 dev_err(&dev->dev, "Can't allocate irq %d\n", IRQ_AMIGA_VERTB);
87 89
88 return 0; 90 return error;
89} 91}
90 92
91static void amimouse_close(struct input_dev *dev) 93static void amimouse_close(struct input_dev *dev)
92{ 94{
93 free_irq(IRQ_AMIGA_VERTB, amimouse_interrupt); 95 free_irq(IRQ_AMIGA_VERTB, dev);
94} 96}
95 97
96static int __init amimouse_init(void) 98static int __init amimouse_probe(struct platform_device *pdev)
97{ 99{
98 int err; 100 int err;
101 struct input_dev *dev;
99 102
100 if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_MOUSE)) 103 dev = input_allocate_device();
101 return -ENODEV; 104 if (!dev)
102
103 amimouse_dev = input_allocate_device();
104 if (!amimouse_dev)
105 return -ENOMEM; 105 return -ENOMEM;
106 106
107 amimouse_dev->name = "Amiga mouse"; 107 dev->name = pdev->name;
108 amimouse_dev->phys = "amimouse/input0"; 108 dev->phys = "amimouse/input0";
109 amimouse_dev->id.bustype = BUS_AMIGA; 109 dev->id.bustype = BUS_AMIGA;
110 amimouse_dev->id.vendor = 0x0001; 110 dev->id.vendor = 0x0001;
111 amimouse_dev->id.product = 0x0002; 111 dev->id.product = 0x0002;
112 amimouse_dev->id.version = 0x0100; 112 dev->id.version = 0x0100;
113 113
114 amimouse_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); 114 dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
115 amimouse_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); 115 dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
116 amimouse_dev->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) | 116 dev->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) |
117 BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); 117 BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
118 amimouse_dev->open = amimouse_open; 118 dev->open = amimouse_open;
119 amimouse_dev->close = amimouse_close; 119 dev->close = amimouse_close;
120 dev->dev.parent = &pdev->dev;
120 121
121 err = input_register_device(amimouse_dev); 122 err = input_register_device(dev);
122 if (err) { 123 if (err) {
123 input_free_device(amimouse_dev); 124 input_free_device(dev);
124 return err; 125 return err;
125 } 126 }
126 127
128 platform_set_drvdata(pdev, dev);
129
127 return 0; 130 return 0;
128} 131}
129 132
130static void __exit amimouse_exit(void) 133static int __exit amimouse_remove(struct platform_device *pdev)
131{ 134{
132 input_unregister_device(amimouse_dev); 135 struct input_dev *dev = platform_get_drvdata(pdev);
136
137 platform_set_drvdata(pdev, NULL);
138 input_unregister_device(dev);
139 return 0;
140}
141
142static struct platform_driver amimouse_driver = {
143 .remove = __exit_p(amimouse_remove),
144 .driver = {
145 .name = "amiga-mouse",
146 .owner = THIS_MODULE,
147 },
148};
149
150static int __init amimouse_init(void)
151{
152 return platform_driver_probe(&amimouse_driver, amimouse_probe);
133} 153}
134 154
135module_init(amimouse_init); 155module_init(amimouse_init);
156
157static void __exit amimouse_exit(void)
158{
159 platform_driver_unregister(&amimouse_driver);
160}
161
136module_exit(amimouse_exit); 162module_exit(amimouse_exit);
163
164MODULE_ALIAS("platform:amiga-mouse");
diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c
index 8291e7399ffa..0ae62f0bcb32 100644
--- a/drivers/input/mouse/synaptics_i2c.c
+++ b/drivers/input/mouse/synaptics_i2c.c
@@ -613,7 +613,6 @@ static int __devexit synaptics_i2c_remove(struct i2c_client *client)
613 free_irq(client->irq, touch); 613 free_irq(client->irq, touch);
614 614
615 input_unregister_device(touch->input); 615 input_unregister_device(touch->input);
616 i2c_set_clientdata(client, NULL);
617 kfree(touch); 616 kfree(touch);
618 617
619 return 0; 618 return 0;
diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
index f34f1dbeb577..3bfe8fafc6ad 100644
--- a/drivers/input/serio/Kconfig
+++ b/drivers/input/serio/Kconfig
@@ -21,7 +21,8 @@ if SERIO
21config SERIO_I8042 21config SERIO_I8042
22 tristate "i8042 PC Keyboard controller" if EMBEDDED || !X86 22 tristate "i8042 PC Keyboard controller" if EMBEDDED || !X86
23 default y 23 default y
24 depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && !M68K && !BLACKFIN 24 depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && \
25 (!SUPERH || SH_CAYMAN) && !M68K && !BLACKFIN
25 help 26 help
26 i8042 is the chip over which the standard AT keyboard and PS/2 27 i8042 is the chip over which the standard AT keyboard and PS/2
27 mouse are connected to the computer. If you use these devices, 28 mouse are connected to the computer. If you use these devices,
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 2dc0c07c0469..42ba3691d908 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -508,7 +508,6 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
508 } 508 }
509 509
510 input_dev->name = wacom_wac->name; 510 input_dev->name = wacom_wac->name;
511 input_dev->name = wacom_wac->name;
512 input_dev->dev.parent = &intf->dev; 511 input_dev->dev.parent = &intf->dev;
513 input_dev->open = wacom_open; 512 input_dev->open = wacom_open;
514 input_dev->close = wacom_close; 513 input_dev->close = wacom_close;
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 847fd0135bcf..d564af58175c 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -300,7 +300,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
300 case 0x823: /* Intuos3 Grip Pen */ 300 case 0x823: /* Intuos3 Grip Pen */
301 case 0x813: /* Intuos3 Classic Pen */ 301 case 0x813: /* Intuos3 Classic Pen */
302 case 0x885: /* Intuos3 Marker Pen */ 302 case 0x885: /* Intuos3 Marker Pen */
303 case 0x802: /* Intuos4 Grip Pen Eraser */ 303 case 0x802: /* Intuos4 General Pen */
304 case 0x804: /* Intuos4 Marker Pen */ 304 case 0x804: /* Intuos4 Marker Pen */
305 case 0x40802: /* Intuos4 Classic Pen */ 305 case 0x40802: /* Intuos4 Classic Pen */
306 case 0x022: 306 case 0x022:
@@ -335,7 +335,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
335 case 0x81b: /* Intuos3 Classic Pen Eraser */ 335 case 0x81b: /* Intuos3 Classic Pen Eraser */
336 case 0x91b: /* Intuos3 Airbrush Eraser */ 336 case 0x91b: /* Intuos3 Airbrush Eraser */
337 case 0x80c: /* Intuos4 Marker Pen Eraser */ 337 case 0x80c: /* Intuos4 Marker Pen Eraser */
338 case 0x80a: /* Intuos4 Grip Pen Eraser */ 338 case 0x80a: /* Intuos4 General Pen Eraser */
339 case 0x4080a: /* Intuos4 Classic Pen Eraser */ 339 case 0x4080a: /* Intuos4 Classic Pen Eraser */
340 case 0x90a: /* Intuos4 Airbrush Eraser */ 340 case 0x90a: /* Intuos4 Airbrush Eraser */
341 wacom->tool[idx] = BTN_TOOL_RUBBER; 341 wacom->tool[idx] = BTN_TOOL_RUBBER;
@@ -356,6 +356,11 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
356 return 1; 356 return 1;
357 } 357 }
358 358
359 /* older I4 styli don't work with new Cintiqs */
360 if (!((wacom->id[idx] >> 20) & 0x01) &&
361 (features->type == WACOM_21UX2))
362 return 1;
363
359 /* Exit report */ 364 /* Exit report */
360 if ((data[1] & 0xfe) == 0x80) { 365 if ((data[1] & 0xfe) == 0x80) {
361 /* 366 /*
@@ -474,21 +479,43 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
474 input_report_abs(input, ABS_MISC, 0); 479 input_report_abs(input, ABS_MISC, 0);
475 } 480 }
476 } else { 481 } else {
477 input_report_key(input, BTN_0, (data[5] & 0x01)); 482 if (features->type == WACOM_21UX2) {
478 input_report_key(input, BTN_1, (data[5] & 0x02)); 483 input_report_key(input, BTN_0, (data[5] & 0x01));
479 input_report_key(input, BTN_2, (data[5] & 0x04)); 484 input_report_key(input, BTN_1, (data[6] & 0x01));
480 input_report_key(input, BTN_3, (data[5] & 0x08)); 485 input_report_key(input, BTN_2, (data[6] & 0x02));
481 input_report_key(input, BTN_4, (data[6] & 0x01)); 486 input_report_key(input, BTN_3, (data[6] & 0x04));
482 input_report_key(input, BTN_5, (data[6] & 0x02)); 487 input_report_key(input, BTN_4, (data[6] & 0x08));
483 input_report_key(input, BTN_6, (data[6] & 0x04)); 488 input_report_key(input, BTN_5, (data[6] & 0x10));
484 input_report_key(input, BTN_7, (data[6] & 0x08)); 489 input_report_key(input, BTN_6, (data[6] & 0x20));
485 input_report_key(input, BTN_8, (data[5] & 0x10)); 490 input_report_key(input, BTN_7, (data[6] & 0x40));
486 input_report_key(input, BTN_9, (data[6] & 0x10)); 491 input_report_key(input, BTN_8, (data[6] & 0x80));
492 input_report_key(input, BTN_9, (data[7] & 0x01));
493 input_report_key(input, BTN_A, (data[8] & 0x01));
494 input_report_key(input, BTN_B, (data[8] & 0x02));
495 input_report_key(input, BTN_C, (data[8] & 0x04));
496 input_report_key(input, BTN_X, (data[8] & 0x08));
497 input_report_key(input, BTN_Y, (data[8] & 0x10));
498 input_report_key(input, BTN_Z, (data[8] & 0x20));
499 input_report_key(input, BTN_BASE, (data[8] & 0x40));
500 input_report_key(input, BTN_BASE2, (data[8] & 0x80));
501 } else {
502 input_report_key(input, BTN_0, (data[5] & 0x01));
503 input_report_key(input, BTN_1, (data[5] & 0x02));
504 input_report_key(input, BTN_2, (data[5] & 0x04));
505 input_report_key(input, BTN_3, (data[5] & 0x08));
506 input_report_key(input, BTN_4, (data[6] & 0x01));
507 input_report_key(input, BTN_5, (data[6] & 0x02));
508 input_report_key(input, BTN_6, (data[6] & 0x04));
509 input_report_key(input, BTN_7, (data[6] & 0x08));
510 input_report_key(input, BTN_8, (data[5] & 0x10));
511 input_report_key(input, BTN_9, (data[6] & 0x10));
512 }
487 input_report_abs(input, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]); 513 input_report_abs(input, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]);
488 input_report_abs(input, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]); 514 input_report_abs(input, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]);
489 515
490 if ((data[5] & 0x1f) | (data[6] & 0x1f) | (data[1] & 0x1f) | 516 if ((data[5] & 0x1f) | (data[6] & 0x1f) | (data[1] & 0x1f) |
491 data[2] | (data[3] & 0x1f) | data[4]) { 517 data[2] | (data[3] & 0x1f) | data[4] | data[8] |
518 (data[7] & 0x01)) {
492 input_report_key(input, wacom->tool[1], 1); 519 input_report_key(input, wacom->tool[1], 1);
493 input_report_abs(input, ABS_MISC, PAD_DEVICE_ID); 520 input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
494 } else { 521 } else {
@@ -640,7 +667,7 @@ static void wacom_tpc_finger_in(struct wacom_wac *wacom, char *data, int idx)
640 if (!idx) 667 if (!idx)
641 input_report_key(input, BTN_TOUCH, 1); 668 input_report_key(input, BTN_TOUCH, 1);
642 input_event(input, EV_MSC, MSC_SERIAL, finger); 669 input_event(input, EV_MSC, MSC_SERIAL, finger);
643 input_sync(wacom->input); 670 input_sync(input);
644 671
645 wacom->last_finger = finger; 672 wacom->last_finger = finger;
646} 673}
@@ -826,6 +853,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
826 case INTUOS4L: 853 case INTUOS4L:
827 case CINTIQ: 854 case CINTIQ:
828 case WACOM_BEE: 855 case WACOM_BEE:
856 case WACOM_21UX2:
829 sync = wacom_intuos_irq(wacom_wac); 857 sync = wacom_intuos_irq(wacom_wac);
830 break; 858 break;
831 859
@@ -921,6 +949,17 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
921 __set_bit(BTN_STYLUS2, input_dev->keybit); 949 __set_bit(BTN_STYLUS2, input_dev->keybit);
922 break; 950 break;
923 951
952 case WACOM_21UX2:
953 __set_bit(BTN_A, input_dev->keybit);
954 __set_bit(BTN_B, input_dev->keybit);
955 __set_bit(BTN_C, input_dev->keybit);
956 __set_bit(BTN_X, input_dev->keybit);
957 __set_bit(BTN_Y, input_dev->keybit);
958 __set_bit(BTN_Z, input_dev->keybit);
959 __set_bit(BTN_BASE, input_dev->keybit);
960 __set_bit(BTN_BASE2, input_dev->keybit);
961 /* fall through */
962
924 case WACOM_BEE: 963 case WACOM_BEE:
925 __set_bit(BTN_8, input_dev->keybit); 964 __set_bit(BTN_8, input_dev->keybit);
926 __set_bit(BTN_9, input_dev->keybit); 965 __set_bit(BTN_9, input_dev->keybit);
@@ -1105,6 +1144,8 @@ static const struct wacom_features wacom_features_0xBA =
1105 { "Wacom Intuos4 8x13", WACOM_PKGLEN_INTUOS, 65024, 40640, 2047, 63, INTUOS4L }; 1144 { "Wacom Intuos4 8x13", WACOM_PKGLEN_INTUOS, 65024, 40640, 2047, 63, INTUOS4L };
1106static const struct wacom_features wacom_features_0xBB = 1145static const struct wacom_features wacom_features_0xBB =
1107 { "Wacom Intuos4 12x19", WACOM_PKGLEN_INTUOS, 97536, 60960, 2047, 63, INTUOS4L }; 1146 { "Wacom Intuos4 12x19", WACOM_PKGLEN_INTUOS, 97536, 60960, 2047, 63, INTUOS4L };
1147static const struct wacom_features wacom_features_0xBC =
1148 { "Wacom Intuos4 WL", WACOM_PKGLEN_INTUOS, 40840, 25400, 2047, 63, INTUOS4 };
1108static const struct wacom_features wacom_features_0x3F = 1149static const struct wacom_features wacom_features_0x3F =
1109 { "Wacom Cintiq 21UX", WACOM_PKGLEN_INTUOS, 87200, 65600, 1023, 63, CINTIQ }; 1150 { "Wacom Cintiq 21UX", WACOM_PKGLEN_INTUOS, 87200, 65600, 1023, 63, CINTIQ };
1110static const struct wacom_features wacom_features_0xC5 = 1151static const struct wacom_features wacom_features_0xC5 =
@@ -1113,6 +1154,8 @@ static const struct wacom_features wacom_features_0xC6 =
1113 { "Wacom Cintiq 12WX", WACOM_PKGLEN_INTUOS, 53020, 33440, 1023, 63, WACOM_BEE }; 1154 { "Wacom Cintiq 12WX", WACOM_PKGLEN_INTUOS, 53020, 33440, 1023, 63, WACOM_BEE };
1114static const struct wacom_features wacom_features_0xC7 = 1155static const struct wacom_features wacom_features_0xC7 =
1115 { "Wacom DTU1931", WACOM_PKGLEN_GRAPHIRE, 37832, 30305, 511, 0, PL }; 1156 { "Wacom DTU1931", WACOM_PKGLEN_GRAPHIRE, 37832, 30305, 511, 0, PL };
1157static const struct wacom_features wacom_features_0xCC =
1158 { "Wacom Cintiq 21UX2", WACOM_PKGLEN_INTUOS, 87200, 65600, 2047, 63, WACOM_21UX2 };
1116static const struct wacom_features wacom_features_0x90 = 1159static const struct wacom_features wacom_features_0x90 =
1117 { "Wacom ISDv4 90", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }; 1160 { "Wacom ISDv4 90", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC };
1118static const struct wacom_features wacom_features_0x93 = 1161static const struct wacom_features wacom_features_0x93 =
@@ -1185,10 +1228,12 @@ const struct usb_device_id wacom_ids[] = {
1185 { USB_DEVICE_WACOM(0xB9) }, 1228 { USB_DEVICE_WACOM(0xB9) },
1186 { USB_DEVICE_WACOM(0xBA) }, 1229 { USB_DEVICE_WACOM(0xBA) },
1187 { USB_DEVICE_WACOM(0xBB) }, 1230 { USB_DEVICE_WACOM(0xBB) },
1231 { USB_DEVICE_WACOM(0xBC) },
1188 { USB_DEVICE_WACOM(0x3F) }, 1232 { USB_DEVICE_WACOM(0x3F) },
1189 { USB_DEVICE_WACOM(0xC5) }, 1233 { USB_DEVICE_WACOM(0xC5) },
1190 { USB_DEVICE_WACOM(0xC6) }, 1234 { USB_DEVICE_WACOM(0xC6) },
1191 { USB_DEVICE_WACOM(0xC7) }, 1235 { USB_DEVICE_WACOM(0xC7) },
1236 { USB_DEVICE_WACOM(0xCC) },
1192 { USB_DEVICE_WACOM(0x90) }, 1237 { USB_DEVICE_WACOM(0x90) },
1193 { USB_DEVICE_WACOM(0x93) }, 1238 { USB_DEVICE_WACOM(0x93) },
1194 { USB_DEVICE_WACOM(0x9A) }, 1239 { USB_DEVICE_WACOM(0x9A) },
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
index 063f1af3204f..854b92092dfc 100644
--- a/drivers/input/tablet/wacom_wac.h
+++ b/drivers/input/tablet/wacom_wac.h
@@ -50,6 +50,7 @@ enum {
50 INTUOS4S, 50 INTUOS4S,
51 INTUOS4, 51 INTUOS4,
52 INTUOS4L, 52 INTUOS4L,
53 WACOM_21UX2,
53 CINTIQ, 54 CINTIQ,
54 WACOM_BEE, 55 WACOM_BEE,
55 WACOM_MO, 56 WACOM_MO,
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index b9f58ca82fd1..3b9d5e2105d7 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -156,7 +156,7 @@ config TOUCHSCREEN_FUJITSU
156config TOUCHSCREEN_S3C2410 156config TOUCHSCREEN_S3C2410
157 tristate "Samsung S3C2410/generic touchscreen input driver" 157 tristate "Samsung S3C2410/generic touchscreen input driver"
158 depends on ARCH_S3C2410 || SAMSUNG_DEV_TS 158 depends on ARCH_S3C2410 || SAMSUNG_DEV_TS
159 select S3C24XX_ADC 159 select S3C_ADC
160 help 160 help
161 Say Y here if you have the s3c2410 touchscreen. 161 Say Y here if you have the s3c2410 touchscreen.
162 162
@@ -590,4 +590,17 @@ config TOUCHSCREEN_PCAP
590 590
591 To compile this driver as a module, choose M here: the 591 To compile this driver as a module, choose M here: the
592 module will be called pcap_ts. 592 module will be called pcap_ts.
593
594config TOUCHSCREEN_TPS6507X
595 tristate "TPS6507x based touchscreens"
596 depends on I2C
597 help
598 Say Y here if you have a TPS6507x based touchscreen
599 controller.
600
601 If unsure, say N.
602
603 To compile this driver as a module, choose M here: the
604 module will be called tps6507x_ts.
605
593endif 606endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 8ad36eef90a2..497964a7a214 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -46,3 +46,4 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_ATMEL) += atmel-wm97xx.o
46obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o 46obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o
47obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o 47obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o
48obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o 48obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o
49obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o
diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c
index 794d070c6900..4b32fb4704cd 100644
--- a/drivers/input/touchscreen/ad7879.c
+++ b/drivers/input/touchscreen/ad7879.c
@@ -812,10 +812,8 @@ static int __devinit ad7879_probe(struct i2c_client *client,
812 ts->bus = client; 812 ts->bus = client;
813 813
814 error = ad7879_construct(client, ts); 814 error = ad7879_construct(client, ts);
815 if (error) { 815 if (error)
816 i2c_set_clientdata(client, NULL);
817 kfree(ts); 816 kfree(ts);
818 }
819 817
820 return error; 818 return error;
821} 819}
@@ -825,7 +823,6 @@ static int __devexit ad7879_remove(struct i2c_client *client)
825 struct ad7879 *ts = dev_get_drvdata(&client->dev); 823 struct ad7879 *ts = dev_get_drvdata(&client->dev);
826 824
827 ad7879_destroy(client, ts); 825 ad7879_destroy(client, ts);
828 i2c_set_clientdata(client, NULL);
829 kfree(ts); 826 kfree(ts);
830 827
831 return 0; 828 return 0;
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index 532279cda0e4..a9fdf55c0238 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -1163,8 +1163,8 @@ static int __devinit ads7846_probe(struct spi_device *spi)
1163 1163
1164 ts->reg = regulator_get(&spi->dev, "vcc"); 1164 ts->reg = regulator_get(&spi->dev, "vcc");
1165 if (IS_ERR(ts->reg)) { 1165 if (IS_ERR(ts->reg)) {
1166 dev_err(&spi->dev, "unable to get regulator: %ld\n", 1166 err = PTR_ERR(ts->reg);
1167 PTR_ERR(ts->reg)); 1167 dev_err(&spi->dev, "unable to get regulator: %d\n", err);
1168 goto err_free_gpio; 1168 goto err_free_gpio;
1169 } 1169 }
1170 1170
diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c
index 75f8b73010fa..7a3a916f84a8 100644
--- a/drivers/input/touchscreen/eeti_ts.c
+++ b/drivers/input/touchscreen/eeti_ts.c
@@ -238,7 +238,6 @@ err2:
238 input = NULL; /* so we dont try to free it below */ 238 input = NULL; /* so we dont try to free it below */
239err1: 239err1:
240 input_free_device(input); 240 input_free_device(input);
241 i2c_set_clientdata(client, NULL);
242 kfree(priv); 241 kfree(priv);
243err0: 242err0:
244 return err; 243 return err;
@@ -256,7 +255,6 @@ static int __devexit eeti_ts_remove(struct i2c_client *client)
256 enable_irq(priv->irq); 255 enable_irq(priv->irq);
257 256
258 input_unregister_device(priv->input); 257 input_unregister_device(priv->input);
259 i2c_set_clientdata(client, NULL);
260 kfree(priv); 258 kfree(priv);
261 259
262 return 0; 260 return 0;
diff --git a/drivers/input/touchscreen/mcs5000_ts.c b/drivers/input/touchscreen/mcs5000_ts.c
index ce8ab0269f6f..1fb0c2f06a44 100644
--- a/drivers/input/touchscreen/mcs5000_ts.c
+++ b/drivers/input/touchscreen/mcs5000_ts.c
@@ -256,7 +256,6 @@ static int __devexit mcs5000_ts_remove(struct i2c_client *client)
256 free_irq(client->irq, data); 256 free_irq(client->irq, data);
257 input_unregister_device(data->input_dev); 257 input_unregister_device(data->input_dev);
258 kfree(data); 258 kfree(data);
259 i2c_set_clientdata(client, NULL);
260 259
261 return 0; 260 return 0;
262} 261}
diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c
index e0b7c834111d..6085d12fd561 100644
--- a/drivers/input/touchscreen/s3c2410_ts.c
+++ b/drivers/input/touchscreen/s3c2410_ts.c
@@ -173,7 +173,7 @@ static irqreturn_t stylus_irq(int irq, void *dev_id)
173 if (down) 173 if (down)
174 s3c_adc_start(ts.client, 0, 1 << ts.shift); 174 s3c_adc_start(ts.client, 0, 1 << ts.shift);
175 else 175 else
176 dev_info(ts.dev, "%s: count=%d\n", __func__, ts.count); 176 dev_dbg(ts.dev, "%s: count=%d\n", __func__, ts.count);
177 177
178 if (ts.features & FEAT_PEN_IRQ) { 178 if (ts.features & FEAT_PEN_IRQ) {
179 /* Clear pen down/up interrupt */ 179 /* Clear pen down/up interrupt */
@@ -413,6 +413,8 @@ static struct dev_pm_ops s3c_ts_pmops = {
413#endif 413#endif
414 414
415static struct platform_device_id s3cts_driver_ids[] = { 415static struct platform_device_id s3cts_driver_ids[] = {
416 { "s3c2410-ts", 0 },
417 { "s3c2440-ts", 0 },
416 { "s3c64xx-ts", FEAT_PEN_IRQ }, 418 { "s3c64xx-ts", FEAT_PEN_IRQ },
417 { } 419 { }
418}; 420};
diff --git a/drivers/input/touchscreen/tps6507x-ts.c b/drivers/input/touchscreen/tps6507x-ts.c
new file mode 100644
index 000000000000..5b70a1419b4d
--- /dev/null
+++ b/drivers/input/touchscreen/tps6507x-ts.c
@@ -0,0 +1,396 @@
1/*
2 * drivers/input/touchscreen/tps6507x_ts.c
3 *
4 * Touchscreen driver for the tps6507x chip.
5 *
6 * Copyright (c) 2009 RidgeRun (todd.fischer@ridgerun.com)
7 *
8 * Credits:
9 *
10 * Using code from tsc2007, MtekVision Co., Ltd.
11 *
12 * For licencing details see kernel-base/COPYING
13 *
14 * TPS65070, TPS65073, TPS650731, and TPS650732 support
15 * 10 bit touch screen interface.
16 */
17
18#include <linux/module.h>
19#include <linux/workqueue.h>
20#include <linux/slab.h>
21#include <linux/input.h>
22#include <linux/platform_device.h>
23#include <linux/mfd/tps6507x.h>
24#include <linux/input/tps6507x-ts.h>
25#include <linux/delay.h>
26
27#define TSC_DEFAULT_POLL_PERIOD 30 /* ms */
28#define TPS_DEFAULT_MIN_PRESSURE 0x30
29#define MAX_10BIT ((1 << 10) - 1)
30
31#define TPS6507X_ADCONFIG_CONVERT_TS (TPS6507X_ADCONFIG_AD_ENABLE | \
32 TPS6507X_ADCONFIG_START_CONVERSION | \
33 TPS6507X_ADCONFIG_INPUT_REAL_TSC)
34#define TPS6507X_ADCONFIG_POWER_DOWN_TS (TPS6507X_ADCONFIG_INPUT_REAL_TSC)
35
36struct ts_event {
37 u16 x;
38 u16 y;
39 u16 pressure;
40};
41
42struct tps6507x_ts {
43 struct input_dev *input_dev;
44 struct device *dev;
45 char phys[32];
46 struct workqueue_struct *wq;
47 struct delayed_work work;
48 unsigned polling; /* polling is active */
49 struct ts_event tc;
50 struct tps6507x_dev *mfd;
51 u16 model;
52 unsigned pendown;
53 int irq;
54 void (*clear_penirq)(void);
55 unsigned long poll_period; /* ms */
56 u16 min_pressure;
57 int vref; /* non-zero to leave vref on */
58};
59
60static int tps6507x_read_u8(struct tps6507x_ts *tsc, u8 reg, u8 *data)
61{
62 int err;
63
64 err = tsc->mfd->read_dev(tsc->mfd, reg, 1, data);
65
66 if (err)
67 return err;
68
69 return 0;
70}
71
72static int tps6507x_write_u8(struct tps6507x_ts *tsc, u8 reg, u8 data)
73{
74 return tsc->mfd->write_dev(tsc->mfd, reg, 1, &data);
75}
76
77static s32 tps6507x_adc_conversion(struct tps6507x_ts *tsc,
78 u8 tsc_mode, u16 *value)
79{
80 s32 ret;
81 u8 adc_status;
82 u8 result;
83
84 /* Route input signal to A/D converter */
85
86 ret = tps6507x_write_u8(tsc, TPS6507X_REG_TSCMODE, tsc_mode);
87 if (ret) {
88 dev_err(tsc->dev, "TSC mode read failed\n");
89 goto err;
90 }
91
92 /* Start A/D conversion */
93
94 ret = tps6507x_write_u8(tsc, TPS6507X_REG_ADCONFIG,
95 TPS6507X_ADCONFIG_CONVERT_TS);
96 if (ret) {
97 dev_err(tsc->dev, "ADC config write failed\n");
98 return ret;
99 }
100
101 do {
102 ret = tps6507x_read_u8(tsc, TPS6507X_REG_ADCONFIG,
103 &adc_status);
104 if (ret) {
105 dev_err(tsc->dev, "ADC config read failed\n");
106 goto err;
107 }
108 } while (adc_status & TPS6507X_ADCONFIG_START_CONVERSION);
109
110 ret = tps6507x_read_u8(tsc, TPS6507X_REG_ADRESULT_2, &result);
111 if (ret) {
112 dev_err(tsc->dev, "ADC result 2 read failed\n");
113 goto err;
114 }
115
116 *value = (result & TPS6507X_REG_ADRESULT_2_MASK) << 8;
117
118 ret = tps6507x_read_u8(tsc, TPS6507X_REG_ADRESULT_1, &result);
119 if (ret) {
120 dev_err(tsc->dev, "ADC result 1 read failed\n");
121 goto err;
122 }
123
124 *value |= result;
125
126 dev_dbg(tsc->dev, "TSC channel %d = 0x%X\n", tsc_mode, *value);
127
128err:
129 return ret;
130}
131
132/* Need to call tps6507x_adc_standby() after using A/D converter for the
133 * touch screen interrupt to work properly.
134 */
135
136static s32 tps6507x_adc_standby(struct tps6507x_ts *tsc)
137{
138 s32 ret;
139 s32 loops = 0;
140 u8 val;
141
142 ret = tps6507x_write_u8(tsc, TPS6507X_REG_ADCONFIG,
143 TPS6507X_ADCONFIG_INPUT_TSC);
144 if (ret)
145 return ret;
146
147 ret = tps6507x_write_u8(tsc, TPS6507X_REG_TSCMODE,
148 TPS6507X_TSCMODE_STANDBY);
149 if (ret)
150 return ret;
151
152 ret = tps6507x_read_u8(tsc, TPS6507X_REG_INT, &val);
153 if (ret)
154 return ret;
155
156 while (val & TPS6507X_REG_TSC_INT) {
157 mdelay(10);
158 ret = tps6507x_read_u8(tsc, TPS6507X_REG_INT, &val);
159 if (ret)
160 return ret;
161 loops++;
162 }
163
164 return ret;
165}
166
167static void tps6507x_ts_handler(struct work_struct *work)
168{
169 struct tps6507x_ts *tsc = container_of(work,
170 struct tps6507x_ts, work.work);
171 struct input_dev *input_dev = tsc->input_dev;
172 int pendown;
173 int schd;
174 int poll = 0;
175 s32 ret;
176
177 ret = tps6507x_adc_conversion(tsc, TPS6507X_TSCMODE_PRESSURE,
178 &tsc->tc.pressure);
179 if (ret)
180 goto done;
181
182 pendown = tsc->tc.pressure > tsc->min_pressure;
183
184 if (unlikely(!pendown && tsc->pendown)) {
185 dev_dbg(tsc->dev, "UP\n");
186 input_report_key(input_dev, BTN_TOUCH, 0);
187 input_report_abs(input_dev, ABS_PRESSURE, 0);
188 input_sync(input_dev);
189 tsc->pendown = 0;
190 }
191
192 if (pendown) {
193
194 if (!tsc->pendown) {
195 dev_dbg(tsc->dev, "DOWN\n");
196 input_report_key(input_dev, BTN_TOUCH, 1);
197 } else
198 dev_dbg(tsc->dev, "still down\n");
199
200 ret = tps6507x_adc_conversion(tsc, TPS6507X_TSCMODE_X_POSITION,
201 &tsc->tc.x);
202 if (ret)
203 goto done;
204
205 ret = tps6507x_adc_conversion(tsc, TPS6507X_TSCMODE_Y_POSITION,
206 &tsc->tc.y);
207 if (ret)
208 goto done;
209
210 input_report_abs(input_dev, ABS_X, tsc->tc.x);
211 input_report_abs(input_dev, ABS_Y, tsc->tc.y);
212 input_report_abs(input_dev, ABS_PRESSURE, tsc->tc.pressure);
213 input_sync(input_dev);
214 tsc->pendown = 1;
215 poll = 1;
216 }
217
218done:
219 /* always poll if not using interrupts */
220 poll = 1;
221
222 if (poll) {
223 schd = queue_delayed_work(tsc->wq, &tsc->work,
224 msecs_to_jiffies(tsc->poll_period));
225 if (schd)
226 tsc->polling = 1;
227 else {
228 tsc->polling = 0;
229 dev_err(tsc->dev, "re-schedule failed");
230 }
231 } else
232 tsc->polling = 0;
233
234 ret = tps6507x_adc_standby(tsc);
235}
236
237static int tps6507x_ts_probe(struct platform_device *pdev)
238{
239 int error;
240 struct tps6507x_ts *tsc;
241 struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent);
242 struct touchscreen_init_data *init_data;
243 struct input_dev *input_dev;
244 struct tps6507x_board *tps_board;
245 int schd;
246
247 /**
248 * tps_board points to pmic related constants
249 * coming from the board-evm file.
250 */
251
252 tps_board = (struct tps6507x_board *)tps6507x_dev->dev->platform_data;
253
254 if (!tps_board) {
255 dev_err(tps6507x_dev->dev,
256 "Could not find tps6507x platform data\n");
257 return -EIO;
258 }
259
260 /**
261 * init_data points to array of regulator_init structures
262 * coming from the board-evm file.
263 */
264
265 init_data = tps_board->tps6507x_ts_init_data;
266
267 tsc = kzalloc(sizeof(struct tps6507x_ts), GFP_KERNEL);
268 if (!tsc) {
269 dev_err(tps6507x_dev->dev, "failed to allocate driver data\n");
270 error = -ENOMEM;
271 goto err0;
272 }
273
274 tps6507x_dev->ts = tsc;
275 tsc->mfd = tps6507x_dev;
276 tsc->dev = tps6507x_dev->dev;
277 input_dev = input_allocate_device();
278 if (!input_dev) {
279 dev_err(tsc->dev, "Failed to allocate input device.\n");
280 error = -ENOMEM;
281 goto err1;
282 }
283
284 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
285 input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
286
287 input_set_abs_params(input_dev, ABS_X, 0, MAX_10BIT, 0, 0);
288 input_set_abs_params(input_dev, ABS_Y, 0, MAX_10BIT, 0, 0);
289 input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_10BIT, 0, 0);
290
291 input_dev->name = "TPS6507x Touchscreen";
292 input_dev->id.bustype = BUS_I2C;
293 input_dev->dev.parent = tsc->dev;
294
295 snprintf(tsc->phys, sizeof(tsc->phys),
296 "%s/input0", dev_name(tsc->dev));
297 input_dev->phys = tsc->phys;
298
299 dev_dbg(tsc->dev, "device: %s\n", input_dev->phys);
300
301 input_set_drvdata(input_dev, tsc);
302
303 tsc->input_dev = input_dev;
304
305 INIT_DELAYED_WORK(&tsc->work, tps6507x_ts_handler);
306 tsc->wq = create_workqueue("TPS6507x Touchscreen");
307
308 if (init_data) {
309 tsc->poll_period = init_data->poll_period;
310 tsc->vref = init_data->vref;
311 tsc->min_pressure = init_data->min_pressure;
312 input_dev->id.vendor = init_data->vendor;
313 input_dev->id.product = init_data->product;
314 input_dev->id.version = init_data->version;
315 } else {
316 tsc->poll_period = TSC_DEFAULT_POLL_PERIOD;
317 tsc->min_pressure = TPS_DEFAULT_MIN_PRESSURE;
318 }
319
320 error = tps6507x_adc_standby(tsc);
321 if (error)
322 goto err2;
323
324 error = input_register_device(input_dev);
325 if (error)
326 goto err2;
327
328 schd = queue_delayed_work(tsc->wq, &tsc->work,
329 msecs_to_jiffies(tsc->poll_period));
330
331 if (schd)
332 tsc->polling = 1;
333 else {
334 tsc->polling = 0;
335 dev_err(tsc->dev, "schedule failed");
336 goto err2;
337 }
338
339 return 0;
340
341err2:
342 cancel_delayed_work_sync(&tsc->work);
343 destroy_workqueue(tsc->wq);
344 input_free_device(input_dev);
345err1:
346 kfree(tsc);
347 tps6507x_dev->ts = NULL;
348err0:
349 return error;
350}
351
352static int __devexit tps6507x_ts_remove(struct platform_device *pdev)
353{
354 struct tps6507x_dev *tps6507x_dev = platform_get_drvdata(pdev);
355 struct tps6507x_ts *tsc = tps6507x_dev->ts;
356 struct input_dev *input_dev = tsc->input_dev;
357
358 if (!tsc)
359 return 0;
360
361 cancel_delayed_work_sync(&tsc->work);
362 destroy_workqueue(tsc->wq);
363
364 input_free_device(input_dev);
365
366 tps6507x_dev->ts = NULL;
367 kfree(tsc);
368
369 return 0;
370}
371
372static struct platform_driver tps6507x_ts_driver = {
373 .driver = {
374 .name = "tps6507x-ts",
375 .owner = THIS_MODULE,
376 },
377 .probe = tps6507x_ts_probe,
378 .remove = __devexit_p(tps6507x_ts_remove),
379};
380
381static int __init tps6507x_ts_init(void)
382{
383 return platform_driver_register(&tps6507x_ts_driver);
384}
385module_init(tps6507x_ts_init);
386
387static void __exit tps6507x_ts_exit(void)
388{
389 platform_driver_unregister(&tps6507x_ts_driver);
390}
391module_exit(tps6507x_ts_exit);
392
393MODULE_AUTHOR("Todd Fischer <todd.fischer@ridgerun.com>");
394MODULE_DESCRIPTION("TPS6507x - TouchScreen driver");
395MODULE_LICENSE("GPL v2");
396MODULE_ALIAS("platform:tps6507x-tsc");
diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c
index 769b479fcaa6..be23780e8a3e 100644
--- a/drivers/input/touchscreen/tsc2007.c
+++ b/drivers/input/touchscreen/tsc2007.c
@@ -347,8 +347,6 @@ static int __devexit tsc2007_remove(struct i2c_client *client)
347 struct tsc2007 *ts = i2c_get_clientdata(client); 347 struct tsc2007 *ts = i2c_get_clientdata(client);
348 struct tsc2007_platform_data *pdata = client->dev.platform_data; 348 struct tsc2007_platform_data *pdata = client->dev.platform_data;
349 349
350 i2c_set_clientdata(client, NULL);
351
352 tsc2007_free_irq(ts); 350 tsc2007_free_irq(ts);
353 351
354 if (pdata->exit_platform_hw) 352 if (pdata->exit_platform_hw)
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c
index 29a8bbf3f086..567d57215c28 100644
--- a/drivers/input/touchscreen/usbtouchscreen.c
+++ b/drivers/input/touchscreen/usbtouchscreen.c
@@ -857,6 +857,11 @@ static int nexio_read_data(struct usbtouch_usb *usbtouch, unsigned char *pkt)
857 if ((pkt[0] & 0xe0) != 0xe0) 857 if ((pkt[0] & 0xe0) != 0xe0)
858 return 0; 858 return 0;
859 859
860 if (be16_to_cpu(packet->data_len) > 0xff)
861 packet->data_len = cpu_to_be16(be16_to_cpu(packet->data_len) - 0x100);
862 if (be16_to_cpu(packet->x_len) > 0xff)
863 packet->x_len = cpu_to_be16(be16_to_cpu(packet->x_len) - 0x80);
864
860 /* send ACK */ 865 /* send ACK */
861 ret = usb_submit_urb(priv->ack, GFP_ATOMIC); 866 ret = usb_submit_urb(priv->ack, GFP_ATOMIC);
862 867
@@ -1112,7 +1117,7 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
1112 1117
1113#ifdef CONFIG_TOUCHSCREEN_USB_NEXIO 1118#ifdef CONFIG_TOUCHSCREEN_USB_NEXIO
1114 [DEVTYPE_NEXIO] = { 1119 [DEVTYPE_NEXIO] = {
1115 .rept_size = 128, 1120 .rept_size = 1024,
1116 .irq_always = true, 1121 .irq_always = true,
1117 .read_data = nexio_read_data, 1122 .read_data = nexio_read_data,
1118 .init = nexio_init, 1123 .init = nexio_init,
diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c
index bde3c88b8b27..b054494df846 100644
--- a/drivers/isdn/capi/kcapi.c
+++ b/drivers/isdn/capi/kcapi.c
@@ -1020,12 +1020,12 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data)
1020 if (cmd == AVMB1_ADDCARD) { 1020 if (cmd == AVMB1_ADDCARD) {
1021 if ((retval = copy_from_user(&cdef, data, 1021 if ((retval = copy_from_user(&cdef, data,
1022 sizeof(avmb1_carddef)))) 1022 sizeof(avmb1_carddef))))
1023 return retval; 1023 return -EFAULT;
1024 cdef.cardtype = AVM_CARDTYPE_B1; 1024 cdef.cardtype = AVM_CARDTYPE_B1;
1025 } else { 1025 } else {
1026 if ((retval = copy_from_user(&cdef, data, 1026 if ((retval = copy_from_user(&cdef, data,
1027 sizeof(avmb1_extcarddef)))) 1027 sizeof(avmb1_extcarddef))))
1028 return retval; 1028 return -EFAULT;
1029 } 1029 }
1030 cparams.port = cdef.port; 1030 cparams.port = cdef.port;
1031 cparams.irq = cdef.irq; 1031 cparams.irq = cdef.irq;
@@ -1218,7 +1218,7 @@ int capi20_manufacturer(unsigned int cmd, void __user *data)
1218 kcapi_carddef cdef; 1218 kcapi_carddef cdef;
1219 1219
1220 if ((retval = copy_from_user(&cdef, data, sizeof(cdef)))) 1220 if ((retval = copy_from_user(&cdef, data, sizeof(cdef))))
1221 return retval; 1221 return -EFAULT;
1222 1222
1223 cparams.port = cdef.port; 1223 cparams.port = cdef.port;
1224 cparams.irq = cdef.irq; 1224 cparams.irq = cdef.irq;
diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.c b/drivers/isdn/hardware/mISDN/hfcsusb.c
index b3b7e2879bac..8700474747e8 100644
--- a/drivers/isdn/hardware/mISDN/hfcsusb.c
+++ b/drivers/isdn/hardware/mISDN/hfcsusb.c
@@ -97,8 +97,10 @@ static int write_reg(struct hfcsusb *hw, __u8 reg, __u8 val)
97 hw->name, __func__, reg, val); 97 hw->name, __func__, reg, val);
98 98
99 spin_lock(&hw->ctrl_lock); 99 spin_lock(&hw->ctrl_lock);
100 if (hw->ctrl_cnt >= HFC_CTRL_BUFSIZE) 100 if (hw->ctrl_cnt >= HFC_CTRL_BUFSIZE) {
101 spin_unlock(&hw->ctrl_lock);
101 return 1; 102 return 1;
103 }
102 buf = &hw->ctrl_buff[hw->ctrl_in_idx]; 104 buf = &hw->ctrl_buff[hw->ctrl_in_idx];
103 buf->hfcs_reg = reg; 105 buf->hfcs_reg = reg;
104 buf->reg_val = val; 106 buf->reg_val = val;
diff --git a/drivers/isdn/hardware/mISDN/netjet.c b/drivers/isdn/hardware/mISDN/netjet.c
index 0a3553df065f..54ae71a907f9 100644
--- a/drivers/isdn/hardware/mISDN/netjet.c
+++ b/drivers/isdn/hardware/mISDN/netjet.c
@@ -320,12 +320,12 @@ inittiger(struct tiger_hw *card)
320 return -ENOMEM; 320 return -ENOMEM;
321 } 321 }
322 for (i = 0; i < 2; i++) { 322 for (i = 0; i < 2; i++) {
323 card->bc[i].hsbuf = kmalloc(NJ_DMA_TXSIZE, GFP_KERNEL); 323 card->bc[i].hsbuf = kmalloc(NJ_DMA_TXSIZE, GFP_ATOMIC);
324 if (!card->bc[i].hsbuf) { 324 if (!card->bc[i].hsbuf) {
325 pr_info("%s: no B%d send buffer\n", card->name, i + 1); 325 pr_info("%s: no B%d send buffer\n", card->name, i + 1);
326 return -ENOMEM; 326 return -ENOMEM;
327 } 327 }
328 card->bc[i].hrbuf = kmalloc(NJ_DMA_RXSIZE, GFP_KERNEL); 328 card->bc[i].hrbuf = kmalloc(NJ_DMA_RXSIZE, GFP_ATOMIC);
329 if (!card->bc[i].hrbuf) { 329 if (!card->bc[i].hrbuf) {
330 pr_info("%s: no B%d recv buffer\n", card->name, i + 1); 330 pr_info("%s: no B%d recv buffer\n", card->name, i + 1);
331 return -ENOMEM; 331 return -ENOMEM;
diff --git a/drivers/isdn/mISDN/timerdev.c b/drivers/isdn/mISDN/timerdev.c
index c3243c913ec0..81048b8ed8ad 100644
--- a/drivers/isdn/mISDN/timerdev.c
+++ b/drivers/isdn/mISDN/timerdev.c
@@ -98,8 +98,6 @@ mISDN_read(struct file *filep, char __user *buf, size_t count, loff_t *off)
98 if (*debug & DEBUG_TIMER) 98 if (*debug & DEBUG_TIMER)
99 printk(KERN_DEBUG "%s(%p, %p, %d, %p)\n", __func__, 99 printk(KERN_DEBUG "%s(%p, %p, %d, %p)\n", __func__,
100 filep, buf, (int)count, off); 100 filep, buf, (int)count, off);
101 if (*off != filep->f_pos)
102 return -ESPIPE;
103 101
104 if (list_empty(&dev->expired) && (dev->work == 0)) { 102 if (list_empty(&dev->expired) && (dev->work == 0)) {
105 if (filep->f_flags & O_NONBLOCK) 103 if (filep->f_flags & O_NONBLOCK)
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 505eb64c329c..81bf25e67ce1 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -21,7 +21,7 @@ comment "LED drivers"
21 21
22config LEDS_88PM860X 22config LEDS_88PM860X
23 tristate "LED Support for Marvell 88PM860x PMIC" 23 tristate "LED Support for Marvell 88PM860x PMIC"
24 depends on LEDS_CLASS && MFD_88PM860X 24 depends on MFD_88PM860X
25 help 25 help
26 This option enables support for on-chip LED drivers found on Marvell 26 This option enables support for on-chip LED drivers found on Marvell
27 Semiconductor 88PM8606 PMIC. 27 Semiconductor 88PM8606 PMIC.
@@ -67,6 +67,16 @@ config LEDS_NET48XX
67 This option enables support for the Soekris net4801 and net4826 error 67 This option enables support for the Soekris net4801 and net4826 error
68 LED. 68 LED.
69 69
70config LEDS_NET5501
71 tristate "LED Support for Soekris net5501 series Error LED"
72 depends on LEDS_TRIGGERS
73 depends on X86 && LEDS_GPIO_PLATFORM && GPIO_CS5535
74 select LEDS_TRIGGER_DEFAULT_ON
75 default n
76 help
77 Add support for the Soekris net5501 board (detection, error led
78 and GPIO).
79
70config LEDS_FSG 80config LEDS_FSG
71 tristate "LED Support for the Freecom FSG-3" 81 tristate "LED Support for the Freecom FSG-3"
72 depends on MACH_FSG 82 depends on MACH_FSG
@@ -285,6 +295,13 @@ config LEDS_DELL_NETBOOKS
285 This adds support for the Latitude 2100 and similar 295 This adds support for the Latitude 2100 and similar
286 notebooks that have an external LED. 296 notebooks that have an external LED.
287 297
298config LEDS_MC13783
299 tristate "LED Support for MC13783 PMIC"
300 depends on MFD_MC13783
301 help
302 This option enable support for on-chip LED drivers found
303 on Freescale Semiconductor MC13783 PMIC.
304
288config LEDS_TRIGGERS 305config LEDS_TRIGGERS
289 bool "LED Trigger support" 306 bool "LED Trigger support"
290 help 307 help
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 0cd8b9957380..2493de499374 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_LEDS_MIKROTIK_RB532) += leds-rb532.o
13obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o 13obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o
14obj-$(CONFIG_LEDS_AMS_DELTA) += leds-ams-delta.o 14obj-$(CONFIG_LEDS_AMS_DELTA) += leds-ams-delta.o
15obj-$(CONFIG_LEDS_NET48XX) += leds-net48xx.o 15obj-$(CONFIG_LEDS_NET48XX) += leds-net48xx.o
16obj-$(CONFIG_LEDS_NET5501) += leds-net5501.o
16obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o 17obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o
17obj-$(CONFIG_LEDS_ALIX2) += leds-alix2.o 18obj-$(CONFIG_LEDS_ALIX2) += leds-alix2.o
18obj-$(CONFIG_LEDS_H1940) += leds-h1940.o 19obj-$(CONFIG_LEDS_H1940) += leds-h1940.o
@@ -35,6 +36,7 @@ obj-$(CONFIG_LEDS_INTEL_SS4200) += leds-ss4200.o
35obj-$(CONFIG_LEDS_LT3593) += leds-lt3593.o 36obj-$(CONFIG_LEDS_LT3593) += leds-lt3593.o
36obj-$(CONFIG_LEDS_ADP5520) += leds-adp5520.o 37obj-$(CONFIG_LEDS_ADP5520) += leds-adp5520.o
37obj-$(CONFIG_LEDS_DELL_NETBOOKS) += dell-led.o 38obj-$(CONFIG_LEDS_DELL_NETBOOKS) += dell-led.o
39obj-$(CONFIG_LEDS_MC13783) += leds-mc13783.o
38 40
39# LED SPI Drivers 41# LED SPI Drivers
40obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o 42obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index 69e7d86a5143..260660076507 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -74,7 +74,7 @@ static ssize_t led_max_brightness_show(struct device *dev,
74 74
75static struct device_attribute led_class_attrs[] = { 75static struct device_attribute led_class_attrs[] = {
76 __ATTR(brightness, 0644, led_brightness_show, led_brightness_store), 76 __ATTR(brightness, 0644, led_brightness_show, led_brightness_store),
77 __ATTR(max_brightness, 0644, led_max_brightness_show, NULL), 77 __ATTR(max_brightness, 0444, led_max_brightness_show, NULL),
78#ifdef CONFIG_LEDS_TRIGGERS 78#ifdef CONFIG_LEDS_TRIGGERS
79 __ATTR(trigger, 0644, led_trigger_show, led_trigger_store), 79 __ATTR(trigger, 0644, led_trigger_show, led_trigger_store),
80#endif 80#endif
diff --git a/drivers/leds/leds-88pm860x.c b/drivers/leds/leds-88pm860x.c
index 16a60c06c96c..b7677106cff8 100644
--- a/drivers/leds/leds-88pm860x.c
+++ b/drivers/leds/leds-88pm860x.c
@@ -256,8 +256,10 @@ static int pm860x_led_probe(struct platform_device *pdev)
256 if (pdev->dev.parent->platform_data) { 256 if (pdev->dev.parent->platform_data) {
257 pm860x_pdata = pdev->dev.parent->platform_data; 257 pm860x_pdata = pdev->dev.parent->platform_data;
258 pdata = pm860x_pdata->led; 258 pdata = pm860x_pdata->led;
259 } else 259 } else {
260 pdata = NULL; 260 dev_err(&pdev->dev, "missing platform data\n");
261 return -EINVAL;
262 }
261 263
262 data = kzalloc(sizeof(struct pm860x_led), GFP_KERNEL); 264 data = kzalloc(sizeof(struct pm860x_led), GFP_KERNEL);
263 if (data == NULL) 265 if (data == NULL)
@@ -268,8 +270,11 @@ static int pm860x_led_probe(struct platform_device *pdev)
268 data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion; 270 data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion;
269 data->iset = pdata->iset; 271 data->iset = pdata->iset;
270 data->port = __check_device(pdata, data->name); 272 data->port = __check_device(pdata, data->name);
271 if (data->port < 0) 273 if (data->port < 0) {
274 dev_err(&pdev->dev, "check device failed\n");
275 kfree(data);
272 return -EINVAL; 276 return -EINVAL;
277 }
273 278
274 data->current_brightness = 0; 279 data->current_brightness = 0;
275 data->cdev.name = data->name; 280 data->cdev.name = data->name;
diff --git a/drivers/leds/leds-bd2802.c b/drivers/leds/leds-bd2802.c
index 286b501a3573..5dcdf9d69b3a 100644
--- a/drivers/leds/leds-bd2802.c
+++ b/drivers/leds/leds-bd2802.c
@@ -742,7 +742,6 @@ failed_unregister_dev_file:
742 for (i--; i >= 0; i--) 742 for (i--; i >= 0; i--)
743 device_remove_file(&led->client->dev, bd2802_attributes[i]); 743 device_remove_file(&led->client->dev, bd2802_attributes[i]);
744failed_free: 744failed_free:
745 i2c_set_clientdata(client, NULL);
746 kfree(led); 745 kfree(led);
747 746
748 return ret; 747 return ret;
@@ -759,7 +758,6 @@ static int __exit bd2802_remove(struct i2c_client *client)
759 bd2802_disable_adv_conf(led); 758 bd2802_disable_adv_conf(led);
760 for (i = 0; i < ARRAY_SIZE(bd2802_attributes); i++) 759 for (i = 0; i < ARRAY_SIZE(bd2802_attributes); i++)
761 device_remove_file(&led->client->dev, bd2802_attributes[i]); 760 device_remove_file(&led->client->dev, bd2802_attributes[i]);
762 i2c_set_clientdata(client, NULL);
763 kfree(led); 761 kfree(led);
764 762
765 return 0; 763 return 0;
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index 6d94b0b9979c..cc22eeefa10b 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -26,7 +26,8 @@ struct gpio_led_data {
26 u8 new_level; 26 u8 new_level;
27 u8 can_sleep; 27 u8 can_sleep;
28 u8 active_low; 28 u8 active_low;
29 int (*platform_gpio_blink_set)(unsigned gpio, 29 u8 blinking;
30 int (*platform_gpio_blink_set)(unsigned gpio, int state,
30 unsigned long *delay_on, unsigned long *delay_off); 31 unsigned long *delay_on, unsigned long *delay_off);
31}; 32};
32 33
@@ -35,7 +36,13 @@ static void gpio_led_work(struct work_struct *work)
35 struct gpio_led_data *led_dat = 36 struct gpio_led_data *led_dat =
36 container_of(work, struct gpio_led_data, work); 37 container_of(work, struct gpio_led_data, work);
37 38
38 gpio_set_value_cansleep(led_dat->gpio, led_dat->new_level); 39 if (led_dat->blinking) {
40 led_dat->platform_gpio_blink_set(led_dat->gpio,
41 led_dat->new_level,
42 NULL, NULL);
43 led_dat->blinking = 0;
44 } else
45 gpio_set_value_cansleep(led_dat->gpio, led_dat->new_level);
39} 46}
40 47
41static void gpio_led_set(struct led_classdev *led_cdev, 48static void gpio_led_set(struct led_classdev *led_cdev,
@@ -60,8 +67,14 @@ static void gpio_led_set(struct led_classdev *led_cdev,
60 if (led_dat->can_sleep) { 67 if (led_dat->can_sleep) {
61 led_dat->new_level = level; 68 led_dat->new_level = level;
62 schedule_work(&led_dat->work); 69 schedule_work(&led_dat->work);
63 } else 70 } else {
64 gpio_set_value(led_dat->gpio, level); 71 if (led_dat->blinking) {
72 led_dat->platform_gpio_blink_set(led_dat->gpio, level,
73 NULL, NULL);
74 led_dat->blinking = 0;
75 } else
76 gpio_set_value(led_dat->gpio, level);
77 }
65} 78}
66 79
67static int gpio_blink_set(struct led_classdev *led_cdev, 80static int gpio_blink_set(struct led_classdev *led_cdev,
@@ -70,12 +83,14 @@ static int gpio_blink_set(struct led_classdev *led_cdev,
70 struct gpio_led_data *led_dat = 83 struct gpio_led_data *led_dat =
71 container_of(led_cdev, struct gpio_led_data, cdev); 84 container_of(led_cdev, struct gpio_led_data, cdev);
72 85
73 return led_dat->platform_gpio_blink_set(led_dat->gpio, delay_on, delay_off); 86 led_dat->blinking = 1;
87 return led_dat->platform_gpio_blink_set(led_dat->gpio, GPIO_LED_BLINK,
88 delay_on, delay_off);
74} 89}
75 90
76static int __devinit create_gpio_led(const struct gpio_led *template, 91static int __devinit create_gpio_led(const struct gpio_led *template,
77 struct gpio_led_data *led_dat, struct device *parent, 92 struct gpio_led_data *led_dat, struct device *parent,
78 int (*blink_set)(unsigned, unsigned long *, unsigned long *)) 93 int (*blink_set)(unsigned, int, unsigned long *, unsigned long *))
79{ 94{
80 int ret, state; 95 int ret, state;
81 96
@@ -97,6 +112,7 @@ static int __devinit create_gpio_led(const struct gpio_led *template,
97 led_dat->gpio = template->gpio; 112 led_dat->gpio = template->gpio;
98 led_dat->can_sleep = gpio_cansleep(template->gpio); 113 led_dat->can_sleep = gpio_cansleep(template->gpio);
99 led_dat->active_low = template->active_low; 114 led_dat->active_low = template->active_low;
115 led_dat->blinking = 0;
100 if (blink_set) { 116 if (blink_set) {
101 led_dat->platform_gpio_blink_set = blink_set; 117 led_dat->platform_gpio_blink_set = blink_set;
102 led_dat->cdev.blink_set = gpio_blink_set; 118 led_dat->cdev.blink_set = gpio_blink_set;
@@ -113,7 +129,7 @@ static int __devinit create_gpio_led(const struct gpio_led *template,
113 ret = gpio_direction_output(led_dat->gpio, led_dat->active_low ^ state); 129 ret = gpio_direction_output(led_dat->gpio, led_dat->active_low ^ state);
114 if (ret < 0) 130 if (ret < 0)
115 goto err; 131 goto err;
116 132
117 INIT_WORK(&led_dat->work, gpio_led_work); 133 INIT_WORK(&led_dat->work, gpio_led_work);
118 134
119 ret = led_classdev_register(parent, &led_dat->cdev); 135 ret = led_classdev_register(parent, &led_dat->cdev);
diff --git a/drivers/leds/leds-lp3944.c b/drivers/leds/leds-lp3944.c
index 8d5ecceba181..9010c054615e 100644
--- a/drivers/leds/leds-lp3944.c
+++ b/drivers/leds/leds-lp3944.c
@@ -379,6 +379,7 @@ static int __devinit lp3944_probe(struct i2c_client *client,
379{ 379{
380 struct lp3944_platform_data *lp3944_pdata = client->dev.platform_data; 380 struct lp3944_platform_data *lp3944_pdata = client->dev.platform_data;
381 struct lp3944_data *data; 381 struct lp3944_data *data;
382 int err;
382 383
383 if (lp3944_pdata == NULL) { 384 if (lp3944_pdata == NULL) {
384 dev_err(&client->dev, "no platform data\n"); 385 dev_err(&client->dev, "no platform data\n");
@@ -401,9 +402,13 @@ static int __devinit lp3944_probe(struct i2c_client *client,
401 402
402 mutex_init(&data->lock); 403 mutex_init(&data->lock);
403 404
404 dev_info(&client->dev, "lp3944 enabled\n"); 405 err = lp3944_configure(client, data, lp3944_pdata);
406 if (err < 0) {
407 kfree(data);
408 return err;
409 }
405 410
406 lp3944_configure(client, data, lp3944_pdata); 411 dev_info(&client->dev, "lp3944 enabled\n");
407 return 0; 412 return 0;
408} 413}
409 414
@@ -427,7 +432,6 @@ static int __devexit lp3944_remove(struct i2c_client *client)
427 } 432 }
428 433
429 kfree(data); 434 kfree(data);
430 i2c_set_clientdata(client, NULL);
431 435
432 return 0; 436 return 0;
433} 437}
diff --git a/drivers/leds/leds-mc13783.c b/drivers/leds/leds-mc13783.c
new file mode 100644
index 000000000000..f05bb08d0f09
--- /dev/null
+++ b/drivers/leds/leds-mc13783.c
@@ -0,0 +1,403 @@
1/*
2 * LEDs driver for Freescale MC13783
3 *
4 * Copyright (C) 2010 Philippe Rétornaz
5 *
6 * Based on leds-da903x:
7 * Copyright (C) 2008 Compulab, Ltd.
8 * Mike Rapoport <mike@compulab.co.il>
9 *
10 * Copyright (C) 2006-2008 Marvell International Ltd.
11 * Eric Miao <eric.miao@marvell.com>
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
16 */
17
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/init.h>
21#include <linux/platform_device.h>
22#include <linux/leds.h>
23#include <linux/workqueue.h>
24#include <linux/mfd/mc13783.h>
25#include <linux/slab.h>
26
27struct mc13783_led {
28 struct led_classdev cdev;
29 struct work_struct work;
30 struct mc13783 *master;
31 enum led_brightness new_brightness;
32 int id;
33};
34
35#define MC13783_REG_LED_CONTROL_0 51
36#define MC13783_LED_C0_ENABLE_BIT (1 << 0)
37#define MC13783_LED_C0_TRIODE_MD_BIT (1 << 7)
38#define MC13783_LED_C0_TRIODE_AD_BIT (1 << 8)
39#define MC13783_LED_C0_TRIODE_KP_BIT (1 << 9)
40#define MC13783_LED_C0_BOOST_BIT (1 << 10)
41#define MC13783_LED_C0_ABMODE_MASK 0x7
42#define MC13783_LED_C0_ABMODE 11
43#define MC13783_LED_C0_ABREF_MASK 0x3
44#define MC13783_LED_C0_ABREF 14
45
46#define MC13783_REG_LED_CONTROL_1 52
47#define MC13783_LED_C1_TC1HALF_BIT (1 << 18)
48
49#define MC13783_REG_LED_CONTROL_2 53
50#define MC13783_LED_C2_BL_P_MASK 0xf
51#define MC13783_LED_C2_MD_P 9
52#define MC13783_LED_C2_AD_P 13
53#define MC13783_LED_C2_KP_P 17
54#define MC13783_LED_C2_BL_C_MASK 0x7
55#define MC13783_LED_C2_MD_C 0
56#define MC13783_LED_C2_AD_C 3
57#define MC13783_LED_C2_KP_C 6
58
59#define MC13783_REG_LED_CONTROL_3 54
60#define MC13783_LED_C3_TC_P 6
61#define MC13783_LED_C3_TC_P_MASK 0x1f
62
63#define MC13783_REG_LED_CONTROL_4 55
64#define MC13783_REG_LED_CONTROL_5 56
65
66#define MC13783_LED_Cx_PERIOD 21
67#define MC13783_LED_Cx_PERIOD_MASK 0x3
68#define MC13783_LED_Cx_SLEWLIM_BIT (1 << 23)
69#define MC13783_LED_Cx_TRIODE_TC_BIT (1 << 23)
70#define MC13783_LED_Cx_TC_C_MASK 0x3
71
72static void mc13783_led_work(struct work_struct *work)
73{
74 struct mc13783_led *led = container_of(work, struct mc13783_led, work);
75 int reg = 0;
76 int mask = 0;
77 int value = 0;
78 int bank, off, shift;
79
80 switch (led->id) {
81 case MC13783_LED_MD:
82 reg = MC13783_REG_LED_CONTROL_2;
83 mask = MC13783_LED_C2_BL_P_MASK << MC13783_LED_C2_MD_P;
84 value = (led->new_brightness >> 4) << MC13783_LED_C2_MD_P;
85 break;
86 case MC13783_LED_AD:
87 reg = MC13783_REG_LED_CONTROL_2;
88 mask = MC13783_LED_C2_BL_P_MASK << MC13783_LED_C2_AD_P;
89 value = (led->new_brightness >> 4) << MC13783_LED_C2_AD_P;
90 break;
91 case MC13783_LED_KP:
92 reg = MC13783_REG_LED_CONTROL_2;
93 mask = MC13783_LED_C2_BL_P_MASK << MC13783_LED_C2_KP_P;
94 value = (led->new_brightness >> 4) << MC13783_LED_C2_KP_P;
95 break;
96 case MC13783_LED_R1:
97 case MC13783_LED_G1:
98 case MC13783_LED_B1:
99 case MC13783_LED_R2:
100 case MC13783_LED_G2:
101 case MC13783_LED_B2:
102 case MC13783_LED_R3:
103 case MC13783_LED_G3:
104 case MC13783_LED_B3:
105 off = led->id - MC13783_LED_R1;
106 bank = off/3;
107 reg = MC13783_REG_LED_CONTROL_3 + off/3;
108 shift = (off - bank * 3) * 5 + MC13783_LED_C3_TC_P;
109 value = (led->new_brightness >> 3) << shift;
110 mask = MC13783_LED_C3_TC_P_MASK << shift;
111 break;
112 }
113
114 mc13783_lock(led->master);
115
116 mc13783_reg_rmw(led->master, reg, mask, value);
117
118 mc13783_unlock(led->master);
119}
120
121static void mc13783_led_set(struct led_classdev *led_cdev,
122 enum led_brightness value)
123{
124 struct mc13783_led *led;
125
126 led = container_of(led_cdev, struct mc13783_led, cdev);
127 led->new_brightness = value;
128 schedule_work(&led->work);
129}
130
131static int __devinit mc13783_led_setup(struct mc13783_led *led, int max_current)
132{
133 int shift = 0;
134 int mask = 0;
135 int value = 0;
136 int reg = 0;
137 int ret, bank;
138
139 switch (led->id) {
140 case MC13783_LED_MD:
141 shift = MC13783_LED_C2_MD_C;
142 mask = MC13783_LED_C2_BL_C_MASK;
143 value = max_current & MC13783_LED_C2_BL_C_MASK;
144 reg = MC13783_REG_LED_CONTROL_2;
145 break;
146 case MC13783_LED_AD:
147 shift = MC13783_LED_C2_AD_C;
148 mask = MC13783_LED_C2_BL_C_MASK;
149 value = max_current & MC13783_LED_C2_BL_C_MASK;
150 reg = MC13783_REG_LED_CONTROL_2;
151 break;
152 case MC13783_LED_KP:
153 shift = MC13783_LED_C2_KP_C;
154 mask = MC13783_LED_C2_BL_C_MASK;
155 value = max_current & MC13783_LED_C2_BL_C_MASK;
156 reg = MC13783_REG_LED_CONTROL_2;
157 break;
158 case MC13783_LED_R1:
159 case MC13783_LED_G1:
160 case MC13783_LED_B1:
161 case MC13783_LED_R2:
162 case MC13783_LED_G2:
163 case MC13783_LED_B2:
164 case MC13783_LED_R3:
165 case MC13783_LED_G3:
166 case MC13783_LED_B3:
167 bank = (led->id - MC13783_LED_R1)/3;
168 reg = MC13783_REG_LED_CONTROL_3 + bank;
169 shift = ((led->id - MC13783_LED_R1) - bank * 3) * 2;
170 mask = MC13783_LED_Cx_TC_C_MASK;
171 value = max_current & MC13783_LED_Cx_TC_C_MASK;
172 break;
173 }
174
175 mc13783_lock(led->master);
176
177 ret = mc13783_reg_rmw(led->master, reg, mask << shift,
178 value << shift);
179
180 mc13783_unlock(led->master);
181 return ret;
182}
183
184static int __devinit mc13783_leds_prepare(struct platform_device *pdev)
185{
186 struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
187 struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent);
188 int ret = 0;
189 int reg = 0;
190
191 mc13783_lock(dev);
192
193 if (pdata->flags & MC13783_LED_TC1HALF)
194 reg |= MC13783_LED_C1_TC1HALF_BIT;
195
196 if (pdata->flags & MC13783_LED_SLEWLIMTC)
197 reg |= MC13783_LED_Cx_SLEWLIM_BIT;
198
199 ret = mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_1, reg);
200 if (ret)
201 goto out;
202
203 reg = (pdata->bl_period & MC13783_LED_Cx_PERIOD_MASK) <<
204 MC13783_LED_Cx_PERIOD;
205
206 if (pdata->flags & MC13783_LED_SLEWLIMBL)
207 reg |= MC13783_LED_Cx_SLEWLIM_BIT;
208
209 ret = mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_2, reg);
210 if (ret)
211 goto out;
212
213 reg = (pdata->tc1_period & MC13783_LED_Cx_PERIOD_MASK) <<
214 MC13783_LED_Cx_PERIOD;
215
216 if (pdata->flags & MC13783_LED_TRIODE_TC1)
217 reg |= MC13783_LED_Cx_TRIODE_TC_BIT;
218
219 ret = mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_3, reg);
220 if (ret)
221 goto out;
222
223 reg = (pdata->tc2_period & MC13783_LED_Cx_PERIOD_MASK) <<
224 MC13783_LED_Cx_PERIOD;
225
226 if (pdata->flags & MC13783_LED_TRIODE_TC2)
227 reg |= MC13783_LED_Cx_TRIODE_TC_BIT;
228
229 ret = mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_4, reg);
230 if (ret)
231 goto out;
232
233 reg = (pdata->tc3_period & MC13783_LED_Cx_PERIOD_MASK) <<
234 MC13783_LED_Cx_PERIOD;
235
236 if (pdata->flags & MC13783_LED_TRIODE_TC3)
237 reg |= MC13783_LED_Cx_TRIODE_TC_BIT;;
238
239 ret = mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_5, reg);
240 if (ret)
241 goto out;
242
243 reg = MC13783_LED_C0_ENABLE_BIT;
244 if (pdata->flags & MC13783_LED_TRIODE_MD)
245 reg |= MC13783_LED_C0_TRIODE_MD_BIT;
246 if (pdata->flags & MC13783_LED_TRIODE_AD)
247 reg |= MC13783_LED_C0_TRIODE_AD_BIT;
248 if (pdata->flags & MC13783_LED_TRIODE_KP)
249 reg |= MC13783_LED_C0_TRIODE_KP_BIT;
250 if (pdata->flags & MC13783_LED_BOOST_EN)
251 reg |= MC13783_LED_C0_BOOST_BIT;
252
253 reg |= (pdata->abmode & MC13783_LED_C0_ABMODE_MASK) <<
254 MC13783_LED_C0_ABMODE;
255 reg |= (pdata->abref & MC13783_LED_C0_ABREF_MASK) <<
256 MC13783_LED_C0_ABREF;
257
258 ret = mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_0, reg);
259
260out:
261 mc13783_unlock(dev);
262 return ret;
263}
264
265static int __devinit mc13783_led_probe(struct platform_device *pdev)
266{
267 struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
268 struct mc13783_led_platform_data *led_cur;
269 struct mc13783_led *led, *led_dat;
270 int ret, i;
271 int init_led = 0;
272
273 if (pdata == NULL) {
274 dev_err(&pdev->dev, "missing platform data\n");
275 return -ENODEV;
276 }
277
278 if (pdata->num_leds < 1 || pdata->num_leds > MC13783_LED_MAX) {
279 dev_err(&pdev->dev, "Invalid led count %d\n", pdata->num_leds);
280 return -EINVAL;
281 }
282
283 led = kzalloc(sizeof(*led) * pdata->num_leds, GFP_KERNEL);
284 if (led == NULL) {
285 dev_err(&pdev->dev, "failed to alloc memory\n");
286 return -ENOMEM;
287 }
288
289 ret = mc13783_leds_prepare(pdev);
290 if (ret) {
291 dev_err(&pdev->dev, "unable to init led driver\n");
292 goto err_free;
293 }
294
295 for (i = 0; i < pdata->num_leds; i++) {
296 led_dat = &led[i];
297 led_cur = &pdata->led[i];
298
299 if (led_cur->id > MC13783_LED_MAX || led_cur->id < 0) {
300 dev_err(&pdev->dev, "invalid id %d\n", led_cur->id);
301 ret = -EINVAL;
302 goto err_register;
303 }
304
305 if (init_led & (1 << led_cur->id)) {
306 dev_err(&pdev->dev, "led %d already initialized\n",
307 led_cur->id);
308 ret = -EINVAL;
309 goto err_register;
310 }
311
312 init_led |= 1 << led_cur->id;
313 led_dat->cdev.name = led_cur->name;
314 led_dat->cdev.default_trigger = led_cur->default_trigger;
315 led_dat->cdev.brightness_set = mc13783_led_set;
316 led_dat->cdev.brightness = LED_OFF;
317 led_dat->id = led_cur->id;
318 led_dat->master = dev_get_drvdata(pdev->dev.parent);
319
320 INIT_WORK(&led_dat->work, mc13783_led_work);
321
322 ret = led_classdev_register(pdev->dev.parent, &led_dat->cdev);
323 if (ret) {
324 dev_err(&pdev->dev, "failed to register led %d\n",
325 led_dat->id);
326 goto err_register;
327 }
328
329 ret = mc13783_led_setup(led_dat, led_cur->max_current);
330 if (ret) {
331 dev_err(&pdev->dev, "unable to init led %d\n",
332 led_dat->id);
333 i++;
334 goto err_register;
335 }
336 }
337
338 platform_set_drvdata(pdev, led);
339 return 0;
340
341err_register:
342 for (i = i - 1; i >= 0; i--) {
343 led_classdev_unregister(&led[i].cdev);
344 cancel_work_sync(&led[i].work);
345 }
346
347err_free:
348 kfree(led);
349 return ret;
350}
351
352static int __devexit mc13783_led_remove(struct platform_device *pdev)
353{
354 struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
355 struct mc13783_led *led = platform_get_drvdata(pdev);
356 struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent);
357 int i;
358
359 for (i = 0; i < pdata->num_leds; i++) {
360 led_classdev_unregister(&led[i].cdev);
361 cancel_work_sync(&led[i].work);
362 }
363
364 mc13783_lock(dev);
365
366 mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_0, 0);
367 mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_1, 0);
368 mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_2, 0);
369 mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_3, 0);
370 mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_4, 0);
371 mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_5, 0);
372
373 mc13783_unlock(dev);
374
375 kfree(led);
376 return 0;
377}
378
379static struct platform_driver mc13783_led_driver = {
380 .driver = {
381 .name = "mc13783-led",
382 .owner = THIS_MODULE,
383 },
384 .probe = mc13783_led_probe,
385 .remove = __devexit_p(mc13783_led_remove),
386};
387
388static int __init mc13783_led_init(void)
389{
390 return platform_driver_register(&mc13783_led_driver);
391}
392module_init(mc13783_led_init);
393
394static void __exit mc13783_led_exit(void)
395{
396 platform_driver_unregister(&mc13783_led_driver);
397}
398module_exit(mc13783_led_exit);
399
400MODULE_DESCRIPTION("LEDs driver for Freescale MC13783 PMIC");
401MODULE_AUTHOR("Philippe Retornaz <philippe.retornaz@epfl.ch>");
402MODULE_LICENSE("GPL");
403MODULE_ALIAS("platform:mc13783-led");
diff --git a/drivers/leds/leds-net5501.c b/drivers/leds/leds-net5501.c
new file mode 100644
index 000000000000..3063f591f0dc
--- /dev/null
+++ b/drivers/leds/leds-net5501.c
@@ -0,0 +1,94 @@
1/*
2 * Soekris board support code
3 *
4 * Copyright (C) 2008-2009 Tower Technologies
5 * Written by Alessandro Zummo <a.zummo@towertech.it>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2
9 * as published by the Free Software Foundation.
10 */
11
12#include <linux/kernel.h>
13#include <linux/init.h>
14#include <linux/io.h>
15#include <linux/string.h>
16#include <linux/leds.h>
17#include <linux/platform_device.h>
18#include <linux/gpio.h>
19
20#include <asm/geode.h>
21
22static struct gpio_led net5501_leds[] = {
23 {
24 .name = "error",
25 .gpio = 6,
26 .default_trigger = "default-on",
27 },
28};
29
30static struct gpio_led_platform_data net5501_leds_data = {
31 .num_leds = ARRAY_SIZE(net5501_leds),
32 .leds = net5501_leds,
33};
34
35static struct platform_device net5501_leds_dev = {
36 .name = "leds-gpio",
37 .id = -1,
38 .dev.platform_data = &net5501_leds_data,
39};
40
41static void __init init_net5501(void)
42{
43 platform_device_register(&net5501_leds_dev);
44}
45
46struct soekris_board {
47 u16 offset;
48 char *sig;
49 u8 len;
50 void (*init)(void);
51};
52
53static struct soekris_board __initdata boards[] = {
54 { 0xb7b, "net5501", 7, init_net5501 }, /* net5501 v1.33/1.33c */
55 { 0xb1f, "net5501", 7, init_net5501 }, /* net5501 v1.32i */
56};
57
58static int __init soekris_init(void)
59{
60 int i;
61 unsigned char *rombase, *bios;
62
63 if (!is_geode())
64 return 0;
65
66 rombase = ioremap(0xffff0000, 0xffff);
67 if (!rombase) {
68 printk(KERN_INFO "Soekris net5501 LED driver failed to get rombase");
69 return 0;
70 }
71
72 bios = rombase + 0x20; /* null terminated */
73
74 if (strncmp(bios, "comBIOS", 7))
75 goto unmap;
76
77 for (i = 0; i < ARRAY_SIZE(boards); i++) {
78 unsigned char *model = rombase + boards[i].offset;
79
80 if (strncmp(model, boards[i].sig, boards[i].len) == 0) {
81 printk(KERN_INFO "Soekris %s: %s\n", model, bios);
82
83 if (boards[i].init)
84 boards[i].init();
85 break;
86 }
87 }
88
89unmap:
90 iounmap(rombase);
91 return 0;
92}
93
94arch_initcall(soekris_init);
diff --git a/drivers/leds/leds-pca9532.c b/drivers/leds/leds-pca9532.c
index 6682175fa9f7..43d08756d823 100644
--- a/drivers/leds/leds-pca9532.c
+++ b/drivers/leds/leds-pca9532.c
@@ -320,10 +320,8 @@ static int pca9532_probe(struct i2c_client *client,
320 mutex_init(&data->update_lock); 320 mutex_init(&data->update_lock);
321 321
322 err = pca9532_configure(client, data, pca9532_pdata); 322 err = pca9532_configure(client, data, pca9532_pdata);
323 if (err) { 323 if (err)
324 kfree(data); 324 kfree(data);
325 i2c_set_clientdata(client, NULL);
326 }
327 325
328 return err; 326 return err;
329} 327}
@@ -351,7 +349,6 @@ static int pca9532_remove(struct i2c_client *client)
351 } 349 }
352 350
353 kfree(data); 351 kfree(data);
354 i2c_set_clientdata(client, NULL);
355 return 0; 352 return 0;
356} 353}
357 354
diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c
index 8ff50f234190..66aa3e8e786f 100644
--- a/drivers/leds/leds-pca955x.c
+++ b/drivers/leds/leds-pca955x.c
@@ -342,7 +342,6 @@ exit:
342 } 342 }
343 343
344 kfree(pca955x); 344 kfree(pca955x);
345 i2c_set_clientdata(client, NULL);
346 345
347 return err; 346 return err;
348} 347}
@@ -358,7 +357,6 @@ static int __devexit pca955x_remove(struct i2c_client *client)
358 } 357 }
359 358
360 kfree(pca955x); 359 kfree(pca955x);
361 i2c_set_clientdata(client, NULL);
362 360
363 return 0; 361 return 0;
364} 362}
diff --git a/drivers/leds/leds-ss4200.c b/drivers/leds/leds-ss4200.c
index 51477ec71391..a688293abd0b 100644
--- a/drivers/leds/leds-ss4200.c
+++ b/drivers/leds/leds-ss4200.c
@@ -534,7 +534,7 @@ static int __init nas_gpio_init(void)
534 set_power_light_amber_noblink(); 534 set_power_light_amber_noblink();
535 return 0; 535 return 0;
536out_err: 536out_err:
537 for (; i >= 0; i--) 537 for (i--; i >= 0; i--)
538 unregister_nasgpio_led(i); 538 unregister_nasgpio_led(i);
539 pci_unregister_driver(&nas_gpio_pci_driver); 539 pci_unregister_driver(&nas_gpio_pci_driver);
540 return ret; 540 return ret;
diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c
index 97147804a49c..b6e7ddc09d76 100644
--- a/drivers/macintosh/macio_asic.c
+++ b/drivers/macintosh/macio_asic.c
@@ -492,8 +492,8 @@ static void macio_pci_add_devices(struct macio_chip *chip)
492 } 492 }
493 493
494 /* Add media bay devices if any */ 494 /* Add media bay devices if any */
495 pnode = mbdev->ofdev.dev.of_node; 495 if (mbdev) {
496 if (mbdev) 496 pnode = mbdev->ofdev.dev.of_node;
497 for (np = NULL; (np = of_get_next_child(pnode, np)) != NULL;) { 497 for (np = NULL; (np = of_get_next_child(pnode, np)) != NULL;) {
498 if (macio_skip_device(np)) 498 if (macio_skip_device(np))
499 continue; 499 continue;
@@ -502,10 +502,11 @@ static void macio_pci_add_devices(struct macio_chip *chip)
502 mbdev, root_res) == NULL) 502 mbdev, root_res) == NULL)
503 of_node_put(np); 503 of_node_put(np);
504 } 504 }
505 }
505 506
506 /* Add serial ports if any */ 507 /* Add serial ports if any */
507 pnode = sdev->ofdev.dev.of_node;
508 if (sdev) { 508 if (sdev) {
509 pnode = sdev->ofdev.dev.of_node;
509 for (np = NULL; (np = of_get_next_child(pnode, np)) != NULL;) { 510 for (np = NULL; (np = of_get_next_child(pnode, np)) != NULL;) {
510 if (macio_skip_device(np)) 511 if (macio_skip_device(np))
511 continue; 512 continue;
@@ -525,7 +526,6 @@ static void macio_pci_add_devices(struct macio_chip *chip)
525int macio_register_driver(struct macio_driver *drv) 526int macio_register_driver(struct macio_driver *drv)
526{ 527{
527 /* initialize common driver fields */ 528 /* initialize common driver fields */
528 drv->driver.name = drv->name;
529 drv->driver.bus = &macio_bus_type; 529 drv->driver.bus = &macio_bus_type;
530 530
531 /* register with core */ 531 /* register with core */
diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c
index 288acce76b74..2fd435bc542e 100644
--- a/drivers/macintosh/mediabay.c
+++ b/drivers/macintosh/mediabay.c
@@ -728,8 +728,10 @@ static struct of_device_id media_bay_match[] =
728 728
729static struct macio_driver media_bay_driver = 729static struct macio_driver media_bay_driver =
730{ 730{
731 .name = "media-bay", 731 .driver = {
732 .match_table = media_bay_match, 732 .name = "media-bay",
733 .of_match_table = media_bay_match,
734 },
733 .probe = media_bay_attach, 735 .probe = media_bay_attach,
734 .suspend = media_bay_suspend, 736 .suspend = media_bay_suspend,
735 .resume = media_bay_resume 737 .resume = media_bay_resume
diff --git a/drivers/macintosh/rack-meter.c b/drivers/macintosh/rack-meter.c
index 12946c5f583f..53cce3a5da23 100644
--- a/drivers/macintosh/rack-meter.c
+++ b/drivers/macintosh/rack-meter.c
@@ -584,9 +584,11 @@ static struct of_device_id rackmeter_match[] = {
584}; 584};
585 585
586static struct macio_driver rackmeter_driver = { 586static struct macio_driver rackmeter_driver = {
587 .name = "rackmeter", 587 .driver = {
588 .owner = THIS_MODULE, 588 .name = "rackmeter",
589 .match_table = rackmeter_match, 589 .owner = THIS_MODULE,
590 .of_match_table = rackmeter_match,
591 },
590 .probe = rackmeter_probe, 592 .probe = rackmeter_probe,
591 .remove = __devexit_p(rackmeter_remove), 593 .remove = __devexit_p(rackmeter_remove),
592 .shutdown = rackmeter_shutdown, 594 .shutdown = rackmeter_shutdown,
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
index 16d82f17ae82..c42eeb43042d 100644
--- a/drivers/macintosh/therm_adt746x.c
+++ b/drivers/macintosh/therm_adt746x.c
@@ -182,7 +182,6 @@ remove_thermostat(struct i2c_client *client)
182 182
183 thermostat = NULL; 183 thermostat = NULL;
184 184
185 i2c_set_clientdata(client, NULL);
186 kfree(th); 185 kfree(th);
187 186
188 return 0; 187 return 0;
@@ -400,7 +399,6 @@ static int probe_thermostat(struct i2c_client *client,
400 rc = read_reg(th, CONFIG_REG); 399 rc = read_reg(th, CONFIG_REG);
401 if (rc < 0) { 400 if (rc < 0) {
402 dev_err(&client->dev, "Thermostat failed to read config!\n"); 401 dev_err(&client->dev, "Thermostat failed to read config!\n");
403 i2c_set_clientdata(client, NULL);
404 kfree(th); 402 kfree(th);
405 return -ENODEV; 403 return -ENODEV;
406 } 404 }
diff --git a/drivers/macintosh/windfarm_lm75_sensor.c b/drivers/macintosh/windfarm_lm75_sensor.c
index d8257d35afde..647c6add2193 100644
--- a/drivers/macintosh/windfarm_lm75_sensor.c
+++ b/drivers/macintosh/windfarm_lm75_sensor.c
@@ -107,10 +107,8 @@ static int wf_lm75_probe(struct i2c_client *client,
107 i2c_set_clientdata(client, lm); 107 i2c_set_clientdata(client, lm);
108 108
109 rc = wf_register_sensor(&lm->sens); 109 rc = wf_register_sensor(&lm->sens);
110 if (rc) { 110 if (rc)
111 i2c_set_clientdata(client, NULL);
112 kfree(lm); 111 kfree(lm);
113 }
114 112
115 return rc; 113 return rc;
116} 114}
@@ -216,7 +214,6 @@ static int wf_lm75_remove(struct i2c_client *client)
216 /* release sensor */ 214 /* release sensor */
217 wf_unregister_sensor(&lm->sens); 215 wf_unregister_sensor(&lm->sens);
218 216
219 i2c_set_clientdata(client, NULL);
220 return 0; 217 return 0;
221} 218}
222 219
diff --git a/drivers/macintosh/windfarm_max6690_sensor.c b/drivers/macintosh/windfarm_max6690_sensor.c
index b486eb929fde..8204113268f4 100644
--- a/drivers/macintosh/windfarm_max6690_sensor.c
+++ b/drivers/macintosh/windfarm_max6690_sensor.c
@@ -81,7 +81,6 @@ static int wf_max6690_probe(struct i2c_client *client,
81 81
82 rc = wf_register_sensor(&max->sens); 82 rc = wf_register_sensor(&max->sens);
83 if (rc) { 83 if (rc) {
84 i2c_set_clientdata(client, NULL);
85 kfree(max); 84 kfree(max);
86 } 85 }
87 86
diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c
index e20330a28959..65a8ff3e1f8e 100644
--- a/drivers/macintosh/windfarm_smu_sat.c
+++ b/drivers/macintosh/windfarm_smu_sat.c
@@ -376,7 +376,6 @@ static int wf_sat_remove(struct i2c_client *client)
376 /* XXX TODO */ 376 /* XXX TODO */
377 377
378 sat->i2c = NULL; 378 sat->i2c = NULL;
379 i2c_set_clientdata(client, NULL);
380 return 0; 379 return 0;
381} 380}
382 381
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 9ea17d6c799b..d2c0f94fa37d 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -4645,7 +4645,7 @@ static int raid456_cpu_notify(struct notifier_block *nfb, unsigned long action,
4645 kfree(percpu->scribble); 4645 kfree(percpu->scribble);
4646 pr_err("%s: failed memory allocation for cpu%ld\n", 4646 pr_err("%s: failed memory allocation for cpu%ld\n",
4647 __func__, cpu); 4647 __func__, cpu);
4648 return NOTIFY_BAD; 4648 return notifier_from_errno(-ENOMEM);
4649 } 4649 }
4650 break; 4650 break;
4651 case CPU_DEAD: 4651 case CPU_DEAD:
diff --git a/drivers/media/IR/Kconfig b/drivers/media/IR/Kconfig
index 195c6cf359f6..d22a8ec523fc 100644
--- a/drivers/media/IR/Kconfig
+++ b/drivers/media/IR/Kconfig
@@ -13,6 +13,7 @@ source "drivers/media/IR/keymaps/Kconfig"
13config IR_NEC_DECODER 13config IR_NEC_DECODER
14 tristate "Enable IR raw decoder for the NEC protocol" 14 tristate "Enable IR raw decoder for the NEC protocol"
15 depends on IR_CORE 15 depends on IR_CORE
16 select BITREVERSE
16 default y 17 default y
17 18
18 ---help--- 19 ---help---
@@ -22,6 +23,7 @@ config IR_NEC_DECODER
22config IR_RC5_DECODER 23config IR_RC5_DECODER
23 tristate "Enable IR raw decoder for the RC-5 protocol" 24 tristate "Enable IR raw decoder for the RC-5 protocol"
24 depends on IR_CORE 25 depends on IR_CORE
26 select BITREVERSE
25 default y 27 default y
26 28
27 ---help--- 29 ---help---
diff --git a/drivers/media/IR/imon.c b/drivers/media/IR/imon.c
index 5e2045670004..4bbd45f4284c 100644
--- a/drivers/media/IR/imon.c
+++ b/drivers/media/IR/imon.c
@@ -94,6 +94,7 @@ struct imon_context {
94 94
95 bool display_supported; /* not all controllers do */ 95 bool display_supported; /* not all controllers do */
96 bool display_isopen; /* display port has been opened */ 96 bool display_isopen; /* display port has been opened */
97 bool rf_device; /* true if iMON 2.4G LT/DT RF device */
97 bool rf_isassociating; /* RF remote associating */ 98 bool rf_isassociating; /* RF remote associating */
98 bool dev_present_intf0; /* USB device presence, interface 0 */ 99 bool dev_present_intf0; /* USB device presence, interface 0 */
99 bool dev_present_intf1; /* USB device presence, interface 1 */ 100 bool dev_present_intf1; /* USB device presence, interface 1 */
@@ -385,7 +386,7 @@ static int display_open(struct inode *inode, struct file *file)
385 err("%s: display port is already open", __func__); 386 err("%s: display port is already open", __func__);
386 retval = -EBUSY; 387 retval = -EBUSY;
387 } else { 388 } else {
388 ictx->display_isopen = 1; 389 ictx->display_isopen = true;
389 file->private_data = ictx; 390 file->private_data = ictx;
390 dev_dbg(ictx->dev, "display port opened\n"); 391 dev_dbg(ictx->dev, "display port opened\n");
391 } 392 }
@@ -422,7 +423,7 @@ static int display_close(struct inode *inode, struct file *file)
422 err("%s: display is not open", __func__); 423 err("%s: display is not open", __func__);
423 retval = -EIO; 424 retval = -EIO;
424 } else { 425 } else {
425 ictx->display_isopen = 0; 426 ictx->display_isopen = false;
426 dev_dbg(ictx->dev, "display port closed\n"); 427 dev_dbg(ictx->dev, "display port closed\n");
427 if (!ictx->dev_present_intf0) { 428 if (!ictx->dev_present_intf0) {
428 /* 429 /*
@@ -491,12 +492,12 @@ static int send_packet(struct imon_context *ictx)
491 } 492 }
492 493
493 init_completion(&ictx->tx.finished); 494 init_completion(&ictx->tx.finished);
494 ictx->tx.busy = 1; 495 ictx->tx.busy = true;
495 smp_rmb(); /* ensure later readers know we're busy */ 496 smp_rmb(); /* ensure later readers know we're busy */
496 497
497 retval = usb_submit_urb(ictx->tx_urb, GFP_KERNEL); 498 retval = usb_submit_urb(ictx->tx_urb, GFP_KERNEL);
498 if (retval) { 499 if (retval) {
499 ictx->tx.busy = 0; 500 ictx->tx.busy = false;
500 smp_rmb(); /* ensure later readers know we're not busy */ 501 smp_rmb(); /* ensure later readers know we're not busy */
501 err("%s: error submitting urb(%d)", __func__, retval); 502 err("%s: error submitting urb(%d)", __func__, retval);
502 } else { 503 } else {
@@ -682,7 +683,7 @@ static ssize_t store_associate_remote(struct device *d,
682 return -ENODEV; 683 return -ENODEV;
683 684
684 mutex_lock(&ictx->lock); 685 mutex_lock(&ictx->lock);
685 ictx->rf_isassociating = 1; 686 ictx->rf_isassociating = true;
686 send_associate_24g(ictx); 687 send_associate_24g(ictx);
687 mutex_unlock(&ictx->lock); 688 mutex_unlock(&ictx->lock);
688 689
@@ -950,7 +951,7 @@ static void usb_tx_callback(struct urb *urb)
950 ictx->tx.status = urb->status; 951 ictx->tx.status = urb->status;
951 952
952 /* notify waiters that write has finished */ 953 /* notify waiters that write has finished */
953 ictx->tx.busy = 0; 954 ictx->tx.busy = false;
954 smp_rmb(); /* ensure later readers know we're not busy */ 955 smp_rmb(); /* ensure later readers know we're not busy */
955 complete(&ictx->tx.finished); 956 complete(&ictx->tx.finished);
956} 957}
@@ -1215,7 +1216,7 @@ static bool imon_mouse_event(struct imon_context *ictx,
1215{ 1216{
1216 char rel_x = 0x00, rel_y = 0x00; 1217 char rel_x = 0x00, rel_y = 0x00;
1217 u8 right_shift = 1; 1218 u8 right_shift = 1;
1218 bool mouse_input = 1; 1219 bool mouse_input = true;
1219 int dir = 0; 1220 int dir = 0;
1220 1221
1221 /* newer iMON device PAD or mouse button */ 1222 /* newer iMON device PAD or mouse button */
@@ -1246,7 +1247,7 @@ static bool imon_mouse_event(struct imon_context *ictx,
1246 } else if (ictx->kc == KEY_CHANNELDOWN && (buf[2] & 0x40) != 0x40) { 1247 } else if (ictx->kc == KEY_CHANNELDOWN && (buf[2] & 0x40) != 0x40) {
1247 dir = -1; 1248 dir = -1;
1248 } else 1249 } else
1249 mouse_input = 0; 1250 mouse_input = false;
1250 1251
1251 if (mouse_input) { 1252 if (mouse_input) {
1252 dev_dbg(ictx->dev, "sending mouse data via input subsystem\n"); 1253 dev_dbg(ictx->dev, "sending mouse data via input subsystem\n");
@@ -1450,7 +1451,7 @@ static void imon_incoming_packet(struct imon_context *ictx,
1450 unsigned char *buf = urb->transfer_buffer; 1451 unsigned char *buf = urb->transfer_buffer;
1451 struct device *dev = ictx->dev; 1452 struct device *dev = ictx->dev;
1452 u32 kc; 1453 u32 kc;
1453 bool norelease = 0; 1454 bool norelease = false;
1454 int i; 1455 int i;
1455 u64 temp_key; 1456 u64 temp_key;
1456 u64 panel_key = 0; 1457 u64 panel_key = 0;
@@ -1465,7 +1466,7 @@ static void imon_incoming_packet(struct imon_context *ictx,
1465 idev = ictx->idev; 1466 idev = ictx->idev;
1466 1467
1467 /* filter out junk data on the older 0xffdc imon devices */ 1468 /* filter out junk data on the older 0xffdc imon devices */
1468 if ((buf[0] == 0xff) && (buf[7] == 0xff)) 1469 if ((buf[0] == 0xff) && (buf[1] == 0xff) && (buf[2] == 0xff))
1469 return; 1470 return;
1470 1471
1471 /* Figure out what key was pressed */ 1472 /* Figure out what key was pressed */
@@ -1517,7 +1518,7 @@ static void imon_incoming_packet(struct imon_context *ictx,
1517 !(buf[1] & 0x1 || buf[1] >> 2 & 0x1))) { 1518 !(buf[1] & 0x1 || buf[1] >> 2 & 0x1))) {
1518 len = 8; 1519 len = 8;
1519 imon_pad_to_keys(ictx, buf); 1520 imon_pad_to_keys(ictx, buf);
1520 norelease = 1; 1521 norelease = true;
1521 } 1522 }
1522 1523
1523 if (debug) { 1524 if (debug) {
@@ -1580,7 +1581,7 @@ not_input_data:
1580 (buf[6] == 0x5E && buf[7] == 0xDF))) { /* DT */ 1581 (buf[6] == 0x5E && buf[7] == 0xDF))) { /* DT */
1581 dev_warn(dev, "%s: remote associated refid=%02X\n", 1582 dev_warn(dev, "%s: remote associated refid=%02X\n",
1582 __func__, buf[1]); 1583 __func__, buf[1]);
1583 ictx->rf_isassociating = 0; 1584 ictx->rf_isassociating = false;
1584 } 1585 }
1585} 1586}
1586 1587
@@ -1790,9 +1791,9 @@ static bool imon_find_endpoints(struct imon_context *ictx,
1790 int ifnum = iface_desc->desc.bInterfaceNumber; 1791 int ifnum = iface_desc->desc.bInterfaceNumber;
1791 int num_endpts = iface_desc->desc.bNumEndpoints; 1792 int num_endpts = iface_desc->desc.bNumEndpoints;
1792 int i, ep_dir, ep_type; 1793 int i, ep_dir, ep_type;
1793 bool ir_ep_found = 0; 1794 bool ir_ep_found = false;
1794 bool display_ep_found = 0; 1795 bool display_ep_found = false;
1795 bool tx_control = 0; 1796 bool tx_control = false;
1796 1797
1797 /* 1798 /*
1798 * Scan the endpoint list and set: 1799 * Scan the endpoint list and set:
@@ -1808,13 +1809,13 @@ static bool imon_find_endpoints(struct imon_context *ictx,
1808 ep_type == USB_ENDPOINT_XFER_INT) { 1809 ep_type == USB_ENDPOINT_XFER_INT) {
1809 1810
1810 rx_endpoint = ep; 1811 rx_endpoint = ep;
1811 ir_ep_found = 1; 1812 ir_ep_found = true;
1812 dev_dbg(ictx->dev, "%s: found IR endpoint\n", __func__); 1813 dev_dbg(ictx->dev, "%s: found IR endpoint\n", __func__);
1813 1814
1814 } else if (!display_ep_found && ep_dir == USB_DIR_OUT && 1815 } else if (!display_ep_found && ep_dir == USB_DIR_OUT &&
1815 ep_type == USB_ENDPOINT_XFER_INT) { 1816 ep_type == USB_ENDPOINT_XFER_INT) {
1816 tx_endpoint = ep; 1817 tx_endpoint = ep;
1817 display_ep_found = 1; 1818 display_ep_found = true;
1818 dev_dbg(ictx->dev, "%s: found display endpoint\n", __func__); 1819 dev_dbg(ictx->dev, "%s: found display endpoint\n", __func__);
1819 } 1820 }
1820 } 1821 }
@@ -1835,8 +1836,8 @@ static bool imon_find_endpoints(struct imon_context *ictx,
1835 * newer iMON devices that use control urb instead of interrupt 1836 * newer iMON devices that use control urb instead of interrupt
1836 */ 1837 */
1837 if (!display_ep_found) { 1838 if (!display_ep_found) {
1838 tx_control = 1; 1839 tx_control = true;
1839 display_ep_found = 1; 1840 display_ep_found = true;
1840 dev_dbg(ictx->dev, "%s: device uses control endpoint, not " 1841 dev_dbg(ictx->dev, "%s: device uses control endpoint, not "
1841 "interface OUT endpoint\n", __func__); 1842 "interface OUT endpoint\n", __func__);
1842 } 1843 }
@@ -1847,7 +1848,7 @@ static bool imon_find_endpoints(struct imon_context *ictx,
1847 * and without... :\ 1848 * and without... :\
1848 */ 1849 */
1849 if (ictx->display_type == IMON_DISPLAY_TYPE_NONE) { 1850 if (ictx->display_type == IMON_DISPLAY_TYPE_NONE) {
1850 display_ep_found = 0; 1851 display_ep_found = false;
1851 dev_dbg(ictx->dev, "%s: device has no display\n", __func__); 1852 dev_dbg(ictx->dev, "%s: device has no display\n", __func__);
1852 } 1853 }
1853 1854
@@ -1856,7 +1857,7 @@ static bool imon_find_endpoints(struct imon_context *ictx,
1856 * that refers to e.g. /dev/lcd0 (a character device LCD or VFD). 1857 * that refers to e.g. /dev/lcd0 (a character device LCD or VFD).
1857 */ 1858 */
1858 if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) { 1859 if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) {
1859 display_ep_found = 0; 1860 display_ep_found = false;
1860 dev_dbg(ictx->dev, "%s: iMON Touch device found\n", __func__); 1861 dev_dbg(ictx->dev, "%s: iMON Touch device found\n", __func__);
1861 } 1862 }
1862 1863
@@ -1905,9 +1906,10 @@ static struct imon_context *imon_init_intf0(struct usb_interface *intf)
1905 1906
1906 ictx->dev = dev; 1907 ictx->dev = dev;
1907 ictx->usbdev_intf0 = usb_get_dev(interface_to_usbdev(intf)); 1908 ictx->usbdev_intf0 = usb_get_dev(interface_to_usbdev(intf));
1908 ictx->dev_present_intf0 = 1; 1909 ictx->dev_present_intf0 = true;
1909 ictx->rx_urb_intf0 = rx_urb; 1910 ictx->rx_urb_intf0 = rx_urb;
1910 ictx->tx_urb = tx_urb; 1911 ictx->tx_urb = tx_urb;
1912 ictx->rf_device = false;
1911 1913
1912 ictx->vendor = le16_to_cpu(ictx->usbdev_intf0->descriptor.idVendor); 1914 ictx->vendor = le16_to_cpu(ictx->usbdev_intf0->descriptor.idVendor);
1913 ictx->product = le16_to_cpu(ictx->usbdev_intf0->descriptor.idProduct); 1915 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,
1979 } 1981 }
1980 1982
1981 ictx->usbdev_intf1 = usb_get_dev(interface_to_usbdev(intf)); 1983 ictx->usbdev_intf1 = usb_get_dev(interface_to_usbdev(intf));
1982 ictx->dev_present_intf1 = 1; 1984 ictx->dev_present_intf1 = true;
1983 ictx->rx_urb_intf1 = rx_urb; 1985 ictx->rx_urb_intf1 = rx_urb;
1984 1986
1985 ret = -ENODEV; 1987 ret = -ENODEV;
@@ -2047,6 +2049,12 @@ static void imon_get_ffdc_type(struct imon_context *ictx)
2047 dev_info(ictx->dev, "0xffdc iMON Knob, iMON IR"); 2049 dev_info(ictx->dev, "0xffdc iMON Knob, iMON IR");
2048 ictx->display_supported = false; 2050 ictx->display_supported = false;
2049 break; 2051 break;
2052 /* iMON 2.4G LT (usb stick), no display, iMON RF */
2053 case 0x4e:
2054 dev_info(ictx->dev, "0xffdc iMON 2.4G LT, iMON RF");
2055 ictx->display_supported = false;
2056 ictx->rf_device = true;
2057 break;
2050 /* iMON VFD, no IR (does have vol knob tho) */ 2058 /* iMON VFD, no IR (does have vol knob tho) */
2051 case 0x35: 2059 case 0x35:
2052 dev_info(ictx->dev, "0xffdc iMON VFD + knob, no IR"); 2060 dev_info(ictx->dev, "0xffdc iMON VFD + knob, no IR");
@@ -2197,15 +2205,6 @@ static int __devinit imon_probe(struct usb_interface *interface,
2197 goto fail; 2205 goto fail;
2198 } 2206 }
2199 2207
2200 if (product == 0xffdc) {
2201 /* RF products *also* use 0xffdc... sigh... */
2202 sysfs_err = sysfs_create_group(&interface->dev.kobj,
2203 &imon_rf_attribute_group);
2204 if (sysfs_err)
2205 err("%s: Could not create RF sysfs entries(%d)",
2206 __func__, sysfs_err);
2207 }
2208
2209 } else { 2208 } else {
2210 /* this is the secondary interface on the device */ 2209 /* this is the secondary interface on the device */
2211 ictx = imon_init_intf1(interface, first_if_ctx); 2210 ictx = imon_init_intf1(interface, first_if_ctx);
@@ -2233,6 +2232,14 @@ static int __devinit imon_probe(struct usb_interface *interface,
2233 2232
2234 imon_set_display_type(ictx, interface); 2233 imon_set_display_type(ictx, interface);
2235 2234
2235 if (product == 0xffdc && ictx->rf_device) {
2236 sysfs_err = sysfs_create_group(&interface->dev.kobj,
2237 &imon_rf_attribute_group);
2238 if (sysfs_err)
2239 err("%s: Could not create RF sysfs entries(%d)",
2240 __func__, sysfs_err);
2241 }
2242
2236 if (ictx->display_supported) 2243 if (ictx->display_supported)
2237 imon_init_display(ictx, interface); 2244 imon_init_display(ictx, interface);
2238 } 2245 }
@@ -2297,7 +2304,7 @@ static void __devexit imon_disconnect(struct usb_interface *interface)
2297 } 2304 }
2298 2305
2299 if (ifnum == 0) { 2306 if (ifnum == 0) {
2300 ictx->dev_present_intf0 = 0; 2307 ictx->dev_present_intf0 = false;
2301 usb_kill_urb(ictx->rx_urb_intf0); 2308 usb_kill_urb(ictx->rx_urb_intf0);
2302 input_unregister_device(ictx->idev); 2309 input_unregister_device(ictx->idev);
2303 if (ictx->display_supported) { 2310 if (ictx->display_supported) {
@@ -2307,7 +2314,7 @@ static void __devexit imon_disconnect(struct usb_interface *interface)
2307 usb_deregister_dev(interface, &imon_vfd_class); 2314 usb_deregister_dev(interface, &imon_vfd_class);
2308 } 2315 }
2309 } else { 2316 } else {
2310 ictx->dev_present_intf1 = 0; 2317 ictx->dev_present_intf1 = false;
2311 usb_kill_urb(ictx->rx_urb_intf1); 2318 usb_kill_urb(ictx->rx_urb_intf1);
2312 if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) 2319 if (ictx->display_type == IMON_DISPLAY_TYPE_VGA)
2313 input_unregister_device(ictx->touch); 2320 input_unregister_device(ictx->touch);
diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c
index 9374a006f43d..94a8577e72eb 100644
--- a/drivers/media/IR/ir-keytable.c
+++ b/drivers/media/IR/ir-keytable.c
@@ -490,11 +490,12 @@ int __ir_input_register(struct input_dev *input_dev,
490 if (rc < 0) 490 if (rc < 0)
491 goto out_table; 491 goto out_table;
492 492
493 if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW) { 493 if (ir_dev->props)
494 rc = ir_raw_event_register(input_dev); 494 if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW) {
495 if (rc < 0) 495 rc = ir_raw_event_register(input_dev);
496 goto out_event; 496 if (rc < 0)
497 } 497 goto out_event;
498 }
498 499
499 IR_dprintk(1, "Registered input device on %s for %s remote.\n", 500 IR_dprintk(1, "Registered input device on %s for %s remote.\n",
500 driver_name, rc_tab->name); 501 driver_name, rc_tab->name);
@@ -530,8 +531,10 @@ void ir_input_unregister(struct input_dev *input_dev)
530 IR_dprintk(1, "Freed keycode table\n"); 531 IR_dprintk(1, "Freed keycode table\n");
531 532
532 del_timer_sync(&ir_dev->timer_keyup); 533 del_timer_sync(&ir_dev->timer_keyup);
533 if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW) 534 if (ir_dev->props)
534 ir_raw_event_unregister(input_dev); 535 if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW)
536 ir_raw_event_unregister(input_dev);
537
535 rc_tab = &ir_dev->rc_tab; 538 rc_tab = &ir_dev->rc_tab;
536 rc_tab->size = 0; 539 rc_tab->size = 0;
537 kfree(rc_tab->scan); 540 kfree(rc_tab->scan);
diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c
index d7da63e16c92..2098dd1488e0 100644
--- a/drivers/media/IR/ir-sysfs.c
+++ b/drivers/media/IR/ir-sysfs.c
@@ -221,9 +221,10 @@ int ir_register_class(struct input_dev *input_dev)
221 if (unlikely(devno < 0)) 221 if (unlikely(devno < 0))
222 return devno; 222 return devno;
223 223
224 if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) 224 if (ir_dev->props) {
225 ir_dev->dev.type = &rc_dev_type; 225 if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE)
226 else 226 ir_dev->dev.type = &rc_dev_type;
227 } else
227 ir_dev->dev.type = &ir_raw_dev_type; 228 ir_dev->dev.type = &ir_raw_dev_type;
228 229
229 ir_dev->dev.class = &ir_input_class; 230 ir_dev->dev.class = &ir_input_class;
diff --git a/drivers/media/IR/keymaps/Makefile b/drivers/media/IR/keymaps/Makefile
index ec25258a955f..aea649fbcf5a 100644
--- a/drivers/media/IR/keymaps/Makefile
+++ b/drivers/media/IR/keymaps/Makefile
@@ -6,7 +6,8 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
6 rc-avermedia.o \ 6 rc-avermedia.o \
7 rc-avermedia-cardbus.o \ 7 rc-avermedia-cardbus.o \
8 rc-avermedia-dvbt.o \ 8 rc-avermedia-dvbt.o \
9 rc-avermedia-m135a-rm-jx.o \ 9 rc-avermedia-m135a.o \
10 rc-avermedia-m733a-rm-k6.o \
10 rc-avertv-303.o \ 11 rc-avertv-303.o \
11 rc-behold.o \ 12 rc-behold.o \
12 rc-behold-columbus.o \ 13 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
index 101e7ea85941..000000000000
--- a/drivers/media/IR/keymaps/rc-avermedia-m135a-rm-jx.c
+++ /dev/null
@@ -1,90 +0,0 @@
1/* avermedia-m135a-rm-jx.h - Keytable for avermedia_m135a_rm_jx Remote Controller
2 *
3 * keymap imported from ir-keymaps.c
4 *
5 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <media/rc-map.h>
14
15/*
16 * Avermedia M135A with IR model RM-JX
17 * The same codes exist on both Positivo (BR) and original IR
18 * Mauro Carvalho Chehab <mchehab@infradead.org>
19 */
20
21static struct ir_scancode avermedia_m135a_rm_jx[] = {
22 { 0x0200, KEY_POWER2 },
23 { 0x022e, KEY_DOT }, /* '.' */
24 { 0x0201, KEY_MODE }, /* TV/FM or SOURCE */
25
26 { 0x0205, KEY_1 },
27 { 0x0206, KEY_2 },
28 { 0x0207, KEY_3 },
29 { 0x0209, KEY_4 },
30 { 0x020a, KEY_5 },
31 { 0x020b, KEY_6 },
32 { 0x020d, KEY_7 },
33 { 0x020e, KEY_8 },
34 { 0x020f, KEY_9 },
35 { 0x0211, KEY_0 },
36
37 { 0x0213, KEY_RIGHT }, /* -> or L */
38 { 0x0212, KEY_LEFT }, /* <- or R */
39
40 { 0x0217, KEY_SLEEP }, /* Capturar Imagem or Snapshot */
41 { 0x0210, KEY_SHUFFLE }, /* Amostra or 16 chan prev */
42
43 { 0x0303, KEY_CHANNELUP },
44 { 0x0302, KEY_CHANNELDOWN },
45 { 0x021f, KEY_VOLUMEUP },
46 { 0x021e, KEY_VOLUMEDOWN },
47 { 0x020c, KEY_ENTER }, /* Full Screen */
48
49 { 0x0214, KEY_MUTE },
50 { 0x0208, KEY_AUDIO },
51
52 { 0x0203, KEY_TEXT }, /* Teletext */
53 { 0x0204, KEY_EPG },
54 { 0x022b, KEY_TV2 }, /* TV2 or PIP */
55
56 { 0x021d, KEY_RED },
57 { 0x021c, KEY_YELLOW },
58 { 0x0301, KEY_GREEN },
59 { 0x0300, KEY_BLUE },
60
61 { 0x021a, KEY_PLAYPAUSE },
62 { 0x0219, KEY_RECORD },
63 { 0x0218, KEY_PLAY },
64 { 0x021b, KEY_STOP },
65};
66
67static struct rc_keymap avermedia_m135a_rm_jx_map = {
68 .map = {
69 .scan = avermedia_m135a_rm_jx,
70 .size = ARRAY_SIZE(avermedia_m135a_rm_jx),
71 .ir_type = IR_TYPE_NEC,
72 .name = RC_MAP_AVERMEDIA_M135A_RM_JX,
73 }
74};
75
76static int __init init_rc_map_avermedia_m135a_rm_jx(void)
77{
78 return ir_register_map(&avermedia_m135a_rm_jx_map);
79}
80
81static void __exit exit_rc_map_avermedia_m135a_rm_jx(void)
82{
83 ir_unregister_map(&avermedia_m135a_rm_jx_map);
84}
85
86module_init(init_rc_map_avermedia_m135a_rm_jx)
87module_exit(exit_rc_map_avermedia_m135a_rm_jx)
88
89MODULE_LICENSE("GPL");
90MODULE_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
index 000000000000..e4471fb2ad1e
--- /dev/null
+++ b/drivers/media/IR/keymaps/rc-avermedia-m135a.c
@@ -0,0 +1,147 @@
1/* avermedia-m135a.c - Keytable for Avermedia M135A Remote Controllers
2 *
3 * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
4 * Copyright (c) 2010 by Herton Ronaldo Krzesinski <herton@mandriva.com.br>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#include <media/rc-map.h>
13
14/*
15 * Avermedia M135A with RM-JX and RM-K6 remote controls
16 *
17 * On Avermedia M135A with IR model RM-JX, the same codes exist on both
18 * Positivo (BR) and original IR, initial version and remote control codes
19 * added by Mauro Carvalho Chehab <mchehab@infradead.org>
20 *
21 * Positivo also ships Avermedia M135A with model RM-K6, extra control
22 * codes added by Herton Ronaldo Krzesinski <herton@mandriva.com.br>
23 */
24
25static struct ir_scancode avermedia_m135a[] = {
26 /* RM-JX */
27 { 0x0200, KEY_POWER2 },
28 { 0x022e, KEY_DOT }, /* '.' */
29 { 0x0201, KEY_MODE }, /* TV/FM or SOURCE */
30
31 { 0x0205, KEY_1 },
32 { 0x0206, KEY_2 },
33 { 0x0207, KEY_3 },
34 { 0x0209, KEY_4 },
35 { 0x020a, KEY_5 },
36 { 0x020b, KEY_6 },
37 { 0x020d, KEY_7 },
38 { 0x020e, KEY_8 },
39 { 0x020f, KEY_9 },
40 { 0x0211, KEY_0 },
41
42 { 0x0213, KEY_RIGHT }, /* -> or L */
43 { 0x0212, KEY_LEFT }, /* <- or R */
44
45 { 0x0217, KEY_SLEEP }, /* Capturar Imagem or Snapshot */
46 { 0x0210, KEY_SHUFFLE }, /* Amostra or 16 chan prev */
47
48 { 0x0303, KEY_CHANNELUP },
49 { 0x0302, KEY_CHANNELDOWN },
50 { 0x021f, KEY_VOLUMEUP },
51 { 0x021e, KEY_VOLUMEDOWN },
52 { 0x020c, KEY_ENTER }, /* Full Screen */
53
54 { 0x0214, KEY_MUTE },
55 { 0x0208, KEY_AUDIO },
56
57 { 0x0203, KEY_TEXT }, /* Teletext */
58 { 0x0204, KEY_EPG },
59 { 0x022b, KEY_TV2 }, /* TV2 or PIP */
60
61 { 0x021d, KEY_RED },
62 { 0x021c, KEY_YELLOW },
63 { 0x0301, KEY_GREEN },
64 { 0x0300, KEY_BLUE },
65
66 { 0x021a, KEY_PLAYPAUSE },
67 { 0x0219, KEY_RECORD },
68 { 0x0218, KEY_PLAY },
69 { 0x021b, KEY_STOP },
70
71 /* RM-K6 */
72 { 0x0401, KEY_POWER2 },
73 { 0x0406, KEY_MUTE },
74 { 0x0408, KEY_MODE }, /* TV/FM */
75
76 { 0x0409, KEY_1 },
77 { 0x040a, KEY_2 },
78 { 0x040b, KEY_3 },
79 { 0x040c, KEY_4 },
80 { 0x040d, KEY_5 },
81 { 0x040e, KEY_6 },
82 { 0x040f, KEY_7 },
83 { 0x0410, KEY_8 },
84 { 0x0411, KEY_9 },
85 { 0x044c, KEY_DOT }, /* '.' */
86 { 0x0412, KEY_0 },
87 { 0x0407, KEY_REFRESH }, /* Refresh/Reload */
88
89 { 0x0413, KEY_AUDIO },
90 { 0x0440, KEY_SCREEN }, /* Full Screen toggle */
91 { 0x0441, KEY_HOME },
92 { 0x0442, KEY_BACK },
93 { 0x0447, KEY_UP },
94 { 0x0448, KEY_DOWN },
95 { 0x0449, KEY_LEFT },
96 { 0x044a, KEY_RIGHT },
97 { 0x044b, KEY_OK },
98 { 0x0404, KEY_VOLUMEUP },
99 { 0x0405, KEY_VOLUMEDOWN },
100 { 0x0402, KEY_CHANNELUP },
101 { 0x0403, KEY_CHANNELDOWN },
102
103 { 0x0443, KEY_RED },
104 { 0x0444, KEY_GREEN },
105 { 0x0445, KEY_YELLOW },
106 { 0x0446, KEY_BLUE },
107
108 { 0x0414, KEY_TEXT },
109 { 0x0415, KEY_EPG },
110 { 0x041a, KEY_TV2 }, /* PIP */
111 { 0x041b, KEY_MHP }, /* Snapshot */
112
113 { 0x0417, KEY_RECORD },
114 { 0x0416, KEY_PLAYPAUSE },
115 { 0x0418, KEY_STOP },
116 { 0x0419, KEY_PAUSE },
117
118 { 0x041f, KEY_PREVIOUS },
119 { 0x041c, KEY_REWIND },
120 { 0x041d, KEY_FORWARD },
121 { 0x041e, KEY_NEXT },
122};
123
124static struct rc_keymap avermedia_m135a_map = {
125 .map = {
126 .scan = avermedia_m135a,
127 .size = ARRAY_SIZE(avermedia_m135a),
128 .ir_type = IR_TYPE_NEC,
129 .name = RC_MAP_AVERMEDIA_M135A,
130 }
131};
132
133static int __init init_rc_map_avermedia_m135a(void)
134{
135 return ir_register_map(&avermedia_m135a_map);
136}
137
138static void __exit exit_rc_map_avermedia_m135a(void)
139{
140 ir_unregister_map(&avermedia_m135a_map);
141}
142
143module_init(init_rc_map_avermedia_m135a)
144module_exit(exit_rc_map_avermedia_m135a)
145
146MODULE_LICENSE("GPL");
147MODULE_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
index 000000000000..cf8d45717cb3
--- /dev/null
+++ b/drivers/media/IR/keymaps/rc-avermedia-m733a-rm-k6.c
@@ -0,0 +1,95 @@
1/* avermedia-m733a-rm-k6.h - Keytable for avermedia_m733a_rm_k6 Remote Controller
2 *
3 * Copyright (c) 2010 by Herton Ronaldo Krzesinski <herton@mandriva.com.br>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 */
10
11#include <media/rc-map.h>
12
13/*
14 * Avermedia M733A with IR model RM-K6
15 * This is the stock remote controller used with Positivo machines with M733A
16 * Herton Ronaldo Krzesinski <herton@mandriva.com.br>
17 */
18
19static struct ir_scancode avermedia_m733a_rm_k6[] = {
20 { 0x0401, KEY_POWER2 },
21 { 0x0406, KEY_MUTE },
22 { 0x0408, KEY_MODE }, /* TV/FM */
23
24 { 0x0409, KEY_1 },
25 { 0x040a, KEY_2 },
26 { 0x040b, KEY_3 },
27 { 0x040c, KEY_4 },
28 { 0x040d, KEY_5 },
29 { 0x040e, KEY_6 },
30 { 0x040f, KEY_7 },
31 { 0x0410, KEY_8 },
32 { 0x0411, KEY_9 },
33 { 0x044c, KEY_DOT }, /* '.' */
34 { 0x0412, KEY_0 },
35 { 0x0407, KEY_REFRESH }, /* Refresh/Reload */
36
37 { 0x0413, KEY_AUDIO },
38 { 0x0440, KEY_SCREEN }, /* Full Screen toggle */
39 { 0x0441, KEY_HOME },
40 { 0x0442, KEY_BACK },
41 { 0x0447, KEY_UP },
42 { 0x0448, KEY_DOWN },
43 { 0x0449, KEY_LEFT },
44 { 0x044a, KEY_RIGHT },
45 { 0x044b, KEY_OK },
46 { 0x0404, KEY_VOLUMEUP },
47 { 0x0405, KEY_VOLUMEDOWN },
48 { 0x0402, KEY_CHANNELUP },
49 { 0x0403, KEY_CHANNELDOWN },
50
51 { 0x0443, KEY_RED },
52 { 0x0444, KEY_GREEN },
53 { 0x0445, KEY_YELLOW },
54 { 0x0446, KEY_BLUE },
55
56 { 0x0414, KEY_TEXT },
57 { 0x0415, KEY_EPG },
58 { 0x041a, KEY_TV2 }, /* PIP */
59 { 0x041b, KEY_MHP }, /* Snapshot */
60
61 { 0x0417, KEY_RECORD },
62 { 0x0416, KEY_PLAYPAUSE },
63 { 0x0418, KEY_STOP },
64 { 0x0419, KEY_PAUSE },
65
66 { 0x041f, KEY_PREVIOUS },
67 { 0x041c, KEY_REWIND },
68 { 0x041d, KEY_FORWARD },
69 { 0x041e, KEY_NEXT },
70};
71
72static struct rc_keymap avermedia_m733a_rm_k6_map = {
73 .map = {
74 .scan = avermedia_m733a_rm_k6,
75 .size = ARRAY_SIZE(avermedia_m733a_rm_k6),
76 .ir_type = IR_TYPE_NEC,
77 .name = RC_MAP_AVERMEDIA_M733A_RM_K6,
78 }
79};
80
81static int __init init_rc_map_avermedia_m733a_rm_k6(void)
82{
83 return ir_register_map(&avermedia_m733a_rm_k6_map);
84}
85
86static void __exit exit_rc_map_avermedia_m733a_rm_k6(void)
87{
88 ir_unregister_map(&avermedia_m733a_rm_k6_map);
89}
90
91module_init(init_rc_map_avermedia_m733a_rm_k6)
92module_exit(exit_rc_map_avermedia_m733a_rm_k6)
93
94MODULE_LICENSE("GPL");
95MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c
index b762e561a6d5..bca07c0bcd01 100644
--- a/drivers/media/dvb/dm1105/dm1105.c
+++ b/drivers/media/dvb/dm1105/dm1105.c
@@ -594,7 +594,7 @@ static irqreturn_t dm1105_irq(int irq, void *dev_id)
594int __devinit dm1105_ir_init(struct dm1105_dev *dm1105) 594int __devinit dm1105_ir_init(struct dm1105_dev *dm1105)
595{ 595{
596 struct input_dev *input_dev; 596 struct input_dev *input_dev;
597 char *ir_codes = NULL; 597 char *ir_codes = RC_MAP_DM1105_NEC;
598 int err = -ENOMEM; 598 int err = -ENOMEM;
599 599
600 input_dev = input_allocate_device(); 600 input_dev = input_allocate_device();
diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
index f6dac2bb0ac6..6c3a8a06ccab 100644
--- a/drivers/media/dvb/dvb-core/dvb_net.c
+++ b/drivers/media/dvb/dvb-core/dvb_net.c
@@ -351,6 +351,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
351 const u8 *ts, *ts_end, *from_where = NULL; 351 const u8 *ts, *ts_end, *from_where = NULL;
352 u8 ts_remain = 0, how_much = 0, new_ts = 1; 352 u8 ts_remain = 0, how_much = 0, new_ts = 1;
353 struct ethhdr *ethh = NULL; 353 struct ethhdr *ethh = NULL;
354 bool error = false;
354 355
355#ifdef ULE_DEBUG 356#ifdef ULE_DEBUG
356 /* The code inside ULE_DEBUG keeps a history of the last 100 TS cells processed. */ 357 /* 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 )
460 461
461 /* Drop partly decoded SNDU, reset state, resync on PUSI. */ 462 /* Drop partly decoded SNDU, reset state, resync on PUSI. */
462 if (priv->ule_skb) { 463 if (priv->ule_skb) {
463 dev_kfree_skb( priv->ule_skb ); 464 error = true;
465 dev_kfree_skb(priv->ule_skb);
466 }
467
468 if (error || priv->ule_sndu_remain) {
464 dev->stats.rx_errors++; 469 dev->stats.rx_errors++;
465 dev->stats.rx_frame_errors++; 470 dev->stats.rx_frame_errors++;
471 error = false;
466 } 472 }
473
467 reset_ule(priv); 474 reset_ule(priv);
468 priv->need_pusi = 1; 475 priv->need_pusi = 1;
469 continue; 476 continue;
@@ -535,6 +542,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
535 from_where += 2; 542 from_where += 2;
536 } 543 }
537 544
545 priv->ule_sndu_remain = priv->ule_sndu_len + 2;
538 /* 546 /*
539 * State of current TS: 547 * State of current TS:
540 * ts_remain (remaining bytes in the current TS cell) 548 * 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 )
544 */ 552 */
545 switch (ts_remain) { 553 switch (ts_remain) {
546 case 1: 554 case 1:
555 priv->ule_sndu_remain--;
547 priv->ule_sndu_type = from_where[0] << 8; 556 priv->ule_sndu_type = from_where[0] << 8;
548 priv->ule_sndu_type_1 = 1; /* first byte of ule_type is set. */ 557 priv->ule_sndu_type_1 = 1; /* first byte of ule_type is set. */
549 ts_remain -= 1; from_where += 1; 558 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 )
557 default: /* complete ULE header is present in current TS. */ 566 default: /* complete ULE header is present in current TS. */
558 /* Extract ULE type field. */ 567 /* Extract ULE type field. */
559 if (priv->ule_sndu_type_1) { 568 if (priv->ule_sndu_type_1) {
569 priv->ule_sndu_type_1 = 0;
560 priv->ule_sndu_type |= from_where[0]; 570 priv->ule_sndu_type |= from_where[0];
561 from_where += 1; /* points to payload start. */ 571 from_where += 1; /* points to payload start. */
562 ts_remain -= 1; 572 ts_remain -= 1;
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
index e5f91f16ffa4..553b48ac1919 100644
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -76,6 +76,7 @@ config DVB_USB_DIB0700
76 select DVB_S5H1411 if !DVB_FE_CUSTOMISE 76 select DVB_S5H1411 if !DVB_FE_CUSTOMISE
77 select DVB_LGDT3305 if !DVB_FE_CUSTOMISE 77 select DVB_LGDT3305 if !DVB_FE_CUSTOMISE
78 select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE 78 select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE
79 select DVB_TUNER_DIB0090 if !DVB_FE_CUSTOMISE
79 select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE 80 select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
80 select MEDIA_TUNER_MT2266 if !MEDIA_TUNER_CUSTOMISE 81 select MEDIA_TUNER_MT2266 if !MEDIA_TUNER_CUSTOMISE
81 select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE 82 select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
@@ -134,6 +135,7 @@ config DVB_USB_M920X
134 select DVB_TDA1004X if !DVB_FE_CUSTOMISE 135 select DVB_TDA1004X if !DVB_FE_CUSTOMISE
135 select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE 136 select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE
136 select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE 137 select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE
138 select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
137 help 139 help
138 Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver. 140 Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver.
139 Currently, only devices with a product id of 141 Currently, only devices with a product id of
@@ -264,7 +266,7 @@ config DVB_USB_DW2102
264 select DVB_STB6000 if !DVB_FE_CUSTOMISE 266 select DVB_STB6000 if !DVB_FE_CUSTOMISE
265 select DVB_CX24116 if !DVB_FE_CUSTOMISE 267 select DVB_CX24116 if !DVB_FE_CUSTOMISE
266 select DVB_SI21XX if !DVB_FE_CUSTOMISE 268 select DVB_SI21XX if !DVB_FE_CUSTOMISE
267 select DVB_TDA10021 if !DVB_FE_CUSTOMISE 269 select DVB_TDA10023 if !DVB_FE_CUSTOMISE
268 select DVB_MT312 if !DVB_FE_CUSTOMISE 270 select DVB_MT312 if !DVB_FE_CUSTOMISE
269 select DVB_ZL10039 if !DVB_FE_CUSTOMISE 271 select DVB_ZL10039 if !DVB_FE_CUSTOMISE
270 select DVB_DS3000 if !DVB_FE_CUSTOMISE 272 select DVB_DS3000 if !DVB_FE_CUSTOMISE
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
index 0eb490889162..11e9e85dac86 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/drivers/media/dvb/dvb-usb/cxusb.c
@@ -1026,8 +1026,10 @@ static int cxusb_dualdig4_rev2_frontend_attach(struct dvb_usb_adapter *adap)
1026 cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1); 1026 cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1);
1027 1027
1028 if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, 1028 if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
1029 &cxusb_dualdig4_rev2_config) < 0) 1029 &cxusb_dualdig4_rev2_config) < 0) {
1030 printk(KERN_WARNING "Unable to enumerate dib7000p\n");
1030 return -ENODEV; 1031 return -ENODEV;
1032 }
1031 1033
1032 adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, 1034 adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
1033 &cxusb_dualdig4_rev2_config); 1035 &cxusb_dualdig4_rev2_config);
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index 085c4e457e0e..b4afe6f8ed19 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -198,6 +198,7 @@
198#define USB_PID_AVERMEDIA_A850 0x850a 198#define USB_PID_AVERMEDIA_A850 0x850a
199#define USB_PID_AVERMEDIA_A805 0xa805 199#define USB_PID_AVERMEDIA_A805 0xa805
200#define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006 200#define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006
201#define USB_PID_TECHNOTREND_CONNECT_CT3650 0x300d
201#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a 202#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a
202#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2 0x0081 203#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2 0x0081
203#define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058 204#define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058
diff --git a/drivers/media/dvb/dvb-usb/ttusb2.c b/drivers/media/dvb/dvb-usb/ttusb2.c
index 20ca9d9ee99b..a6de489a6a39 100644
--- a/drivers/media/dvb/dvb-usb/ttusb2.c
+++ b/drivers/media/dvb/dvb-usb/ttusb2.c
@@ -29,6 +29,8 @@
29 29
30#include "tda826x.h" 30#include "tda826x.h"
31#include "tda10086.h" 31#include "tda10086.h"
32#include "tda1002x.h"
33#include "tda827x.h"
32#include "lnbp21.h" 34#include "lnbp21.h"
33 35
34/* debug */ 36/* debug */
@@ -150,7 +152,17 @@ static struct tda10086_config tda10086_config = {
150 .xtal_freq = TDA10086_XTAL_16M, 152 .xtal_freq = TDA10086_XTAL_16M,
151}; 153};
152 154
153static int ttusb2_frontend_attach(struct dvb_usb_adapter *adap) 155static struct tda10023_config tda10023_config = {
156 .demod_address = 0x0c,
157 .invert = 0,
158 .xtal = 16000000,
159 .pll_m = 11,
160 .pll_p = 3,
161 .pll_n = 1,
162 .deltaf = 0xa511,
163};
164
165static int ttusb2_frontend_tda10086_attach(struct dvb_usb_adapter *adap)
154{ 166{
155 if (usb_set_interface(adap->dev->udev,0,3) < 0) 167 if (usb_set_interface(adap->dev->udev,0,3) < 0)
156 err("set interface to alts=3 failed"); 168 err("set interface to alts=3 failed");
@@ -163,7 +175,27 @@ static int ttusb2_frontend_attach(struct dvb_usb_adapter *adap)
163 return 0; 175 return 0;
164} 176}
165 177
166static int ttusb2_tuner_attach(struct dvb_usb_adapter *adap) 178static int ttusb2_frontend_tda10023_attach(struct dvb_usb_adapter *adap)
179{
180 if (usb_set_interface(adap->dev->udev, 0, 3) < 0)
181 err("set interface to alts=3 failed");
182 if ((adap->fe = dvb_attach(tda10023_attach, &tda10023_config, &adap->dev->i2c_adap, 0x48)) == NULL) {
183 deb_info("TDA10023 attach failed\n");
184 return -ENODEV;
185 }
186 return 0;
187}
188
189static int ttusb2_tuner_tda827x_attach(struct dvb_usb_adapter *adap)
190{
191 if (dvb_attach(tda827x_attach, adap->fe, 0x61, &adap->dev->i2c_adap, NULL) == NULL) {
192 printk(KERN_ERR "%s: No tda827x found!\n", __func__);
193 return -ENODEV;
194 }
195 return 0;
196}
197
198static int ttusb2_tuner_tda826x_attach(struct dvb_usb_adapter *adap)
167{ 199{
168 if (dvb_attach(tda826x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, 0) == NULL) { 200 if (dvb_attach(tda826x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, 0) == NULL) {
169 deb_info("TDA8263 attach failed\n"); 201 deb_info("TDA8263 attach failed\n");
@@ -180,6 +212,7 @@ static int ttusb2_tuner_attach(struct dvb_usb_adapter *adap)
180/* DVB USB Driver stuff */ 212/* DVB USB Driver stuff */
181static struct dvb_usb_device_properties ttusb2_properties; 213static struct dvb_usb_device_properties ttusb2_properties;
182static struct dvb_usb_device_properties ttusb2_properties_s2400; 214static struct dvb_usb_device_properties ttusb2_properties_s2400;
215static struct dvb_usb_device_properties ttusb2_properties_ct3650;
183 216
184static int ttusb2_probe(struct usb_interface *intf, 217static int ttusb2_probe(struct usb_interface *intf,
185 const struct usb_device_id *id) 218 const struct usb_device_id *id)
@@ -187,6 +220,8 @@ static int ttusb2_probe(struct usb_interface *intf,
187 if (0 == dvb_usb_device_init(intf, &ttusb2_properties, 220 if (0 == dvb_usb_device_init(intf, &ttusb2_properties,
188 THIS_MODULE, NULL, adapter_nr) || 221 THIS_MODULE, NULL, adapter_nr) ||
189 0 == dvb_usb_device_init(intf, &ttusb2_properties_s2400, 222 0 == dvb_usb_device_init(intf, &ttusb2_properties_s2400,
223 THIS_MODULE, NULL, adapter_nr) ||
224 0 == dvb_usb_device_init(intf, &ttusb2_properties_ct3650,
190 THIS_MODULE, NULL, adapter_nr)) 225 THIS_MODULE, NULL, adapter_nr))
191 return 0; 226 return 0;
192 return -ENODEV; 227 return -ENODEV;
@@ -197,6 +232,8 @@ static struct usb_device_id ttusb2_table [] = {
197 { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_450E) }, 232 { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_450E) },
198 { USB_DEVICE(USB_VID_TECHNOTREND, 233 { USB_DEVICE(USB_VID_TECHNOTREND,
199 USB_PID_TECHNOTREND_CONNECT_S2400) }, 234 USB_PID_TECHNOTREND_CONNECT_S2400) },
235 { USB_DEVICE(USB_VID_TECHNOTREND,
236 USB_PID_TECHNOTREND_CONNECT_CT3650) },
200 {} /* Terminating entry */ 237 {} /* Terminating entry */
201}; 238};
202MODULE_DEVICE_TABLE (usb, ttusb2_table); 239MODULE_DEVICE_TABLE (usb, ttusb2_table);
@@ -214,8 +251,8 @@ static struct dvb_usb_device_properties ttusb2_properties = {
214 { 251 {
215 .streaming_ctrl = NULL, // ttusb2_streaming_ctrl, 252 .streaming_ctrl = NULL, // ttusb2_streaming_ctrl,
216 253
217 .frontend_attach = ttusb2_frontend_attach, 254 .frontend_attach = ttusb2_frontend_tda10086_attach,
218 .tuner_attach = ttusb2_tuner_attach, 255 .tuner_attach = ttusb2_tuner_tda826x_attach,
219 256
220 /* parameter for the MPEG2-data transfer */ 257 /* parameter for the MPEG2-data transfer */
221 .stream = { 258 .stream = {
@@ -266,8 +303,8 @@ static struct dvb_usb_device_properties ttusb2_properties_s2400 = {
266 { 303 {
267 .streaming_ctrl = NULL, 304 .streaming_ctrl = NULL,
268 305
269 .frontend_attach = ttusb2_frontend_attach, 306 .frontend_attach = ttusb2_frontend_tda10086_attach,
270 .tuner_attach = ttusb2_tuner_attach, 307 .tuner_attach = ttusb2_tuner_tda826x_attach,
271 308
272 /* parameter for the MPEG2-data transfer */ 309 /* parameter for the MPEG2-data transfer */
273 .stream = { 310 .stream = {
@@ -301,6 +338,52 @@ static struct dvb_usb_device_properties ttusb2_properties_s2400 = {
301 } 338 }
302}; 339};
303 340
341static struct dvb_usb_device_properties ttusb2_properties_ct3650 = {
342 .caps = DVB_USB_IS_AN_I2C_ADAPTER,
343
344 .usb_ctrl = CYPRESS_FX2,
345
346 .size_of_priv = sizeof(struct ttusb2_state),
347
348 .num_adapters = 1,
349 .adapter = {
350 {
351 .streaming_ctrl = NULL,
352
353 .frontend_attach = ttusb2_frontend_tda10023_attach,
354 .tuner_attach = ttusb2_tuner_tda827x_attach,
355
356 /* parameter for the MPEG2-data transfer */
357 .stream = {
358 .type = USB_ISOC,
359 .count = 5,
360 .endpoint = 0x02,
361 .u = {
362 .isoc = {
363 .framesperurb = 4,
364 .framesize = 940,
365 .interval = 1,
366 }
367 }
368 }
369 },
370 },
371
372 .power_ctrl = ttusb2_power_ctrl,
373 .identify_state = ttusb2_identify_state,
374
375 .i2c_algo = &ttusb2_i2c_algo,
376
377 .generic_bulk_ctrl_endpoint = 0x01,
378
379 .num_device_descs = 1,
380 .devices = {
381 { "Technotrend TT-connect CT-3650",
382 .warm_ids = { &ttusb2_table[3], NULL },
383 },
384 }
385};
386
304static struct usb_driver ttusb2_driver = { 387static struct usb_driver ttusb2_driver = {
305 .name = "dvb_usb_ttusb2", 388 .name = "dvb_usb_ttusb2",
306 .probe = ttusb2_probe, 389 .probe = ttusb2_probe,
diff --git a/drivers/media/dvb/firewire/firedtv-1394.c b/drivers/media/dvb/firewire/firedtv-1394.c
index 26333b4f4d3e..b34ca7afb0e6 100644
--- a/drivers/media/dvb/firewire/firedtv-1394.c
+++ b/drivers/media/dvb/firewire/firedtv-1394.c
@@ -58,7 +58,7 @@ static void rawiso_activity_cb(struct hpsb_iso *iso)
58 num = hpsb_iso_n_ready(iso); 58 num = hpsb_iso_n_ready(iso);
59 59
60 if (!fdtv) { 60 if (!fdtv) {
61 dev_err(fdtv->device, "received at unknown iso channel\n"); 61 pr_err("received at unknown iso channel\n");
62 goto out; 62 goto out;
63 } 63 }
64 64
diff --git a/drivers/media/dvb/frontends/au8522_decoder.c b/drivers/media/dvb/frontends/au8522_decoder.c
index 68dba3a4b4da..29cdbfe36852 100644
--- a/drivers/media/dvb/frontends/au8522_decoder.c
+++ b/drivers/media/dvb/frontends/au8522_decoder.c
@@ -567,30 +567,6 @@ static int au8522_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
567 567
568/* ----------------------------------------------------------------------- */ 568/* ----------------------------------------------------------------------- */
569 569
570static int au8522_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
571{
572 switch (fmt->type) {
573 default:
574 return -EINVAL;
575 }
576 return 0;
577}
578
579static int au8522_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
580{
581 switch (fmt->type) {
582 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
583 /* Not yet implemented */
584 break;
585 default:
586 return -EINVAL;
587 }
588
589 return 0;
590}
591
592/* ----------------------------------------------------------------------- */
593
594#ifdef CONFIG_VIDEO_ADV_DEBUG 570#ifdef CONFIG_VIDEO_ADV_DEBUG
595static int au8522_g_register(struct v4l2_subdev *sd, 571static int au8522_g_register(struct v4l2_subdev *sd,
596 struct v4l2_dbg_register *reg) 572 struct v4l2_dbg_register *reg)
@@ -772,8 +748,6 @@ static const struct v4l2_subdev_audio_ops au8522_audio_ops = {
772 748
773static const struct v4l2_subdev_video_ops au8522_video_ops = { 749static const struct v4l2_subdev_video_ops au8522_video_ops = {
774 .s_routing = au8522_s_video_routing, 750 .s_routing = au8522_s_video_routing,
775 .g_fmt = au8522_g_fmt,
776 .s_fmt = au8522_s_fmt,
777 .s_stream = au8522_s_stream, 751 .s_stream = au8522_s_stream,
778}; 752};
779 753
diff --git a/drivers/media/dvb/frontends/ds3000.c b/drivers/media/dvb/frontends/ds3000.c
index 78001e8bcdb7..fc61d9230db8 100644
--- a/drivers/media/dvb/frontends/ds3000.c
+++ b/drivers/media/dvb/frontends/ds3000.c
@@ -969,15 +969,12 @@ struct dvb_frontend *ds3000_attach(const struct ds3000_config *config,
969 dprintk("%s\n", __func__); 969 dprintk("%s\n", __func__);
970 970
971 /* allocate memory for the internal state */ 971 /* allocate memory for the internal state */
972 state = kmalloc(sizeof(struct ds3000_state), GFP_KERNEL); 972 state = kzalloc(sizeof(struct ds3000_state), GFP_KERNEL);
973 if (state == NULL) { 973 if (state == NULL) {
974 printk(KERN_ERR "Unable to kmalloc\n"); 974 printk(KERN_ERR "Unable to kmalloc\n");
975 goto error2; 975 goto error2;
976 } 976 }
977 977
978 /* setup the state */
979 memset(state, 0, sizeof(struct ds3000_state));
980
981 state->config = config; 978 state->config = config;
982 state->i2c = i2c; 979 state->i2c = i2c;
983 state->prevUCBS2 = 0; 980 state->prevUCBS2 = 0;
diff --git a/drivers/media/dvb/frontends/stv6110x.c b/drivers/media/dvb/frontends/stv6110x.c
index 42591ce1aaad..f36cab12bdc7 100644
--- a/drivers/media/dvb/frontends/stv6110x.c
+++ b/drivers/media/dvb/frontends/stv6110x.c
@@ -303,7 +303,10 @@ static int stv6110x_set_mode(struct dvb_frontend *fe, enum tuner_mode mode)
303 303
304static int stv6110x_sleep(struct dvb_frontend *fe) 304static int stv6110x_sleep(struct dvb_frontend *fe)
305{ 305{
306 return stv6110x_set_mode(fe, TUNER_SLEEP); 306 if (fe->tuner_priv)
307 return stv6110x_set_mode(fe, TUNER_SLEEP);
308
309 return 0;
307} 310}
308 311
309static int stv6110x_get_status(struct dvb_frontend *fe, u32 *status) 312static int stv6110x_get_status(struct dvb_frontend *fe, u32 *status)
diff --git a/drivers/media/dvb/ngene/ngene-cards.c b/drivers/media/dvb/ngene/ngene-cards.c
index 692c3e226e83..4692a41ad95b 100644
--- a/drivers/media/dvb/ngene/ngene-cards.c
+++ b/drivers/media/dvb/ngene/ngene-cards.c
@@ -217,6 +217,19 @@ static struct ngene_info ngene_info_cineS2v5 = {
217 .fw_version = 15, 217 .fw_version = 15,
218}; 218};
219 219
220static struct ngene_info ngene_info_duoFlexS2 = {
221 .type = NGENE_SIDEWINDER,
222 .name = "Digital Devices DuoFlex S2 miniPCIe",
223 .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN},
224 .demod_attach = {demod_attach_stv0900, demod_attach_stv0900},
225 .tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110},
226 .fe_config = {&fe_cineS2, &fe_cineS2},
227 .tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1},
228 .lnb = {0x0a, 0x08},
229 .tsf = {3, 3},
230 .fw_version = 15,
231};
232
220static struct ngene_info ngene_info_m780 = { 233static struct ngene_info ngene_info_m780 = {
221 .type = NGENE_APP, 234 .type = NGENE_APP,
222 .name = "Aver M780 ATSC/QAM-B", 235 .name = "Aver M780 ATSC/QAM-B",
@@ -256,6 +269,8 @@ static const struct pci_device_id ngene_id_tbl[] __devinitdata = {
256 NGENE_ID(0x18c3, 0xdb01, ngene_info_satixS2), 269 NGENE_ID(0x18c3, 0xdb01, ngene_info_satixS2),
257 NGENE_ID(0x18c3, 0xdb02, ngene_info_satixS2v2), 270 NGENE_ID(0x18c3, 0xdb02, ngene_info_satixS2v2),
258 NGENE_ID(0x18c3, 0xdd00, ngene_info_cineS2v5), 271 NGENE_ID(0x18c3, 0xdd00, ngene_info_cineS2v5),
272 NGENE_ID(0x18c3, 0xdd10, ngene_info_duoFlexS2),
273 NGENE_ID(0x18c3, 0xdd20, ngene_info_duoFlexS2),
259 NGENE_ID(0x1461, 0x062e, ngene_info_m780), 274 NGENE_ID(0x1461, 0x062e, ngene_info_m780),
260 {0} 275 {0}
261}; 276};
diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c
index c8b4dfa0ab5f..4caeb163a666 100644
--- a/drivers/media/dvb/ngene/ngene-core.c
+++ b/drivers/media/dvb/ngene/ngene-core.c
@@ -53,8 +53,6 @@ MODULE_PARM_DESC(debug, "Print debugging information.");
53 53
54DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 54DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
55 55
56#define COMMAND_TIMEOUT_WORKAROUND
57
58#define dprintk if (debug) printk 56#define dprintk if (debug) printk
59 57
60#define ngwriteb(dat, adr) writeb((dat), (char *)(dev->iomem + (adr))) 58#define ngwriteb(dat, adr) writeb((dat), (char *)(dev->iomem + (adr)))
@@ -147,24 +145,24 @@ static void demux_tasklet(unsigned long data)
147 } else { 145 } else {
148 if (chan->HWState == HWSTATE_RUN) { 146 if (chan->HWState == HWSTATE_RUN) {
149 u32 Flags = 0; 147 u32 Flags = 0;
148 IBufferExchange *exch1 = chan->pBufferExchange;
149 IBufferExchange *exch2 = chan->pBufferExchange2;
150 if (Cur->ngeneBuffer.SR.Flags & 0x01) 150 if (Cur->ngeneBuffer.SR.Flags & 0x01)
151 Flags |= BEF_EVEN_FIELD; 151 Flags |= BEF_EVEN_FIELD;
152 if (Cur->ngeneBuffer.SR.Flags & 0x20) 152 if (Cur->ngeneBuffer.SR.Flags & 0x20)
153 Flags |= BEF_OVERFLOW; 153 Flags |= BEF_OVERFLOW;
154 if (chan->pBufferExchange) 154 spin_unlock_irq(&chan->state_lock);
155 chan->pBufferExchange(chan, 155 if (exch1)
156 Cur->Buffer1, 156 exch1(chan, Cur->Buffer1,
157 chan-> 157 chan->Capture1Length,
158 Capture1Length, 158 Cur->ngeneBuffer.SR.Clock,
159 Cur->ngeneBuffer. 159 Flags);
160 SR.Clock, Flags); 160 if (exch2)
161 if (chan->pBufferExchange2) 161 exch2(chan, Cur->Buffer2,
162 chan->pBufferExchange2(chan, 162 chan->Capture2Length,
163 Cur->Buffer2, 163 Cur->ngeneBuffer.SR.Clock,
164 chan-> 164 Flags);
165 Capture2Length, 165 spin_lock_irq(&chan->state_lock);
166 Cur->ngeneBuffer.
167 SR.Clock, Flags);
168 } else if (chan->HWState != HWSTATE_STOP) 166 } else if (chan->HWState != HWSTATE_STOP)
169 chan->HWState = HWSTATE_RUN; 167 chan->HWState = HWSTATE_RUN;
170 } 168 }
@@ -572,11 +570,7 @@ static int ngene_command_stream_control(struct ngene *dev, u8 stream,
572 u16 BsSPI = ((stream & 1) ? 0x9800 : 0x9700); 570 u16 BsSPI = ((stream & 1) ? 0x9800 : 0x9700);
573 u16 BsSDO = 0x9B00; 571 u16 BsSDO = 0x9B00;
574 572
575 /* down(&dev->stream_mutex); */ 573 down(&dev->stream_mutex);
576 while (down_trylock(&dev->stream_mutex)) {
577 printk(KERN_INFO DEVICE_NAME ": SC locked\n");
578 msleep(1);
579 }
580 memset(&com, 0, sizeof(com)); 574 memset(&com, 0, sizeof(com));
581 com.cmd.hdr.Opcode = CMD_CONTROL; 575 com.cmd.hdr.Opcode = CMD_CONTROL;
582 com.cmd.hdr.Length = sizeof(struct FW_STREAM_CONTROL) - 2; 576 com.cmd.hdr.Length = sizeof(struct FW_STREAM_CONTROL) - 2;
@@ -1252,14 +1246,17 @@ static int ngene_load_firm(struct ngene *dev)
1252 version = 15; 1246 version = 15;
1253 size = 23466; 1247 size = 23466;
1254 fw_name = "ngene_15.fw"; 1248 fw_name = "ngene_15.fw";
1249 dev->cmd_timeout_workaround = true;
1255 break; 1250 break;
1256 case 16: 1251 case 16:
1257 size = 23498; 1252 size = 23498;
1258 fw_name = "ngene_16.fw"; 1253 fw_name = "ngene_16.fw";
1254 dev->cmd_timeout_workaround = true;
1259 break; 1255 break;
1260 case 17: 1256 case 17:
1261 size = 24446; 1257 size = 24446;
1262 fw_name = "ngene_17.fw"; 1258 fw_name = "ngene_17.fw";
1259 dev->cmd_timeout_workaround = true;
1263 break; 1260 break;
1264 } 1261 }
1265 1262
@@ -1299,11 +1296,16 @@ static void ngene_stop(struct ngene *dev)
1299 ngwritel(0, NGENE_EVENT); 1296 ngwritel(0, NGENE_EVENT);
1300 ngwritel(0, NGENE_EVENT_HI); 1297 ngwritel(0, NGENE_EVENT_HI);
1301 free_irq(dev->pci_dev->irq, dev); 1298 free_irq(dev->pci_dev->irq, dev);
1299#ifdef CONFIG_PCI_MSI
1300 if (dev->msi_enabled)
1301 pci_disable_msi(dev->pci_dev);
1302#endif
1302} 1303}
1303 1304
1304static int ngene_start(struct ngene *dev) 1305static int ngene_start(struct ngene *dev)
1305{ 1306{
1306 int stat; 1307 int stat;
1308 unsigned long flags;
1307 int i; 1309 int i;
1308 1310
1309 pci_set_master(dev->pci_dev); 1311 pci_set_master(dev->pci_dev);
@@ -1333,6 +1335,28 @@ static int ngene_start(struct ngene *dev)
1333 if (stat < 0) 1335 if (stat < 0)
1334 goto fail; 1336 goto fail;
1335 1337
1338#ifdef CONFIG_PCI_MSI
1339 /* enable MSI if kernel and card support it */
1340 if (pci_msi_enabled() && dev->card_info->msi_supported) {
1341 ngwritel(0, NGENE_INT_ENABLE);
1342 free_irq(dev->pci_dev->irq, dev);
1343 stat = pci_enable_msi(dev->pci_dev);
1344 if (stat) {
1345 printk(KERN_INFO DEVICE_NAME
1346 ": MSI not available\n");
1347 flags = IRQF_SHARED;
1348 } else {
1349 flags = 0;
1350 dev->msi_enabled = true;
1351 }
1352 stat = request_irq(dev->pci_dev->irq, irq_handler,
1353 flags, "nGene", dev);
1354 if (stat < 0)
1355 goto fail2;
1356 ngwritel(1, NGENE_INT_ENABLE);
1357 }
1358#endif
1359
1336 stat = ngene_i2c_init(dev, 0); 1360 stat = ngene_i2c_init(dev, 0);
1337 if (stat < 0) 1361 if (stat < 0)
1338 goto fail; 1362 goto fail;
@@ -1358,10 +1382,18 @@ static int ngene_start(struct ngene *dev)
1358 bconf = BUFFER_CONFIG_3333; 1382 bconf = BUFFER_CONFIG_3333;
1359 stat = ngene_command_config_buf(dev, bconf); 1383 stat = ngene_command_config_buf(dev, bconf);
1360 } 1384 }
1361 return stat; 1385 if (!stat)
1386 return stat;
1387
1388 /* otherwise error: fall through */
1362fail: 1389fail:
1363 ngwritel(0, NGENE_INT_ENABLE); 1390 ngwritel(0, NGENE_INT_ENABLE);
1364 free_irq(dev->pci_dev->irq, dev); 1391 free_irq(dev->pci_dev->irq, dev);
1392#ifdef CONFIG_PCI_MSI
1393fail2:
1394 if (dev->msi_enabled)
1395 pci_disable_msi(dev->pci_dev);
1396#endif
1365 return stat; 1397 return stat;
1366} 1398}
1367 1399
@@ -1379,10 +1411,8 @@ static void release_channel(struct ngene_channel *chan)
1379 struct ngene_info *ni = dev->card_info; 1411 struct ngene_info *ni = dev->card_info;
1380 int io = ni->io_type[chan->number]; 1412 int io = ni->io_type[chan->number];
1381 1413
1382#ifdef COMMAND_TIMEOUT_WORKAROUND 1414 if (chan->dev->cmd_timeout_workaround && chan->running)
1383 if (chan->running)
1384 set_transfer(chan, 0); 1415 set_transfer(chan, 0);
1385#endif
1386 1416
1387 tasklet_kill(&chan->demux_tasklet); 1417 tasklet_kill(&chan->demux_tasklet);
1388 1418
diff --git a/drivers/media/dvb/ngene/ngene-dvb.c b/drivers/media/dvb/ngene/ngene-dvb.c
index 96013eb353cd..48f980b21d66 100644
--- a/drivers/media/dvb/ngene/ngene-dvb.c
+++ b/drivers/media/dvb/ngene/ngene-dvb.c
@@ -37,15 +37,12 @@
37#include <linux/pci.h> 37#include <linux/pci.h>
38#include <linux/smp_lock.h> 38#include <linux/smp_lock.h>
39#include <linux/timer.h> 39#include <linux/timer.h>
40#include <linux/version.h>
41#include <linux/byteorder/generic.h> 40#include <linux/byteorder/generic.h>
42#include <linux/firmware.h> 41#include <linux/firmware.h>
43#include <linux/vmalloc.h> 42#include <linux/vmalloc.h>
44 43
45#include "ngene.h" 44#include "ngene.h"
46 45
47#define COMMAND_TIMEOUT_WORKAROUND
48
49 46
50/****************************************************************************/ 47/****************************************************************************/
51/* COMMAND API interface ****************************************************/ 48/* COMMAND API interface ****************************************************/
@@ -69,9 +66,7 @@ void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags)
69 struct ngene_channel *chan = priv; 66 struct ngene_channel *chan = priv;
70 67
71 68
72#ifdef COMMAND_TIMEOUT_WORKAROUND
73 if (chan->users > 0) 69 if (chan->users > 0)
74#endif
75 dvb_dmx_swfilter(&chan->demux, buf, len); 70 dvb_dmx_swfilter(&chan->demux, buf, len);
76 return NULL; 71 return NULL;
77} 72}
@@ -106,11 +101,8 @@ int ngene_start_feed(struct dvb_demux_feed *dvbdmxfeed)
106 struct ngene_channel *chan = dvbdmx->priv; 101 struct ngene_channel *chan = dvbdmx->priv;
107 102
108 if (chan->users == 0) { 103 if (chan->users == 0) {
109#ifdef COMMAND_TIMEOUT_WORKAROUND 104 if (!chan->dev->cmd_timeout_workaround || !chan->running)
110 if (!chan->running)
111#endif
112 set_transfer(chan, 1); 105 set_transfer(chan, 1);
113 /* msleep(10); */
114 } 106 }
115 107
116 return ++chan->users; 108 return ++chan->users;
@@ -124,9 +116,8 @@ int ngene_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
124 if (--chan->users) 116 if (--chan->users)
125 return chan->users; 117 return chan->users;
126 118
127#ifndef COMMAND_TIMEOUT_WORKAROUND 119 if (!chan->dev->cmd_timeout_workaround)
128 set_transfer(chan, 0); 120 set_transfer(chan, 0);
129#endif
130 121
131 return 0; 122 return 0;
132} 123}
diff --git a/drivers/media/dvb/ngene/ngene-i2c.c b/drivers/media/dvb/ngene/ngene-i2c.c
index 2ef54ca6badd..477fe0aade86 100644
--- a/drivers/media/dvb/ngene/ngene-i2c.c
+++ b/drivers/media/dvb/ngene/ngene-i2c.c
@@ -39,7 +39,6 @@
39#include <linux/pci_ids.h> 39#include <linux/pci_ids.h>
40#include <linux/smp_lock.h> 40#include <linux/smp_lock.h>
41#include <linux/timer.h> 41#include <linux/timer.h>
42#include <linux/version.h>
43#include <linux/byteorder/generic.h> 42#include <linux/byteorder/generic.h>
44#include <linux/firmware.h> 43#include <linux/firmware.h>
45#include <linux/vmalloc.h> 44#include <linux/vmalloc.h>
diff --git a/drivers/media/dvb/ngene/ngene.h b/drivers/media/dvb/ngene/ngene.h
index 676fcbb79026..8fb4200f83f8 100644
--- a/drivers/media/dvb/ngene/ngene.h
+++ b/drivers/media/dvb/ngene/ngene.h
@@ -725,6 +725,8 @@ struct ngene {
725 u32 device_version; 725 u32 device_version;
726 u32 fw_interface_version; 726 u32 fw_interface_version;
727 u32 icounts; 727 u32 icounts;
728 bool msi_enabled;
729 bool cmd_timeout_workaround;
728 730
729 u8 *CmdDoneByte; 731 u8 *CmdDoneByte;
730 int BootFirmware; 732 int BootFirmware;
@@ -797,6 +799,7 @@ struct ngene_info {
797#define NGENE_VBOX_V2 7 799#define NGENE_VBOX_V2 7
798 800
799 int fw_version; 801 int fw_version;
802 bool msi_supported;
800 char *name; 803 char *name;
801 804
802 int io_type[MAX_STREAM]; 805 int io_type[MAX_STREAM];
diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig
index d8d4214fd65f..32a7ec65ec42 100644
--- a/drivers/media/dvb/ttpci/Kconfig
+++ b/drivers/media/dvb/ttpci/Kconfig
@@ -68,13 +68,14 @@ config DVB_BUDGET
68 select DVB_VES1820 if !DVB_FE_CUSTOMISE 68 select DVB_VES1820 if !DVB_FE_CUSTOMISE
69 select DVB_L64781 if !DVB_FE_CUSTOMISE 69 select DVB_L64781 if !DVB_FE_CUSTOMISE
70 select DVB_TDA8083 if !DVB_FE_CUSTOMISE 70 select DVB_TDA8083 if !DVB_FE_CUSTOMISE
71 select DVB_TDA10021 if !DVB_FE_CUSTOMISE
72 select DVB_TDA10023 if !DVB_FE_CUSTOMISE
73 select DVB_S5H1420 if !DVB_FE_CUSTOMISE 71 select DVB_S5H1420 if !DVB_FE_CUSTOMISE
74 select DVB_TDA10086 if !DVB_FE_CUSTOMISE 72 select DVB_TDA10086 if !DVB_FE_CUSTOMISE
75 select DVB_TDA826X if !DVB_FE_CUSTOMISE 73 select DVB_TDA826X if !DVB_FE_CUSTOMISE
76 select DVB_LNBP21 if !DVB_FE_CUSTOMISE 74 select DVB_LNBP21 if !DVB_FE_CUSTOMISE
77 select DVB_TDA1004X if !DVB_FE_CUSTOMISE 75 select DVB_TDA1004X if !DVB_FE_CUSTOMISE
76 select DVB_ISL6423 if !DVB_FE_CUSTOMISE
77 select DVB_STV090x if !DVB_FE_CUSTOMISE
78 select DVB_STV6110x if !DVB_FE_CUSTOMISE
78 help 79 help
79 Support for simple SAA7146 based DVB cards (so called Budget- 80 Support for simple SAA7146 based DVB cards (so called Budget-
80 or Nova-PCI cards) without onboard MPEG2 decoder, and without 81 or Nova-PCI cards) without onboard MPEG2 decoder, and without
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
index 461714396331..13ac9e3ab121 100644
--- a/drivers/media/dvb/ttpci/budget-ci.c
+++ b/drivers/media/dvb/ttpci/budget-ci.c
@@ -215,6 +215,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
215 break; 215 break;
216 case 0x1010: 216 case 0x1010:
217 case 0x1017: 217 case 0x1017:
218 case 0x1019:
218 case 0x101a: 219 case 0x101a:
219 /* for the Technotrend 1500 bundled remote */ 220 /* for the Technotrend 1500 bundled remote */
220 ir_codes = RC_MAP_TT_1500; 221 ir_codes = RC_MAP_TT_1500;
diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c
index a5844d08d8b7..67a4ec8768a6 100644
--- a/drivers/media/radio/si470x/radio-si470x-i2c.c
+++ b/drivers/media/radio/si470x/radio-si470x-i2c.c
@@ -482,7 +482,6 @@ static __devexit int si470x_i2c_remove(struct i2c_client *client)
482 cancel_work_sync(&radio->radio_work); 482 cancel_work_sync(&radio->radio_work);
483 video_unregister_device(radio->videodev); 483 video_unregister_device(radio->videodev);
484 kfree(radio); 484 kfree(radio);
485 i2c_set_clientdata(client, NULL);
486 485
487 return 0; 486 return 0;
488} 487}
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index ad9e6f9c22e9..bdbc9d305419 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -646,7 +646,7 @@ config VIDEO_PMS
646 646
647config VIDEO_BWQCAM 647config VIDEO_BWQCAM
648 tristate "Quickcam BW Video For Linux" 648 tristate "Quickcam BW Video For Linux"
649 depends on PARPORT && VIDEO_V4L1 649 depends on PARPORT && VIDEO_V4L2
650 help 650 help
651 Say Y have if you the black and white version of the QuickCam 651 Say Y have if you the black and white version of the QuickCam
652 camera. See the next option for the color version. 652 camera. See the next option for the color version.
@@ -656,7 +656,7 @@ config VIDEO_BWQCAM
656 656
657config VIDEO_CQCAM 657config VIDEO_CQCAM
658 tristate "QuickCam Colour Video For Linux (EXPERIMENTAL)" 658 tristate "QuickCam Colour Video For Linux (EXPERIMENTAL)"
659 depends on EXPERIMENTAL && PARPORT && VIDEO_V4L1 659 depends on EXPERIMENTAL && PARPORT && VIDEO_V4L2
660 help 660 help
661 This is the video4linux driver for the colour version of the 661 This is the video4linux driver for the colour version of the
662 Connectix QuickCam. If you have one of these cameras, say Y here, 662 Connectix QuickCam. If you have one of these cameras, say Y here,
diff --git a/drivers/media/video/ak881x.c b/drivers/media/video/ak881x.c
index 35390d4717b9..1573392f74bd 100644
--- a/drivers/media/video/ak881x.c
+++ b/drivers/media/video/ak881x.c
@@ -11,6 +11,7 @@
11#include <linux/i2c.h> 11#include <linux/i2c.h>
12#include <linux/init.h> 12#include <linux/init.h>
13#include <linux/platform_device.h> 13#include <linux/platform_device.h>
14#include <linux/slab.h>
14#include <linux/videodev2.h> 15#include <linux/videodev2.h>
15 16
16#include <media/ak881x.h> 17#include <media/ak881x.h>
@@ -141,7 +142,7 @@ static int ak881x_s_mbus_fmt(struct v4l2_subdev *sd,
141 return ak881x_try_g_mbus_fmt(sd, mf); 142 return ak881x_try_g_mbus_fmt(sd, mf);
142} 143}
143 144
144static int ak881x_enum_mbus_fmt(struct v4l2_subdev *sd, int index, 145static int ak881x_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
145 enum v4l2_mbus_pixelcode *code) 146 enum v4l2_mbus_pixelcode *code)
146{ 147{
147 if (index) 148 if (index)
diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c
index 3c9e754d73a0..935e0c9a9674 100644
--- a/drivers/media/video/bw-qcam.c
+++ b/drivers/media/video/bw-qcam.c
@@ -66,19 +66,58 @@ OTHER DEALINGS IN THE SOFTWARE.
66#include <linux/delay.h> 66#include <linux/delay.h>
67#include <linux/errno.h> 67#include <linux/errno.h>
68#include <linux/fs.h> 68#include <linux/fs.h>
69#include <linux/init.h>
70#include <linux/kernel.h> 69#include <linux/kernel.h>
71#include <linux/slab.h> 70#include <linux/slab.h>
72#include <linux/mm.h> 71#include <linux/mm.h>
73#include <linux/parport.h> 72#include <linux/parport.h>
74#include <linux/sched.h> 73#include <linux/sched.h>
75#include <linux/videodev.h> 74#include <linux/version.h>
76#include <media/v4l2-common.h> 75#include <linux/videodev2.h>
77#include <media/v4l2-ioctl.h>
78#include <linux/mutex.h> 76#include <linux/mutex.h>
79#include <asm/uaccess.h> 77#include <asm/uaccess.h>
80 78#include <media/v4l2-common.h>
81#include "bw-qcam.h" 79#include <media/v4l2-ioctl.h>
80#include <media/v4l2-device.h>
81
82/* One from column A... */
83#define QC_NOTSET 0
84#define QC_UNIDIR 1
85#define QC_BIDIR 2
86#define QC_SERIAL 3
87
88/* ... and one from column B */
89#define QC_ANY 0x00
90#define QC_FORCE_UNIDIR 0x10
91#define QC_FORCE_BIDIR 0x20
92#define QC_FORCE_SERIAL 0x30
93/* in the port_mode member */
94
95#define QC_MODE_MASK 0x07
96#define QC_FORCE_MASK 0x70
97
98#define MAX_HEIGHT 243
99#define MAX_WIDTH 336
100
101/* Bit fields for status flags */
102#define QC_PARAM_CHANGE 0x01 /* Camera status change has occurred */
103
104struct qcam {
105 struct v4l2_device v4l2_dev;
106 struct video_device vdev;
107 struct pardevice *pdev;
108 struct parport *pport;
109 struct mutex lock;
110 int width, height;
111 int bpp;
112 int mode;
113 int contrast, brightness, whitebal;
114 int port_mode;
115 int transfer_scale;
116 int top, left;
117 int status;
118 unsigned int saved_bits;
119 unsigned long in_use;
120};
82 121
83static unsigned int maxpoll = 250; /* Maximum busy-loop count for qcam I/O */ 122static unsigned int maxpoll = 250; /* Maximum busy-loop count for qcam I/O */
84static unsigned int yieldlines = 4; /* Yield after this many during capture */ 123static unsigned int yieldlines = 4; /* Yield after this many during capture */
@@ -93,22 +132,26 @@ module_param(video_nr, int, 0);
93 * immediately attempt to initialize qcam */ 132 * immediately attempt to initialize qcam */
94module_param(force_init, int, 0); 133module_param(force_init, int, 0);
95 134
96static inline int read_lpstatus(struct qcam_device *q) 135#define MAX_CAMS 4
136static struct qcam *qcams[MAX_CAMS];
137static unsigned int num_cams;
138
139static inline int read_lpstatus(struct qcam *q)
97{ 140{
98 return parport_read_status(q->pport); 141 return parport_read_status(q->pport);
99} 142}
100 143
101static inline int read_lpdata(struct qcam_device *q) 144static inline int read_lpdata(struct qcam *q)
102{ 145{
103 return parport_read_data(q->pport); 146 return parport_read_data(q->pport);
104} 147}
105 148
106static inline void write_lpdata(struct qcam_device *q, int d) 149static inline void write_lpdata(struct qcam *q, int d)
107{ 150{
108 parport_write_data(q->pport, d); 151 parport_write_data(q->pport, d);
109} 152}
110 153
111static inline void write_lpcontrol(struct qcam_device *q, int d) 154static void write_lpcontrol(struct qcam *q, int d)
112{ 155{
113 if (d & 0x20) { 156 if (d & 0x20) {
114 /* Set bidirectional mode to reverse (data in) */ 157 /* Set bidirectional mode to reverse (data in) */
@@ -124,126 +167,11 @@ static inline void write_lpcontrol(struct qcam_device *q, int d)
124 parport_write_control(q->pport, d); 167 parport_write_control(q->pport, d);
125} 168}
126 169
127static int qc_waithand(struct qcam_device *q, int val);
128static int qc_command(struct qcam_device *q, int command);
129static int qc_readparam(struct qcam_device *q);
130static int qc_setscanmode(struct qcam_device *q);
131static int qc_readbytes(struct qcam_device *q, char buffer[]);
132
133static struct video_device qcam_template;
134
135static int qc_calibrate(struct qcam_device *q)
136{
137 /*
138 * Bugfix by Hanno Mueller hmueller@kabel.de, Mai 21 96
139 * The white balance is an individiual value for each
140 * quickcam.
141 */
142
143 int value;
144 int count = 0;
145
146 qc_command(q, 27); /* AutoAdjustOffset */
147 qc_command(q, 0); /* Dummy Parameter, ignored by the camera */
148
149 /* GetOffset (33) will read 255 until autocalibration */
150 /* is finished. After that, a value of 1-254 will be */
151 /* returned. */
152
153 do {
154 qc_command(q, 33);
155 value = qc_readparam(q);
156 mdelay(1);
157 schedule();
158 count++;
159 } while (value == 0xff && count < 2048);
160
161 q->whitebal = value;
162 return value;
163}
164
165/* Initialize the QuickCam driver control structure. This is where
166 * defaults are set for people who don't have a config file.*/
167
168static struct qcam_device *qcam_init(struct parport *port)
169{
170 struct qcam_device *q;
171
172 q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL);
173 if (q == NULL)
174 return NULL;
175
176 q->pport = port;
177 q->pdev = parport_register_device(port, "bw-qcam", NULL, NULL,
178 NULL, 0, NULL);
179 if (q->pdev == NULL) {
180 printk(KERN_ERR "bw-qcam: couldn't register for %s.\n",
181 port->name);
182 kfree(q);
183 return NULL;
184 }
185
186 memcpy(&q->vdev, &qcam_template, sizeof(qcam_template));
187
188 mutex_init(&q->lock);
189
190 q->port_mode = (QC_ANY | QC_NOTSET);
191 q->width = 320;
192 q->height = 240;
193 q->bpp = 4;
194 q->transfer_scale = 2;
195 q->contrast = 192;
196 q->brightness = 180;
197 q->whitebal = 105;
198 q->top = 1;
199 q->left = 14;
200 q->mode = -1;
201 q->status = QC_PARAM_CHANGE;
202 return q;
203}
204
205
206/* qc_command is probably a bit of a misnomer -- it's used to send
207 * bytes *to* the camera. Generally, these bytes are either commands
208 * or arguments to commands, so the name fits, but it still bugs me a
209 * bit. See the documentation for a list of commands. */
210
211static int qc_command(struct qcam_device *q, int command)
212{
213 int n1, n2;
214 int cmd;
215
216 write_lpdata(q, command);
217 write_lpcontrol(q, 6);
218
219 n1 = qc_waithand(q, 1);
220
221 write_lpcontrol(q, 0xe);
222 n2 = qc_waithand(q, 0);
223
224 cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4);
225 return cmd;
226}
227
228static int qc_readparam(struct qcam_device *q)
229{
230 int n1, n2;
231 int cmd;
232
233 write_lpcontrol(q, 6);
234 n1 = qc_waithand(q, 1);
235
236 write_lpcontrol(q, 0xe);
237 n2 = qc_waithand(q, 0);
238
239 cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4);
240 return cmd;
241}
242 170
243/* qc_waithand busy-waits for a handshake signal from the QuickCam. 171/* qc_waithand busy-waits for a handshake signal from the QuickCam.
244 * Almost all communication with the camera requires handshaking. */ 172 * Almost all communication with the camera requires handshaking. */
245 173
246static int qc_waithand(struct qcam_device *q, int val) 174static int qc_waithand(struct qcam *q, int val)
247{ 175{
248 int status; 176 int status;
249 int runs = 0; 177 int runs = 0;
@@ -286,7 +214,7 @@ static int qc_waithand(struct qcam_device *q, int val)
286 * (bit 3 of status register). It also returns the last value read, 214 * (bit 3 of status register). It also returns the last value read,
287 * since this data is useful. */ 215 * since this data is useful. */
288 216
289static unsigned int qc_waithand2(struct qcam_device *q, int val) 217static unsigned int qc_waithand2(struct qcam *q, int val)
290{ 218{
291 unsigned int status; 219 unsigned int status;
292 int runs = 0; 220 int runs = 0;
@@ -309,6 +237,43 @@ static unsigned int qc_waithand2(struct qcam_device *q, int val)
309 return status; 237 return status;
310} 238}
311 239
240/* qc_command is probably a bit of a misnomer -- it's used to send
241 * bytes *to* the camera. Generally, these bytes are either commands
242 * or arguments to commands, so the name fits, but it still bugs me a
243 * bit. See the documentation for a list of commands. */
244
245static int qc_command(struct qcam *q, int command)
246{
247 int n1, n2;
248 int cmd;
249
250 write_lpdata(q, command);
251 write_lpcontrol(q, 6);
252
253 n1 = qc_waithand(q, 1);
254
255 write_lpcontrol(q, 0xe);
256 n2 = qc_waithand(q, 0);
257
258 cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4);
259 return cmd;
260}
261
262static int qc_readparam(struct qcam *q)
263{
264 int n1, n2;
265 int cmd;
266
267 write_lpcontrol(q, 6);
268 n1 = qc_waithand(q, 1);
269
270 write_lpcontrol(q, 0xe);
271 n2 = qc_waithand(q, 0);
272
273 cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4);
274 return cmd;
275}
276
312 277
313/* Try to detect a QuickCam. It appears to flash the upper 4 bits of 278/* Try to detect a QuickCam. It appears to flash the upper 4 bits of
314 the status register at 5-10 Hz. This is only used in the autoprobe 279 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)
317 almost completely safe, while their method screws up my printer if 282 almost completely safe, while their method screws up my printer if
318 I plug it in before the camera. */ 283 I plug it in before the camera. */
319 284
320static int qc_detect(struct qcam_device *q) 285static int qc_detect(struct qcam *q)
321{ 286{
322 int reg, lastreg; 287 int reg, lastreg;
323 int count = 0; 288 int count = 0;
@@ -358,41 +323,6 @@ static int qc_detect(struct qcam_device *q)
358 } 323 }
359} 324}
360 325
361
362/* Reset the QuickCam. This uses the same sequence the Windows
363 * QuickPic program uses. Someone with a bi-directional port should
364 * check that bi-directional mode is detected right, and then
365 * implement bi-directional mode in qc_readbyte(). */
366
367static void qc_reset(struct qcam_device *q)
368{
369 switch (q->port_mode & QC_FORCE_MASK) {
370 case QC_FORCE_UNIDIR:
371 q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR;
372 break;
373
374 case QC_FORCE_BIDIR:
375 q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR;
376 break;
377
378 case QC_ANY:
379 write_lpcontrol(q, 0x20);
380 write_lpdata(q, 0x75);
381
382 if (read_lpdata(q) != 0x75)
383 q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR;
384 else
385 q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR;
386 break;
387 }
388
389 write_lpcontrol(q, 0xb);
390 udelay(250);
391 write_lpcontrol(q, 0xe);
392 qc_setscanmode(q); /* in case port_mode changed */
393}
394
395
396/* Decide which scan mode to use. There's no real requirement that 326/* Decide which scan mode to use. There's no real requirement that
397 * the scanmode match the resolution in q->height and q-> width -- the 327 * the scanmode match the resolution in q->height and q-> width -- the
398 * camera takes the picture at the resolution specified in the 328 * camera takes the picture at the resolution specified in the
@@ -402,7 +332,7 @@ static void qc_reset(struct qcam_device *q)
402 * returned. If the scan is smaller, then the rest of the image 332 * returned. If the scan is smaller, then the rest of the image
403 * returned contains garbage. */ 333 * returned contains garbage. */
404 334
405static int qc_setscanmode(struct qcam_device *q) 335static int qc_setscanmode(struct qcam *q)
406{ 336{
407 int old_mode = q->mode; 337 int old_mode = q->mode;
408 338
@@ -442,10 +372,45 @@ static int qc_setscanmode(struct qcam_device *q)
442} 372}
443 373
444 374
375/* Reset the QuickCam. This uses the same sequence the Windows
376 * QuickPic program uses. Someone with a bi-directional port should
377 * check that bi-directional mode is detected right, and then
378 * implement bi-directional mode in qc_readbyte(). */
379
380static void qc_reset(struct qcam *q)
381{
382 switch (q->port_mode & QC_FORCE_MASK) {
383 case QC_FORCE_UNIDIR:
384 q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR;
385 break;
386
387 case QC_FORCE_BIDIR:
388 q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR;
389 break;
390
391 case QC_ANY:
392 write_lpcontrol(q, 0x20);
393 write_lpdata(q, 0x75);
394
395 if (read_lpdata(q) != 0x75)
396 q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR;
397 else
398 q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR;
399 break;
400 }
401
402 write_lpcontrol(q, 0xb);
403 udelay(250);
404 write_lpcontrol(q, 0xe);
405 qc_setscanmode(q); /* in case port_mode changed */
406}
407
408
409
445/* Reset the QuickCam and program for brightness, contrast, 410/* Reset the QuickCam and program for brightness, contrast,
446 * white-balance, and resolution. */ 411 * white-balance, and resolution. */
447 412
448static void qc_set(struct qcam_device *q) 413static void qc_set(struct qcam *q)
449{ 414{
450 int val; 415 int val;
451 int val2; 416 int val2;
@@ -499,7 +464,7 @@ static void qc_set(struct qcam_device *q)
499 the supplied buffer. It returns the number of bytes read, 464 the supplied buffer. It returns the number of bytes read,
500 or -1 on error. */ 465 or -1 on error. */
501 466
502static inline int qc_readbytes(struct qcam_device *q, char buffer[]) 467static inline int qc_readbytes(struct qcam *q, char buffer[])
503{ 468{
504 int ret = 1; 469 int ret = 1;
505 unsigned int hi, lo; 470 unsigned int hi, lo;
@@ -590,7 +555,7 @@ static inline int qc_readbytes(struct qcam_device *q, char buffer[])
590 * n=2^(bit depth)-1. Ask me for more details if you don't understand 555 * n=2^(bit depth)-1. Ask me for more details if you don't understand
591 * this. */ 556 * this. */
592 557
593static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long len) 558static long qc_capture(struct qcam *q, char __user *buf, unsigned long len)
594{ 559{
595 int i, j, k, yield; 560 int i, j, k, yield;
596 int bytes; 561 int bytes;
@@ -674,171 +639,206 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le
674 * Video4linux interfacing 639 * Video4linux interfacing
675 */ 640 */
676 641
677static long qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg) 642static int qcam_querycap(struct file *file, void *priv,
643 struct v4l2_capability *vcap)
678{ 644{
679 struct video_device *dev = video_devdata(file); 645 struct qcam *qcam = video_drvdata(file);
680 struct qcam_device *qcam = (struct qcam_device *)dev;
681
682 switch (cmd) {
683 case VIDIOCGCAP:
684 {
685 struct video_capability *b = arg;
686 strcpy(b->name, "Quickcam");
687 b->type = VID_TYPE_CAPTURE|VID_TYPE_SCALES|VID_TYPE_MONOCHROME;
688 b->channels = 1;
689 b->audios = 0;
690 b->maxwidth = 320;
691 b->maxheight = 240;
692 b->minwidth = 80;
693 b->minheight = 60;
694 return 0;
695 }
696 case VIDIOCGCHAN:
697 {
698 struct video_channel *v = arg;
699 if (v->channel != 0)
700 return -EINVAL;
701 v->flags = 0;
702 v->tuners = 0;
703 /* Good question.. its composite or SVHS so.. */
704 v->type = VIDEO_TYPE_CAMERA;
705 strcpy(v->name, "Camera");
706 return 0;
707 }
708 case VIDIOCSCHAN:
709 {
710 struct video_channel *v = arg;
711 if (v->channel != 0)
712 return -EINVAL;
713 return 0;
714 }
715 case VIDIOCGTUNER:
716 {
717 struct video_tuner *v = arg;
718 if (v->tuner)
719 return -EINVAL;
720 strcpy(v->name, "Format");
721 v->rangelow = 0;
722 v->rangehigh = 0;
723 v->flags = 0;
724 v->mode = VIDEO_MODE_AUTO;
725 return 0;
726 }
727 case VIDIOCSTUNER:
728 {
729 struct video_tuner *v = arg;
730 if (v->tuner)
731 return -EINVAL;
732 if (v->mode != VIDEO_MODE_AUTO)
733 return -EINVAL;
734 return 0;
735 }
736 case VIDIOCGPICT:
737 {
738 struct video_picture *p = arg;
739 p->colour = 0x8000;
740 p->hue = 0x8000;
741 p->brightness = qcam->brightness << 8;
742 p->contrast = qcam->contrast << 8;
743 p->whiteness = qcam->whitebal << 8;
744 p->depth = qcam->bpp;
745 p->palette = VIDEO_PALETTE_GREY;
746 return 0;
747 }
748 case VIDIOCSPICT:
749 {
750 struct video_picture *p = arg;
751 if (p->palette != VIDEO_PALETTE_GREY)
752 return -EINVAL;
753 if (p->depth != 4 && p->depth != 6)
754 return -EINVAL;
755
756 /*
757 * Now load the camera.
758 */
759
760 qcam->brightness = p->brightness >> 8;
761 qcam->contrast = p->contrast >> 8;
762 qcam->whitebal = p->whiteness >> 8;
763 qcam->bpp = p->depth;
764
765 mutex_lock(&qcam->lock);
766 qc_setscanmode(qcam);
767 mutex_unlock(&qcam->lock);
768 qcam->status |= QC_PARAM_CHANGE;
769 646
770 return 0; 647 strlcpy(vcap->driver, qcam->v4l2_dev.name, sizeof(vcap->driver));
771 } 648 strlcpy(vcap->card, "B&W Quickcam", sizeof(vcap->card));
772 case VIDIOCSWIN: 649 strlcpy(vcap->bus_info, "parport", sizeof(vcap->bus_info));
773 { 650 vcap->version = KERNEL_VERSION(0, 0, 2);
774 struct video_window *vw = arg; 651 vcap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
775 if (vw->flags) 652 return 0;
776 return -EINVAL; 653}
777 if (vw->clipcount)
778 return -EINVAL;
779 if (vw->height < 60 || vw->height > 240)
780 return -EINVAL;
781 if (vw->width < 80 || vw->width > 320)
782 return -EINVAL;
783
784 qcam->width = 320;
785 qcam->height = 240;
786 qcam->transfer_scale = 4;
787
788 if (vw->width >= 160 && vw->height >= 120)
789 qcam->transfer_scale = 2;
790 if (vw->width >= 320 && vw->height >= 240) {
791 qcam->width = 320;
792 qcam->height = 240;
793 qcam->transfer_scale = 1;
794 }
795 mutex_lock(&qcam->lock);
796 qc_setscanmode(qcam);
797 mutex_unlock(&qcam->lock);
798 654
799 /* We must update the camera before we grab. We could 655static int qcam_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
800 just have changed the grab size */ 656{
801 qcam->status |= QC_PARAM_CHANGE; 657 if (vin->index > 0)
658 return -EINVAL;
659 strlcpy(vin->name, "Camera", sizeof(vin->name));
660 vin->type = V4L2_INPUT_TYPE_CAMERA;
661 vin->audioset = 0;
662 vin->tuner = 0;
663 vin->std = 0;
664 vin->status = 0;
665 return 0;
666}
802 667
803 /* Ok we figured out what to use from our wide choice */ 668static int qcam_g_input(struct file *file, void *fh, unsigned int *inp)
804 return 0; 669{
805 } 670 *inp = 0;
806 case VIDIOCGWIN: 671 return 0;
807 { 672}
808 struct video_window *vw = arg;
809 673
810 memset(vw, 0, sizeof(*vw)); 674static int qcam_s_input(struct file *file, void *fh, unsigned int inp)
811 vw->width = qcam->width / qcam->transfer_scale; 675{
812 vw->height = qcam->height / qcam->transfer_scale; 676 return (inp > 0) ? -EINVAL : 0;
813 return 0; 677}
814 } 678
815 case VIDIOCKEY: 679static int qcam_queryctrl(struct file *file, void *priv,
816 return 0; 680 struct v4l2_queryctrl *qc)
817 case VIDIOCCAPTURE: 681{
818 case VIDIOCGFBUF: 682 switch (qc->id) {
819 case VIDIOCSFBUF: 683 case V4L2_CID_BRIGHTNESS:
820 case VIDIOCGFREQ: 684 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 180);
821 case VIDIOCSFREQ: 685 case V4L2_CID_CONTRAST:
822 case VIDIOCGAUDIO: 686 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 192);
823 case VIDIOCSAUDIO: 687 case V4L2_CID_GAMMA:
824 return -EINVAL; 688 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 105);
689 }
690 return -EINVAL;
691}
692
693static int qcam_g_ctrl(struct file *file, void *priv,
694 struct v4l2_control *ctrl)
695{
696 struct qcam *qcam = video_drvdata(file);
697 int ret = 0;
698
699 switch (ctrl->id) {
700 case V4L2_CID_BRIGHTNESS:
701 ctrl->value = qcam->brightness;
702 break;
703 case V4L2_CID_CONTRAST:
704 ctrl->value = qcam->contrast;
705 break;
706 case V4L2_CID_GAMMA:
707 ctrl->value = qcam->whitebal;
708 break;
825 default: 709 default:
826 return -ENOIOCTLCMD; 710 ret = -EINVAL;
711 break;
827 } 712 }
713 return ret;
714}
715
716static int qcam_s_ctrl(struct file *file, void *priv,
717 struct v4l2_control *ctrl)
718{
719 struct qcam *qcam = video_drvdata(file);
720 int ret = 0;
721
722 mutex_lock(&qcam->lock);
723 switch (ctrl->id) {
724 case V4L2_CID_BRIGHTNESS:
725 qcam->brightness = ctrl->value;
726 break;
727 case V4L2_CID_CONTRAST:
728 qcam->contrast = ctrl->value;
729 break;
730 case V4L2_CID_GAMMA:
731 qcam->whitebal = ctrl->value;
732 break;
733 default:
734 ret = -EINVAL;
735 break;
736 }
737 if (ret == 0) {
738 qc_setscanmode(qcam);
739 qcam->status |= QC_PARAM_CHANGE;
740 }
741 mutex_unlock(&qcam->lock);
742 return ret;
743}
744
745static int qcam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
746{
747 struct qcam *qcam = video_drvdata(file);
748 struct v4l2_pix_format *pix = &fmt->fmt.pix;
749
750 pix->width = qcam->width / qcam->transfer_scale;
751 pix->height = qcam->height / qcam->transfer_scale;
752 pix->pixelformat = (qcam->bpp == 4) ? V4L2_PIX_FMT_Y4 : V4L2_PIX_FMT_Y6;
753 pix->field = V4L2_FIELD_NONE;
754 pix->bytesperline = qcam->width;
755 pix->sizeimage = qcam->width * qcam->height;
756 /* Just a guess */
757 pix->colorspace = V4L2_COLORSPACE_SRGB;
758 return 0;
759}
760
761static int qcam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
762{
763 struct v4l2_pix_format *pix = &fmt->fmt.pix;
764
765 if (pix->height <= 60 || pix->width <= 80) {
766 pix->height = 60;
767 pix->width = 80;
768 } else if (pix->height <= 120 || pix->width <= 160) {
769 pix->height = 120;
770 pix->width = 160;
771 } else {
772 pix->height = 240;
773 pix->width = 320;
774 }
775 if (pix->pixelformat != V4L2_PIX_FMT_Y4 &&
776 pix->pixelformat != V4L2_PIX_FMT_Y6)
777 pix->pixelformat = V4L2_PIX_FMT_Y4;
778 pix->field = V4L2_FIELD_NONE;
779 pix->bytesperline = pix->width;
780 pix->sizeimage = pix->width * pix->height;
781 /* Just a guess */
782 pix->colorspace = V4L2_COLORSPACE_SRGB;
783 return 0;
784}
785
786static int qcam_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
787{
788 struct qcam *qcam = video_drvdata(file);
789 struct v4l2_pix_format *pix = &fmt->fmt.pix;
790 int ret = qcam_try_fmt_vid_cap(file, fh, fmt);
791
792 if (ret)
793 return ret;
794 qcam->width = 320;
795 qcam->height = 240;
796 if (pix->height == 60)
797 qcam->transfer_scale = 4;
798 else if (pix->height == 120)
799 qcam->transfer_scale = 2;
800 else
801 qcam->transfer_scale = 1;
802 if (pix->pixelformat == V4L2_PIX_FMT_Y6)
803 qcam->bpp = 6;
804 else
805 qcam->bpp = 4;
806
807 mutex_lock(&qcam->lock);
808 qc_setscanmode(qcam);
809 /* We must update the camera before we grab. We could
810 just have changed the grab size */
811 qcam->status |= QC_PARAM_CHANGE;
812 mutex_unlock(&qcam->lock);
828 return 0; 813 return 0;
829} 814}
830 815
831static long qcam_ioctl(struct file *file, 816static int qcam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
832 unsigned int cmd, unsigned long arg)
833{ 817{
834 return video_usercopy(file, cmd, arg, qcam_do_ioctl); 818 static struct v4l2_fmtdesc formats[] = {
819 { 0, 0, 0,
820 "4-Bit Monochrome", V4L2_PIX_FMT_Y4,
821 { 0, 0, 0, 0 }
822 },
823 { 0, 0, 0,
824 "6-Bit Monochrome", V4L2_PIX_FMT_Y6,
825 { 0, 0, 0, 0 }
826 },
827 };
828 enum v4l2_buf_type type = fmt->type;
829
830 if (fmt->index > 1)
831 return -EINVAL;
832
833 *fmt = formats[fmt->index];
834 fmt->type = type;
835 return 0;
835} 836}
836 837
837static ssize_t qcam_read(struct file *file, char __user *buf, 838static ssize_t qcam_read(struct file *file, char __user *buf,
838 size_t count, loff_t *ppos) 839 size_t count, loff_t *ppos)
839{ 840{
840 struct video_device *v = video_devdata(file); 841 struct qcam *qcam = video_drvdata(file);
841 struct qcam_device *qcam = (struct qcam_device *)v;
842 int len; 842 int len;
843 parport_claim_or_block(qcam->pdev); 843 parport_claim_or_block(qcam->pdev);
844 844
@@ -858,43 +858,112 @@ static ssize_t qcam_read(struct file *file, char __user *buf,
858 return len; 858 return len;
859} 859}
860 860
861static int qcam_exclusive_open(struct file *file) 861static const struct v4l2_file_operations qcam_fops = {
862 .owner = THIS_MODULE,
863 .ioctl = video_ioctl2,
864 .read = qcam_read,
865};
866
867static const struct v4l2_ioctl_ops qcam_ioctl_ops = {
868 .vidioc_querycap = qcam_querycap,
869 .vidioc_g_input = qcam_g_input,
870 .vidioc_s_input = qcam_s_input,
871 .vidioc_enum_input = qcam_enum_input,
872 .vidioc_queryctrl = qcam_queryctrl,
873 .vidioc_g_ctrl = qcam_g_ctrl,
874 .vidioc_s_ctrl = qcam_s_ctrl,
875 .vidioc_enum_fmt_vid_cap = qcam_enum_fmt_vid_cap,
876 .vidioc_g_fmt_vid_cap = qcam_g_fmt_vid_cap,
877 .vidioc_s_fmt_vid_cap = qcam_s_fmt_vid_cap,
878 .vidioc_try_fmt_vid_cap = qcam_try_fmt_vid_cap,
879};
880
881/* Initialize the QuickCam driver control structure. This is where
882 * defaults are set for people who don't have a config file.*/
883
884static struct qcam *qcam_init(struct parport *port)
862{ 885{
863 struct video_device *dev = video_devdata(file); 886 struct qcam *qcam;
864 struct qcam_device *qcam = (struct qcam_device *)dev; 887 struct v4l2_device *v4l2_dev;
888
889 qcam = kzalloc(sizeof(struct qcam), GFP_KERNEL);
890 if (qcam == NULL)
891 return NULL;
892
893 v4l2_dev = &qcam->v4l2_dev;
894 strlcpy(v4l2_dev->name, "bw-qcam", sizeof(v4l2_dev->name));
865 895
866 return test_and_set_bit(0, &qcam->in_use) ? -EBUSY : 0; 896 if (v4l2_device_register(NULL, v4l2_dev) < 0) {
897 v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
898 return NULL;
899 }
900
901 qcam->pport = port;
902 qcam->pdev = parport_register_device(port, "bw-qcam", NULL, NULL,
903 NULL, 0, NULL);
904 if (qcam->pdev == NULL) {
905 v4l2_err(v4l2_dev, "couldn't register for %s.\n", port->name);
906 kfree(qcam);
907 return NULL;
908 }
909
910 strlcpy(qcam->vdev.name, "Connectix QuickCam", sizeof(qcam->vdev.name));
911 qcam->vdev.v4l2_dev = v4l2_dev;
912 qcam->vdev.fops = &qcam_fops;
913 qcam->vdev.ioctl_ops = &qcam_ioctl_ops;
914 qcam->vdev.release = video_device_release_empty;
915 video_set_drvdata(&qcam->vdev, qcam);
916
917 mutex_init(&qcam->lock);
918
919 qcam->port_mode = (QC_ANY | QC_NOTSET);
920 qcam->width = 320;
921 qcam->height = 240;
922 qcam->bpp = 4;
923 qcam->transfer_scale = 2;
924 qcam->contrast = 192;
925 qcam->brightness = 180;
926 qcam->whitebal = 105;
927 qcam->top = 1;
928 qcam->left = 14;
929 qcam->mode = -1;
930 qcam->status = QC_PARAM_CHANGE;
931 return qcam;
867} 932}
868 933
869static int qcam_exclusive_release(struct file *file) 934static int qc_calibrate(struct qcam *q)
870{ 935{
871 struct video_device *dev = video_devdata(file); 936 /*
872 struct qcam_device *qcam = (struct qcam_device *)dev; 937 * Bugfix by Hanno Mueller hmueller@kabel.de, Mai 21 96
938 * The white balance is an individual value for each
939 * quickcam.
940 */
873 941
874 clear_bit(0, &qcam->in_use); 942 int value;
875 return 0; 943 int count = 0;
876}
877 944
878static const struct v4l2_file_operations qcam_fops = { 945 qc_command(q, 27); /* AutoAdjustOffset */
879 .owner = THIS_MODULE, 946 qc_command(q, 0); /* Dummy Parameter, ignored by the camera */
880 .open = qcam_exclusive_open,
881 .release = qcam_exclusive_release,
882 .ioctl = qcam_ioctl,
883 .read = qcam_read,
884};
885static struct video_device qcam_template = {
886 .name = "Connectix Quickcam",
887 .fops = &qcam_fops,
888 .release = video_device_release_empty,
889};
890 947
891#define MAX_CAMS 4 948 /* GetOffset (33) will read 255 until autocalibration */
892static struct qcam_device *qcams[MAX_CAMS]; 949 /* is finished. After that, a value of 1-254 will be */
893static unsigned int num_cams; 950 /* returned. */
951
952 do {
953 qc_command(q, 33);
954 value = qc_readparam(q);
955 mdelay(1);
956 schedule();
957 count++;
958 } while (value == 0xff && count < 2048);
959
960 q->whitebal = value;
961 return value;
962}
894 963
895static int init_bwqcam(struct parport *port) 964static int init_bwqcam(struct parport *port)
896{ 965{
897 struct qcam_device *qcam; 966 struct qcam *qcam;
898 967
899 if (num_cams == MAX_CAMS) { 968 if (num_cams == MAX_CAMS) {
900 printk(KERN_ERR "Too many Quickcams (max %d)\n", MAX_CAMS); 969 printk(KERN_ERR "Too many Quickcams (max %d)\n", MAX_CAMS);
@@ -919,7 +988,7 @@ static int init_bwqcam(struct parport *port)
919 988
920 parport_release(qcam->pdev); 989 parport_release(qcam->pdev);
921 990
922 printk(KERN_INFO "Connectix Quickcam on %s\n", qcam->pport->name); 991 v4l2_info(&qcam->v4l2_dev, "Connectix Quickcam on %s\n", qcam->pport->name);
923 992
924 if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { 993 if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
925 parport_unregister_device(qcam->pdev); 994 parport_unregister_device(qcam->pdev);
@@ -932,7 +1001,7 @@ static int init_bwqcam(struct parport *port)
932 return 0; 1001 return 0;
933} 1002}
934 1003
935static void close_bwqcam(struct qcam_device *qcam) 1004static void close_bwqcam(struct qcam *qcam)
936{ 1005{
937 video_unregister_device(&qcam->vdev); 1006 video_unregister_device(&qcam->vdev);
938 parport_unregister_device(qcam->pdev); 1007 parport_unregister_device(qcam->pdev);
@@ -983,7 +1052,7 @@ static void bwqcam_detach(struct parport *port)
983{ 1052{
984 int i; 1053 int i;
985 for (i = 0; i < num_cams; i++) { 1054 for (i = 0; i < num_cams; i++) {
986 struct qcam_device *qcam = qcams[i]; 1055 struct qcam *qcam = qcams[i];
987 if (qcam && qcam->pdev->port == port) { 1056 if (qcam && qcam->pdev->port == port) {
988 qcams[i] = NULL; 1057 qcams[i] = NULL;
989 close_bwqcam(qcam); 1058 close_bwqcam(qcam);
diff --git a/drivers/media/video/bw-qcam.h b/drivers/media/video/bw-qcam.h
deleted file mode 100644
index 8a60c5de0935..000000000000
--- a/drivers/media/video/bw-qcam.h
+++ /dev/null
@@ -1,69 +0,0 @@
1/*
2 * Video4Linux bw-qcam driver
3 *
4 * Derived from code..
5 */
6
7/******************************************************************
8
9Copyright (C) 1996 by Scott Laird
10
11Permission is hereby granted, free of charge, to any person obtaining
12a copy of this software and associated documentation files (the
13"Software"), to deal in the Software without restriction, including
14without limitation the rights to use, copy, modify, merge, publish,
15distribute, sublicense, and/or sell copies of the Software, and to
16permit persons to whom the Software is furnished to do so, subject to
17the following conditions:
18
19The above copyright notice and this permission notice shall be
20included in all copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25IN NO EVENT SHALL SCOTT LAIRD BE LIABLE FOR ANY CLAIM, DAMAGES OR
26OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
27ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28OTHER DEALINGS IN THE SOFTWARE.
29
30******************************************************************/
31
32/* One from column A... */
33#define QC_NOTSET 0
34#define QC_UNIDIR 1
35#define QC_BIDIR 2
36#define QC_SERIAL 3
37
38/* ... and one from column B */
39#define QC_ANY 0x00
40#define QC_FORCE_UNIDIR 0x10
41#define QC_FORCE_BIDIR 0x20
42#define QC_FORCE_SERIAL 0x30
43/* in the port_mode member */
44
45#define QC_MODE_MASK 0x07
46#define QC_FORCE_MASK 0x70
47
48#define MAX_HEIGHT 243
49#define MAX_WIDTH 336
50
51/* Bit fields for status flags */
52#define QC_PARAM_CHANGE 0x01 /* Camera status change has occurred */
53
54struct qcam_device {
55 struct video_device vdev;
56 struct pardevice *pdev;
57 struct parport *pport;
58 struct mutex lock;
59 int width, height;
60 int bpp;
61 int mode;
62 int contrast, brightness, whitebal;
63 int port_mode;
64 int transfer_scale;
65 int top, left;
66 int status;
67 unsigned int saved_bits;
68 unsigned long in_use;
69};
diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c
index 8f1dd88b32a6..6e4b19698c13 100644
--- a/drivers/media/video/c-qcam.c
+++ b/drivers/media/video/c-qcam.c
@@ -33,15 +33,17 @@
33#include <linux/mm.h> 33#include <linux/mm.h>
34#include <linux/parport.h> 34#include <linux/parport.h>
35#include <linux/sched.h> 35#include <linux/sched.h>
36#include <linux/videodev.h>
37#include <media/v4l2-common.h>
38#include <media/v4l2-ioctl.h>
39#include <linux/mutex.h> 36#include <linux/mutex.h>
40#include <linux/jiffies.h> 37#include <linux/jiffies.h>
41 38#include <linux/version.h>
39#include <linux/videodev2.h>
42#include <asm/uaccess.h> 40#include <asm/uaccess.h>
41#include <media/v4l2-device.h>
42#include <media/v4l2-common.h>
43#include <media/v4l2-ioctl.h>
43 44
44struct qcam_device { 45struct qcam {
46 struct v4l2_device v4l2_dev;
45 struct video_device vdev; 47 struct video_device vdev;
46 struct pardevice *pdev; 48 struct pardevice *pdev;
47 struct parport *pport; 49 struct parport *pport;
@@ -51,7 +53,6 @@ struct qcam_device {
51 int contrast, brightness, whitebal; 53 int contrast, brightness, whitebal;
52 int top, left; 54 int top, left;
53 unsigned int bidirectional; 55 unsigned int bidirectional;
54 unsigned long in_use;
55 struct mutex lock; 56 struct mutex lock;
56}; 57};
57 58
@@ -68,33 +69,45 @@ struct qcam_device {
68#define QC_DECIMATION_2 2 69#define QC_DECIMATION_2 2
69#define QC_DECIMATION_4 4 70#define QC_DECIMATION_4 4
70 71
71#define BANNER "Colour QuickCam for Video4Linux v0.05" 72#define BANNER "Colour QuickCam for Video4Linux v0.06"
72 73
73static int parport[MAX_CAMS] = { [1 ... MAX_CAMS-1] = -1 }; 74static int parport[MAX_CAMS] = { [1 ... MAX_CAMS-1] = -1 };
74static int probe = 2; 75static int probe = 2;
75static int force_rgb; 76static int force_rgb;
76static int video_nr = -1; 77static int video_nr = -1;
77 78
78static inline void qcam_set_ack(struct qcam_device *qcam, unsigned int i) 79/* FIXME: parport=auto would never have worked, surely? --RR */
80MODULE_PARM_DESC(parport, "parport=<auto|n[,n]...> for port detection method\n"
81 "probe=<0|1|2> for camera detection method\n"
82 "force_rgb=<0|1> for RGB data format (default BGR)");
83module_param_array(parport, int, NULL, 0);
84module_param(probe, int, 0);
85module_param(force_rgb, bool, 0);
86module_param(video_nr, int, 0);
87
88static struct qcam *qcams[MAX_CAMS];
89static unsigned int num_cams;
90
91static inline void qcam_set_ack(struct qcam *qcam, unsigned int i)
79{ 92{
80 /* note: the QC specs refer to the PCAck pin by voltage, not 93 /* note: the QC specs refer to the PCAck pin by voltage, not
81 software level. PC ports have builtin inverters. */ 94 software level. PC ports have builtin inverters. */
82 parport_frob_control(qcam->pport, 8, i ? 8 : 0); 95 parport_frob_control(qcam->pport, 8, i ? 8 : 0);
83} 96}
84 97
85static inline unsigned int qcam_ready1(struct qcam_device *qcam) 98static inline unsigned int qcam_ready1(struct qcam *qcam)
86{ 99{
87 return (parport_read_status(qcam->pport) & 0x8) ? 1 : 0; 100 return (parport_read_status(qcam->pport) & 0x8) ? 1 : 0;
88} 101}
89 102
90static inline unsigned int qcam_ready2(struct qcam_device *qcam) 103static inline unsigned int qcam_ready2(struct qcam *qcam)
91{ 104{
92 return (parport_read_data(qcam->pport) & 0x1) ? 1 : 0; 105 return (parport_read_data(qcam->pport) & 0x1) ? 1 : 0;
93} 106}
94 107
95static unsigned int qcam_await_ready1(struct qcam_device *qcam, 108static unsigned int qcam_await_ready1(struct qcam *qcam, int value)
96 int value)
97{ 109{
110 struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
98 unsigned long oldjiffies = jiffies; 111 unsigned long oldjiffies = jiffies;
99 unsigned int i; 112 unsigned int i;
100 113
@@ -112,14 +125,15 @@ static unsigned int qcam_await_ready1(struct qcam_device *qcam,
112 } 125 }
113 126
114 /* Probably somebody pulled the plug out. Not much we can do. */ 127 /* Probably somebody pulled the plug out. Not much we can do. */
115 printk(KERN_ERR "c-qcam: ready1 timeout (%d) %x %x\n", value, 128 v4l2_err(v4l2_dev, "ready1 timeout (%d) %x %x\n", value,
116 parport_read_status(qcam->pport), 129 parport_read_status(qcam->pport),
117 parport_read_control(qcam->pport)); 130 parport_read_control(qcam->pport));
118 return 1; 131 return 1;
119} 132}
120 133
121static unsigned int qcam_await_ready2(struct qcam_device *qcam, int value) 134static unsigned int qcam_await_ready2(struct qcam *qcam, int value)
122{ 135{
136 struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
123 unsigned long oldjiffies = jiffies; 137 unsigned long oldjiffies = jiffies;
124 unsigned int i; 138 unsigned int i;
125 139
@@ -137,14 +151,14 @@ static unsigned int qcam_await_ready2(struct qcam_device *qcam, int value)
137 } 151 }
138 152
139 /* Probably somebody pulled the plug out. Not much we can do. */ 153 /* Probably somebody pulled the plug out. Not much we can do. */
140 printk(KERN_ERR "c-qcam: ready2 timeout (%d) %x %x %x\n", value, 154 v4l2_err(v4l2_dev, "ready2 timeout (%d) %x %x %x\n", value,
141 parport_read_status(qcam->pport), 155 parport_read_status(qcam->pport),
142 parport_read_control(qcam->pport), 156 parport_read_control(qcam->pport),
143 parport_read_data(qcam->pport)); 157 parport_read_data(qcam->pport));
144 return 1; 158 return 1;
145} 159}
146 160
147static int qcam_read_data(struct qcam_device *qcam) 161static int qcam_read_data(struct qcam *qcam)
148{ 162{
149 unsigned int idata; 163 unsigned int idata;
150 164
@@ -159,21 +173,22 @@ static int qcam_read_data(struct qcam_device *qcam)
159 return idata; 173 return idata;
160} 174}
161 175
162static int qcam_write_data(struct qcam_device *qcam, unsigned int data) 176static int qcam_write_data(struct qcam *qcam, unsigned int data)
163{ 177{
178 struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
164 unsigned int idata; 179 unsigned int idata;
165 180
166 parport_write_data(qcam->pport, data); 181 parport_write_data(qcam->pport, data);
167 idata = qcam_read_data(qcam); 182 idata = qcam_read_data(qcam);
168 if (data != idata) { 183 if (data != idata) {
169 printk(KERN_WARNING "cqcam: sent %x but received %x\n", data, 184 v4l2_warn(v4l2_dev, "sent %x but received %x\n", data,
170 idata); 185 idata);
171 return 1; 186 return 1;
172 } 187 }
173 return 0; 188 return 0;
174} 189}
175 190
176static inline int qcam_set(struct qcam_device *qcam, unsigned int cmd, unsigned int data) 191static inline int qcam_set(struct qcam *qcam, unsigned int cmd, unsigned int data)
177{ 192{
178 if (qcam_write_data(qcam, cmd)) 193 if (qcam_write_data(qcam, cmd))
179 return -1; 194 return -1;
@@ -182,14 +197,14 @@ static inline int qcam_set(struct qcam_device *qcam, unsigned int cmd, unsigned
182 return 0; 197 return 0;
183} 198}
184 199
185static inline int qcam_get(struct qcam_device *qcam, unsigned int cmd) 200static inline int qcam_get(struct qcam *qcam, unsigned int cmd)
186{ 201{
187 if (qcam_write_data(qcam, cmd)) 202 if (qcam_write_data(qcam, cmd))
188 return -1; 203 return -1;
189 return qcam_read_data(qcam); 204 return qcam_read_data(qcam);
190} 205}
191 206
192static int qc_detect(struct qcam_device *qcam) 207static int qc_detect(struct qcam *qcam)
193{ 208{
194 unsigned int stat, ostat, i, count = 0; 209 unsigned int stat, ostat, i, count = 0;
195 210
@@ -246,7 +261,7 @@ static int qc_detect(struct qcam_device *qcam)
246 return 0; 261 return 0;
247} 262}
248 263
249static void qc_reset(struct qcam_device *qcam) 264static void qc_reset(struct qcam *qcam)
250{ 265{
251 parport_write_control(qcam->pport, 0xc); 266 parport_write_control(qcam->pport, 0xc);
252 parport_write_control(qcam->pport, 0x8); 267 parport_write_control(qcam->pport, 0x8);
@@ -258,55 +273,55 @@ static void qc_reset(struct qcam_device *qcam)
258/* Reset the QuickCam and program for brightness, contrast, 273/* Reset the QuickCam and program for brightness, contrast,
259 * white-balance, and resolution. */ 274 * white-balance, and resolution. */
260 275
261static void qc_setup(struct qcam_device *q) 276static void qc_setup(struct qcam *qcam)
262{ 277{
263 qc_reset(q); 278 qc_reset(qcam);
264 279
265 /* Set the brightness. */ 280 /* Set the brightness. */
266 qcam_set(q, 11, q->brightness); 281 qcam_set(qcam, 11, qcam->brightness);
267 282
268 /* Set the height and width. These refer to the actual 283 /* Set the height and width. These refer to the actual
269 CCD area *before* applying the selected decimation. */ 284 CCD area *before* applying the selected decimation. */
270 qcam_set(q, 17, q->ccd_height); 285 qcam_set(qcam, 17, qcam->ccd_height);
271 qcam_set(q, 19, q->ccd_width / 2); 286 qcam_set(qcam, 19, qcam->ccd_width / 2);
272 287
273 /* Set top and left. */ 288 /* Set top and left. */
274 qcam_set(q, 0xd, q->top); 289 qcam_set(qcam, 0xd, qcam->top);
275 qcam_set(q, 0xf, q->left); 290 qcam_set(qcam, 0xf, qcam->left);
276 291
277 /* Set contrast and white balance. */ 292 /* Set contrast and white balance. */
278 qcam_set(q, 0x19, q->contrast); 293 qcam_set(qcam, 0x19, qcam->contrast);
279 qcam_set(q, 0x1f, q->whitebal); 294 qcam_set(qcam, 0x1f, qcam->whitebal);
280 295
281 /* Set the speed. */ 296 /* Set the speed. */
282 qcam_set(q, 45, 2); 297 qcam_set(qcam, 45, 2);
283} 298}
284 299
285/* Read some bytes from the camera and put them in the buffer. 300/* Read some bytes from the camera and put them in the buffer.
286 nbytes should be a multiple of 3, because bidirectional mode gives 301 nbytes should be a multiple of 3, because bidirectional mode gives
287 us three bytes at a time. */ 302 us three bytes at a time. */
288 303
289static unsigned int qcam_read_bytes(struct qcam_device *q, unsigned char *buf, unsigned int nbytes) 304static unsigned int qcam_read_bytes(struct qcam *qcam, unsigned char *buf, unsigned int nbytes)
290{ 305{
291 unsigned int bytes = 0; 306 unsigned int bytes = 0;
292 307
293 qcam_set_ack(q, 0); 308 qcam_set_ack(qcam, 0);
294 if (q->bidirectional) { 309 if (qcam->bidirectional) {
295 /* It's a bidirectional port */ 310 /* It's a bidirectional port */
296 while (bytes < nbytes) { 311 while (bytes < nbytes) {
297 unsigned int lo1, hi1, lo2, hi2; 312 unsigned int lo1, hi1, lo2, hi2;
298 unsigned char r, g, b; 313 unsigned char r, g, b;
299 314
300 if (qcam_await_ready2(q, 1)) 315 if (qcam_await_ready2(qcam, 1))
301 return bytes; 316 return bytes;
302 lo1 = parport_read_data(q->pport) >> 1; 317 lo1 = parport_read_data(qcam->pport) >> 1;
303 hi1 = ((parport_read_status(q->pport) >> 3) & 0x1f) ^ 0x10; 318 hi1 = ((parport_read_status(qcam->pport) >> 3) & 0x1f) ^ 0x10;
304 qcam_set_ack(q, 1); 319 qcam_set_ack(qcam, 1);
305 if (qcam_await_ready2(q, 0)) 320 if (qcam_await_ready2(qcam, 0))
306 return bytes; 321 return bytes;
307 lo2 = parport_read_data(q->pport) >> 1; 322 lo2 = parport_read_data(qcam->pport) >> 1;
308 hi2 = ((parport_read_status(q->pport) >> 3) & 0x1f) ^ 0x10; 323 hi2 = ((parport_read_status(qcam->pport) >> 3) & 0x1f) ^ 0x10;
309 qcam_set_ack(q, 0); 324 qcam_set_ack(qcam, 0);
310 r = lo1 | ((hi1 & 1) << 7); 325 r = lo1 | ((hi1 & 1) << 7);
311 g = ((hi1 & 0x1e) << 3) | ((hi2 & 0x1e) >> 1); 326 g = ((hi1 & 0x1e) << 3) | ((hi2 & 0x1e) >> 1);
312 b = lo2 | ((hi2 & 1) << 7); 327 b = lo2 | ((hi2 & 1) << 7);
@@ -328,14 +343,14 @@ static unsigned int qcam_read_bytes(struct qcam_device *q, unsigned char *buf, u
328 while (bytes < nbytes) { 343 while (bytes < nbytes) {
329 unsigned int hi, lo; 344 unsigned int hi, lo;
330 345
331 if (qcam_await_ready1(q, 1)) 346 if (qcam_await_ready1(qcam, 1))
332 return bytes; 347 return bytes;
333 hi = (parport_read_status(q->pport) & 0xf0); 348 hi = (parport_read_status(qcam->pport) & 0xf0);
334 qcam_set_ack(q, 1); 349 qcam_set_ack(qcam, 1);
335 if (qcam_await_ready1(q, 0)) 350 if (qcam_await_ready1(qcam, 0))
336 return bytes; 351 return bytes;
337 lo = (parport_read_status(q->pport) & 0xf0); 352 lo = (parport_read_status(qcam->pport) & 0xf0);
338 qcam_set_ack(q, 0); 353 qcam_set_ack(qcam, 0);
339 /* flip some bits */ 354 /* flip some bits */
340 rgb[(i = bytes++ % 3)] = (hi | (lo >> 4)) ^ 0x88; 355 rgb[(i = bytes++ % 3)] = (hi | (lo >> 4)) ^ 0x88;
341 if (i >= 2) { 356 if (i >= 2) {
@@ -361,10 +376,11 @@ get_fragment:
361 376
362#define BUFSZ 150 377#define BUFSZ 150
363 378
364static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long len) 379static long qc_capture(struct qcam *qcam, char __user *buf, unsigned long len)
365{ 380{
381 struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
366 unsigned lines, pixelsperline, bitsperxfer; 382 unsigned lines, pixelsperline, bitsperxfer;
367 unsigned int is_bi_dir = q->bidirectional; 383 unsigned int is_bi_dir = qcam->bidirectional;
368 size_t wantlen, outptr = 0; 384 size_t wantlen, outptr = 0;
369 char tmpbuf[BUFSZ]; 385 char tmpbuf[BUFSZ];
370 386
@@ -373,10 +389,10 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le
373 389
374 /* Wait for camera to become ready */ 390 /* Wait for camera to become ready */
375 for (;;) { 391 for (;;) {
376 int i = qcam_get(q, 41); 392 int i = qcam_get(qcam, 41);
377 393
378 if (i == -1) { 394 if (i == -1) {
379 qc_setup(q); 395 qc_setup(qcam);
380 return -EIO; 396 return -EIO;
381 } 397 }
382 if ((i & 0x80) == 0) 398 if ((i & 0x80) == 0)
@@ -384,25 +400,25 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le
384 schedule(); 400 schedule();
385 } 401 }
386 402
387 if (qcam_set(q, 7, (q->mode | (is_bi_dir ? 1 : 0)) + 1)) 403 if (qcam_set(qcam, 7, (qcam->mode | (is_bi_dir ? 1 : 0)) + 1))
388 return -EIO; 404 return -EIO;
389 405
390 lines = q->height; 406 lines = qcam->height;
391 pixelsperline = q->width; 407 pixelsperline = qcam->width;
392 bitsperxfer = (is_bi_dir) ? 24 : 8; 408 bitsperxfer = (is_bi_dir) ? 24 : 8;
393 409
394 if (is_bi_dir) { 410 if (is_bi_dir) {
395 /* Turn the port around */ 411 /* Turn the port around */
396 parport_data_reverse(q->pport); 412 parport_data_reverse(qcam->pport);
397 mdelay(3); 413 mdelay(3);
398 qcam_set_ack(q, 0); 414 qcam_set_ack(qcam, 0);
399 if (qcam_await_ready1(q, 1)) { 415 if (qcam_await_ready1(qcam, 1)) {
400 qc_setup(q); 416 qc_setup(qcam);
401 return -EIO; 417 return -EIO;
402 } 418 }
403 qcam_set_ack(q, 1); 419 qcam_set_ack(qcam, 1);
404 if (qcam_await_ready1(q, 0)) { 420 if (qcam_await_ready1(qcam, 0)) {
405 qc_setup(q); 421 qc_setup(qcam);
406 return -EIO; 422 return -EIO;
407 } 423 }
408 } 424 }
@@ -413,7 +429,7 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le
413 size_t t, s; 429 size_t t, s;
414 430
415 s = (wantlen > BUFSZ) ? BUFSZ : wantlen; 431 s = (wantlen > BUFSZ) ? BUFSZ : wantlen;
416 t = qcam_read_bytes(q, tmpbuf, s); 432 t = qcam_read_bytes(qcam, tmpbuf, s);
417 if (outptr < len) { 433 if (outptr < len) {
418 size_t sz = len - outptr; 434 size_t sz = len - outptr;
419 435
@@ -432,10 +448,10 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le
432 len = outptr; 448 len = outptr;
433 449
434 if (wantlen) { 450 if (wantlen) {
435 printk(KERN_ERR "qcam: short read.\n"); 451 v4l2_err(v4l2_dev, "short read.\n");
436 if (is_bi_dir) 452 if (is_bi_dir)
437 parport_data_forward(q->pport); 453 parport_data_forward(qcam->pport);
438 qc_setup(q); 454 qc_setup(qcam);
439 return len; 455 return len;
440 } 456 }
441 457
@@ -443,49 +459,49 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le
443 int l; 459 int l;
444 460
445 do { 461 do {
446 l = qcam_read_bytes(q, tmpbuf, 3); 462 l = qcam_read_bytes(qcam, tmpbuf, 3);
447 cond_resched(); 463 cond_resched();
448 } while (l && (tmpbuf[0] == 0x7e || tmpbuf[1] == 0x7e || tmpbuf[2] == 0x7e)); 464 } while (l && (tmpbuf[0] == 0x7e || tmpbuf[1] == 0x7e || tmpbuf[2] == 0x7e));
449 if (force_rgb) { 465 if (force_rgb) {
450 if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf) 466 if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf)
451 printk(KERN_ERR "qcam: bad EOF\n"); 467 v4l2_err(v4l2_dev, "bad EOF\n");
452 } else { 468 } else {
453 if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe) 469 if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe)
454 printk(KERN_ERR "qcam: bad EOF\n"); 470 v4l2_err(v4l2_dev, "bad EOF\n");
455 } 471 }
456 qcam_set_ack(q, 0); 472 qcam_set_ack(qcam, 0);
457 if (qcam_await_ready1(q, 1)) { 473 if (qcam_await_ready1(qcam, 1)) {
458 printk(KERN_ERR "qcam: no ack after EOF\n"); 474 v4l2_err(v4l2_dev, "no ack after EOF\n");
459 parport_data_forward(q->pport); 475 parport_data_forward(qcam->pport);
460 qc_setup(q); 476 qc_setup(qcam);
461 return len; 477 return len;
462 } 478 }
463 parport_data_forward(q->pport); 479 parport_data_forward(qcam->pport);
464 mdelay(3); 480 mdelay(3);
465 qcam_set_ack(q, 1); 481 qcam_set_ack(qcam, 1);
466 if (qcam_await_ready1(q, 0)) { 482 if (qcam_await_ready1(qcam, 0)) {
467 printk(KERN_ERR "qcam: no ack to port turnaround\n"); 483 v4l2_err(v4l2_dev, "no ack to port turnaround\n");
468 qc_setup(q); 484 qc_setup(qcam);
469 return len; 485 return len;
470 } 486 }
471 } else { 487 } else {
472 int l; 488 int l;
473 489
474 do { 490 do {
475 l = qcam_read_bytes(q, tmpbuf, 1); 491 l = qcam_read_bytes(qcam, tmpbuf, 1);
476 cond_resched(); 492 cond_resched();
477 } while (l && tmpbuf[0] == 0x7e); 493 } while (l && tmpbuf[0] == 0x7e);
478 l = qcam_read_bytes(q, tmpbuf + 1, 2); 494 l = qcam_read_bytes(qcam, tmpbuf + 1, 2);
479 if (force_rgb) { 495 if (force_rgb) {
480 if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf) 496 if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf)
481 printk(KERN_ERR "qcam: bad EOF\n"); 497 v4l2_err(v4l2_dev, "bad EOF\n");
482 } else { 498 } else {
483 if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe) 499 if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe)
484 printk(KERN_ERR "qcam: bad EOF\n"); 500 v4l2_err(v4l2_dev, "bad EOF\n");
485 } 501 }
486 } 502 }
487 503
488 qcam_write_data(q, 0); 504 qcam_write_data(qcam, 0);
489 return len; 505 return len;
490} 506}
491 507
@@ -493,184 +509,202 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le
493 * Video4linux interfacing 509 * Video4linux interfacing
494 */ 510 */
495 511
496static long qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg) 512static int qcam_querycap(struct file *file, void *priv,
513 struct v4l2_capability *vcap)
497{ 514{
498 struct video_device *dev = video_devdata(file); 515 struct qcam *qcam = video_drvdata(file);
499 struct qcam_device *qcam = (struct qcam_device *)dev;
500 516
501 switch (cmd) { 517 strlcpy(vcap->driver, qcam->v4l2_dev.name, sizeof(vcap->driver));
502 case VIDIOCGCAP: 518 strlcpy(vcap->card, "Color Quickcam", sizeof(vcap->card));
503 { 519 strlcpy(vcap->bus_info, "parport", sizeof(vcap->bus_info));
504 struct video_capability *b = arg; 520 vcap->version = KERNEL_VERSION(0, 0, 3);
521 vcap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
522 return 0;
523}
505 524
506 strcpy(b->name, "Quickcam"); 525static int qcam_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
507 b->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES; 526{
508 b->channels = 1; 527 if (vin->index > 0)
509 b->audios = 0; 528 return -EINVAL;
510 b->maxwidth = 320; 529 strlcpy(vin->name, "Camera", sizeof(vin->name));
511 b->maxheight = 240; 530 vin->type = V4L2_INPUT_TYPE_CAMERA;
512 b->minwidth = 80; 531 vin->audioset = 0;
513 b->minheight = 60; 532 vin->tuner = 0;
514 return 0; 533 vin->std = 0;
515 } 534 vin->status = 0;
516 case VIDIOCGCHAN: 535 return 0;
517 { 536}
518 struct video_channel *v = arg;
519
520 if (v->channel != 0)
521 return -EINVAL;
522 v->flags = 0;
523 v->tuners = 0;
524 /* Good question.. its composite or SVHS so.. */
525 v->type = VIDEO_TYPE_CAMERA;
526 strcpy(v->name, "Camera");
527 return 0;
528 }
529 case VIDIOCSCHAN:
530 {
531 struct video_channel *v = arg;
532 537
533 if (v->channel != 0) 538static int qcam_g_input(struct file *file, void *fh, unsigned int *inp)
534 return -EINVAL; 539{
535 return 0; 540 *inp = 0;
536 } 541 return 0;
537 case VIDIOCGTUNER: 542}
538 { 543
539 struct video_tuner *v = arg; 544static int qcam_s_input(struct file *file, void *fh, unsigned int inp)
540 545{
541 if (v->tuner) 546 return (inp > 0) ? -EINVAL : 0;
542 return -EINVAL; 547}
543 memset(v, 0, sizeof(*v)); 548
544 strcpy(v->name, "Format"); 549static int qcam_queryctrl(struct file *file, void *priv,
545 v->mode = VIDEO_MODE_AUTO; 550 struct v4l2_queryctrl *qc)
546 return 0; 551{
552 switch (qc->id) {
553 case V4L2_CID_BRIGHTNESS:
554 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 240);
555 case V4L2_CID_CONTRAST:
556 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 192);
557 case V4L2_CID_GAMMA:
558 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
547 } 559 }
548 case VIDIOCSTUNER: 560 return -EINVAL;
549 { 561}
550 struct video_tuner *v = arg; 562
551 563static int qcam_g_ctrl(struct file *file, void *priv,
552 if (v->tuner) 564 struct v4l2_control *ctrl)
553 return -EINVAL; 565{
554 if (v->mode != VIDEO_MODE_AUTO) 566 struct qcam *qcam = video_drvdata(file);
555 return -EINVAL; 567 int ret = 0;
556 return 0; 568
569 switch (ctrl->id) {
570 case V4L2_CID_BRIGHTNESS:
571 ctrl->value = qcam->brightness;
572 break;
573 case V4L2_CID_CONTRAST:
574 ctrl->value = qcam->contrast;
575 break;
576 case V4L2_CID_GAMMA:
577 ctrl->value = qcam->whitebal;
578 break;
579 default:
580 ret = -EINVAL;
581 break;
557 } 582 }
558 case VIDIOCGPICT: 583 return ret;
559 { 584}
560 struct video_picture *p = arg; 585
561 586static int qcam_s_ctrl(struct file *file, void *priv,
562 p->colour = 0x8000; 587 struct v4l2_control *ctrl)
563 p->hue = 0x8000; 588{
564 p->brightness = qcam->brightness << 8; 589 struct qcam *qcam = video_drvdata(file);
565 p->contrast = qcam->contrast << 8; 590 int ret = 0;
566 p->whiteness = qcam->whitebal << 8; 591
567 p->depth = 24; 592 mutex_lock(&qcam->lock);
568 p->palette = VIDEO_PALETTE_RGB24; 593 switch (ctrl->id) {
569 return 0; 594 case V4L2_CID_BRIGHTNESS:
595 qcam->brightness = ctrl->value;
596 break;
597 case V4L2_CID_CONTRAST:
598 qcam->contrast = ctrl->value;
599 break;
600 case V4L2_CID_GAMMA:
601 qcam->whitebal = ctrl->value;
602 break;
603 default:
604 ret = -EINVAL;
605 break;
570 } 606 }
571 case VIDIOCSPICT: 607 if (ret == 0) {
572 {
573 struct video_picture *p = arg;
574
575 /*
576 * Sanity check args
577 */
578 if (p->depth != 24 || p->palette != VIDEO_PALETTE_RGB24)
579 return -EINVAL;
580
581 /*
582 * Now load the camera.
583 */
584 qcam->brightness = p->brightness >> 8;
585 qcam->contrast = p->contrast >> 8;
586 qcam->whitebal = p->whiteness >> 8;
587
588 mutex_lock(&qcam->lock);
589 parport_claim_or_block(qcam->pdev); 608 parport_claim_or_block(qcam->pdev);
590 qc_setup(qcam); 609 qc_setup(qcam);
591 parport_release(qcam->pdev); 610 parport_release(qcam->pdev);
592 mutex_unlock(&qcam->lock);
593 return 0;
594 } 611 }
595 case VIDIOCSWIN: 612 mutex_unlock(&qcam->lock);
596 { 613 return ret;
597 struct video_window *vw = arg; 614}
598
599 if (vw->flags)
600 return -EINVAL;
601 if (vw->clipcount)
602 return -EINVAL;
603 if (vw->height < 60 || vw->height > 240)
604 return -EINVAL;
605 if (vw->width < 80 || vw->width > 320)
606 return -EINVAL;
607
608 qcam->width = 80;
609 qcam->height = 60;
610 qcam->mode = QC_DECIMATION_4;
611 615
612 if (vw->width >= 160 && vw->height >= 120) { 616static int qcam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
613 qcam->width = 160; 617{
614 qcam->height = 120; 618 struct qcam *qcam = video_drvdata(file);
615 qcam->mode = QC_DECIMATION_2; 619 struct v4l2_pix_format *pix = &fmt->fmt.pix;
616 } 620
617 if (vw->width >= 320 && vw->height >= 240) { 621 pix->width = qcam->width;
618 qcam->width = 320; 622 pix->height = qcam->height;
619 qcam->height = 240; 623 pix->pixelformat = V4L2_PIX_FMT_RGB24;
620 qcam->mode = QC_DECIMATION_1; 624 pix->field = V4L2_FIELD_NONE;
621 } 625 pix->bytesperline = 3 * qcam->width;
622 qcam->mode |= QC_MILLIONS; 626 pix->sizeimage = 3 * qcam->width * qcam->height;
623#if 0 627 /* Just a guess */
624 if (vw->width >= 640 && vw->height >= 480) { 628 pix->colorspace = V4L2_COLORSPACE_SRGB;
625 qcam->width = 640; 629 return 0;
626 qcam->height = 480; 630}
627 qcam->mode = QC_BILLIONS | QC_DECIMATION_1; 631
628 } 632static int qcam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
629#endif 633{
630 /* Ok we figured out what to use from our 634 struct v4l2_pix_format *pix = &fmt->fmt.pix;
631 wide choice */ 635
632 mutex_lock(&qcam->lock); 636 if (pix->height < 60 || pix->width < 80) {
633 parport_claim_or_block(qcam->pdev); 637 pix->height = 60;
634 qc_setup(qcam); 638 pix->width = 80;
635 parport_release(qcam->pdev); 639 } else if (pix->height < 120 || pix->width < 160) {
636 mutex_unlock(&qcam->lock); 640 pix->height = 120;
637 return 0; 641 pix->width = 160;
638 } 642 } else {
639 case VIDIOCGWIN: 643 pix->height = 240;
640 { 644 pix->width = 320;
641 struct video_window *vw = arg;
642 memset(vw, 0, sizeof(*vw));
643 vw->width = qcam->width;
644 vw->height = qcam->height;
645 return 0;
646 } 645 }
647 case VIDIOCKEY: 646 pix->pixelformat = V4L2_PIX_FMT_RGB24;
648 return 0; 647 pix->field = V4L2_FIELD_NONE;
649 case VIDIOCCAPTURE: 648 pix->bytesperline = 3 * pix->width;
650 case VIDIOCGFBUF: 649 pix->sizeimage = 3 * pix->width * pix->height;
651 case VIDIOCSFBUF: 650 /* Just a guess */
652 case VIDIOCGFREQ: 651 pix->colorspace = V4L2_COLORSPACE_SRGB;
653 case VIDIOCSFREQ: 652 return 0;
654 case VIDIOCGAUDIO: 653}
655 case VIDIOCSAUDIO: 654
656 return -EINVAL; 655static int qcam_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
656{
657 struct qcam *qcam = video_drvdata(file);
658 struct v4l2_pix_format *pix = &fmt->fmt.pix;
659 int ret = qcam_try_fmt_vid_cap(file, fh, fmt);
660
661 if (ret)
662 return ret;
663 switch (pix->height) {
664 case 60:
665 qcam->mode = QC_DECIMATION_4;
666 break;
667 case 120:
668 qcam->mode = QC_DECIMATION_2;
669 break;
657 default: 670 default:
658 return -ENOIOCTLCMD; 671 qcam->mode = QC_DECIMATION_1;
672 break;
659 } 673 }
674
675 mutex_lock(&qcam->lock);
676 qcam->mode |= QC_MILLIONS;
677 qcam->height = pix->height;
678 qcam->width = pix->width;
679 parport_claim_or_block(qcam->pdev);
680 qc_setup(qcam);
681 parport_release(qcam->pdev);
682 mutex_unlock(&qcam->lock);
660 return 0; 683 return 0;
661} 684}
662 685
663static long qcam_ioctl(struct file *file, 686static int qcam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
664 unsigned int cmd, unsigned long arg)
665{ 687{
666 return video_usercopy(file, cmd, arg, qcam_do_ioctl); 688 static struct v4l2_fmtdesc formats[] = {
689 { 0, 0, 0,
690 "RGB 8:8:8", V4L2_PIX_FMT_RGB24,
691 { 0, 0, 0, 0 }
692 },
693 };
694 enum v4l2_buf_type type = fmt->type;
695
696 if (fmt->index > 0)
697 return -EINVAL;
698
699 *fmt = formats[fmt->index];
700 fmt->type = type;
701 return 0;
667} 702}
668 703
669static ssize_t qcam_read(struct file *file, char __user *buf, 704static ssize_t qcam_read(struct file *file, char __user *buf,
670 size_t count, loff_t *ppos) 705 size_t count, loff_t *ppos)
671{ 706{
672 struct video_device *v = video_devdata(file); 707 struct qcam *qcam = video_drvdata(file);
673 struct qcam_device *qcam = (struct qcam_device *)v;
674 int len; 708 int len;
675 709
676 mutex_lock(&qcam->lock); 710 mutex_lock(&qcam->lock);
@@ -682,81 +716,80 @@ static ssize_t qcam_read(struct file *file, char __user *buf,
682 return len; 716 return len;
683} 717}
684 718
685static int qcam_exclusive_open(struct file *file)
686{
687 struct video_device *dev = video_devdata(file);
688 struct qcam_device *qcam = (struct qcam_device *)dev;
689
690 return test_and_set_bit(0, &qcam->in_use) ? -EBUSY : 0;
691}
692
693static int qcam_exclusive_release(struct file *file)
694{
695 struct video_device *dev = video_devdata(file);
696 struct qcam_device *qcam = (struct qcam_device *)dev;
697
698 clear_bit(0, &qcam->in_use);
699 return 0;
700}
701
702/* video device template */
703static const struct v4l2_file_operations qcam_fops = { 719static const struct v4l2_file_operations qcam_fops = {
704 .owner = THIS_MODULE, 720 .owner = THIS_MODULE,
705 .open = qcam_exclusive_open, 721 .ioctl = video_ioctl2,
706 .release = qcam_exclusive_release,
707 .ioctl = qcam_ioctl,
708 .read = qcam_read, 722 .read = qcam_read,
709}; 723};
710 724
711static struct video_device qcam_template = { 725static const struct v4l2_ioctl_ops qcam_ioctl_ops = {
712 .name = "Colour QuickCam", 726 .vidioc_querycap = qcam_querycap,
713 .fops = &qcam_fops, 727 .vidioc_g_input = qcam_g_input,
714 .release = video_device_release_empty, 728 .vidioc_s_input = qcam_s_input,
729 .vidioc_enum_input = qcam_enum_input,
730 .vidioc_queryctrl = qcam_queryctrl,
731 .vidioc_g_ctrl = qcam_g_ctrl,
732 .vidioc_s_ctrl = qcam_s_ctrl,
733 .vidioc_enum_fmt_vid_cap = qcam_enum_fmt_vid_cap,
734 .vidioc_g_fmt_vid_cap = qcam_g_fmt_vid_cap,
735 .vidioc_s_fmt_vid_cap = qcam_s_fmt_vid_cap,
736 .vidioc_try_fmt_vid_cap = qcam_try_fmt_vid_cap,
715}; 737};
716 738
717/* Initialize the QuickCam driver control structure. */ 739/* Initialize the QuickCam driver control structure. */
718 740
719static struct qcam_device *qcam_init(struct parport *port) 741static struct qcam *qcam_init(struct parport *port)
720{ 742{
721 struct qcam_device *q; 743 struct qcam *qcam;
744 struct v4l2_device *v4l2_dev;
722 745
723 q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL); 746 qcam = kzalloc(sizeof(*qcam), GFP_KERNEL);
724 if (q == NULL) 747 if (qcam == NULL)
725 return NULL; 748 return NULL;
726 749
727 q->pport = port; 750 v4l2_dev = &qcam->v4l2_dev;
728 q->pdev = parport_register_device(port, "c-qcam", NULL, NULL, 751 strlcpy(v4l2_dev->name, "c-qcam", sizeof(v4l2_dev->name));
752
753 if (v4l2_device_register(NULL, v4l2_dev) < 0) {
754 v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
755 return NULL;
756 }
757
758 qcam->pport = port;
759 qcam->pdev = parport_register_device(port, "c-qcam", NULL, NULL,
729 NULL, 0, NULL); 760 NULL, 0, NULL);
730 761
731 q->bidirectional = (q->pport->modes & PARPORT_MODE_TRISTATE) ? 1 : 0; 762 qcam->bidirectional = (qcam->pport->modes & PARPORT_MODE_TRISTATE) ? 1 : 0;
732 763
733 if (q->pdev == NULL) { 764 if (qcam->pdev == NULL) {
734 printk(KERN_ERR "c-qcam: couldn't register for %s.\n", 765 v4l2_err(v4l2_dev, "couldn't register for %s.\n", port->name);
735 port->name); 766 kfree(qcam);
736 kfree(q);
737 return NULL; 767 return NULL;
738 } 768 }
739 769
740 memcpy(&q->vdev, &qcam_template, sizeof(qcam_template)); 770 strlcpy(qcam->vdev.name, "Colour QuickCam", sizeof(qcam->vdev.name));
741 771 qcam->vdev.v4l2_dev = v4l2_dev;
742 mutex_init(&q->lock); 772 qcam->vdev.fops = &qcam_fops;
743 q->width = q->ccd_width = 320; 773 qcam->vdev.ioctl_ops = &qcam_ioctl_ops;
744 q->height = q->ccd_height = 240; 774 qcam->vdev.release = video_device_release_empty;
745 q->mode = QC_MILLIONS | QC_DECIMATION_1; 775 video_set_drvdata(&qcam->vdev, qcam);
746 q->contrast = 192; 776
747 q->brightness = 240; 777 mutex_init(&qcam->lock);
748 q->whitebal = 128; 778 qcam->width = qcam->ccd_width = 320;
749 q->top = 1; 779 qcam->height = qcam->ccd_height = 240;
750 q->left = 14; 780 qcam->mode = QC_MILLIONS | QC_DECIMATION_1;
751 return q; 781 qcam->contrast = 192;
782 qcam->brightness = 240;
783 qcam->whitebal = 128;
784 qcam->top = 1;
785 qcam->left = 14;
786 return qcam;
752} 787}
753 788
754static struct qcam_device *qcams[MAX_CAMS];
755static unsigned int num_cams;
756
757static int init_cqcam(struct parport *port) 789static int init_cqcam(struct parport *port)
758{ 790{
759 struct qcam_device *qcam; 791 struct qcam *qcam;
792 struct v4l2_device *v4l2_dev;
760 793
761 if (parport[0] != -1) { 794 if (parport[0] != -1) {
762 /* The user gave specific instructions */ 795 /* The user gave specific instructions */
@@ -777,6 +810,8 @@ static int init_cqcam(struct parport *port)
777 if (qcam == NULL) 810 if (qcam == NULL)
778 return -ENODEV; 811 return -ENODEV;
779 812
813 v4l2_dev = &qcam->v4l2_dev;
814
780 parport_claim_or_block(qcam->pdev); 815 parport_claim_or_block(qcam->pdev);
781 816
782 qc_reset(qcam); 817 qc_reset(qcam);
@@ -793,14 +828,14 @@ static int init_cqcam(struct parport *port)
793 parport_release(qcam->pdev); 828 parport_release(qcam->pdev);
794 829
795 if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { 830 if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
796 printk(KERN_ERR "Unable to register Colour QuickCam on %s\n", 831 v4l2_err(v4l2_dev, "Unable to register Colour QuickCam on %s\n",
797 qcam->pport->name); 832 qcam->pport->name);
798 parport_unregister_device(qcam->pdev); 833 parport_unregister_device(qcam->pdev);
799 kfree(qcam); 834 kfree(qcam);
800 return -ENODEV; 835 return -ENODEV;
801 } 836 }
802 837
803 printk(KERN_INFO "%s: Colour QuickCam found on %s\n", 838 v4l2_info(v4l2_dev, "%s: Colour QuickCam found on %s\n",
804 video_device_node_name(&qcam->vdev), qcam->pport->name); 839 video_device_node_name(&qcam->vdev), qcam->pport->name);
805 840
806 qcams[num_cams++] = qcam; 841 qcams[num_cams++] = qcam;
@@ -808,7 +843,7 @@ static int init_cqcam(struct parport *port)
808 return 0; 843 return 0;
809} 844}
810 845
811static void close_cqcam(struct qcam_device *qcam) 846static void close_cqcam(struct qcam *qcam)
812{ 847{
813 video_unregister_device(&qcam->vdev); 848 video_unregister_device(&qcam->vdev);
814 parport_unregister_device(qcam->pdev); 849 parport_unregister_device(qcam->pdev);
@@ -833,7 +868,7 @@ static struct parport_driver cqcam_driver = {
833 868
834static int __init cqcam_init(void) 869static int __init cqcam_init(void)
835{ 870{
836 printk(BANNER "\n"); 871 printk(KERN_INFO BANNER "\n");
837 872
838 return parport_register_driver(&cqcam_driver); 873 return parport_register_driver(&cqcam_driver);
839} 874}
@@ -852,14 +887,5 @@ MODULE_AUTHOR("Philip Blundell <philb@gnu.org>");
852MODULE_DESCRIPTION(BANNER); 887MODULE_DESCRIPTION(BANNER);
853MODULE_LICENSE("GPL"); 888MODULE_LICENSE("GPL");
854 889
855/* FIXME: parport=auto would never have worked, surely? --RR */
856MODULE_PARM_DESC(parport, "parport=<auto|n[,n]...> for port detection method\n"
857 "probe=<0|1|2> for camera detection method\n"
858 "force_rgb=<0|1> for RGB data format (default BGR)");
859module_param_array(parport, int, NULL, 0);
860module_param(probe, int, 0);
861module_param(force_rgb, bool, 0);
862module_param(video_nr, int, 0);
863
864module_init(cqcam_init); 890module_init(cqcam_init);
865module_exit(cqcam_cleanup); 891module_exit(cqcam_cleanup);
diff --git a/drivers/media/video/cx18/cx18-alsa-main.c b/drivers/media/video/cx18/cx18-alsa-main.c
index b5d7cbf4528a..d50d69da387b 100644
--- a/drivers/media/video/cx18/cx18-alsa-main.c
+++ b/drivers/media/video/cx18/cx18-alsa-main.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * ALSA interface to cx18 PCM capture streams 2 * ALSA interface to cx18 PCM capture streams
3 * 3 *
4 * Copyright (C) 2009 Andy Walls <awalls@radix.net> 4 * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net>
5 * Copyright (C) 2009 Devin Heitmueller <dheitmueller@kernellabs.com> 5 * Copyright (C) 2009 Devin Heitmueller <dheitmueller@kernellabs.com>
6 * 6 *
7 * Portions of this work were sponsored by ONELAN Limited. 7 * Portions of this work were sponsored by ONELAN Limited.
diff --git a/drivers/media/video/cx18/cx18-alsa-mixer.c b/drivers/media/video/cx18/cx18-alsa-mixer.c
index ef21114309fe..341bddc00b77 100644
--- a/drivers/media/video/cx18/cx18-alsa-mixer.c
+++ b/drivers/media/video/cx18/cx18-alsa-mixer.c
@@ -2,7 +2,7 @@
2 * ALSA mixer controls for the 2 * ALSA mixer controls for the
3 * ALSA interface to cx18 PCM capture streams 3 * ALSA interface to cx18 PCM capture streams
4 * 4 *
5 * Copyright (C) 2009 Andy Walls <awalls@radix.net> 5 * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
diff --git a/drivers/media/video/cx18/cx18-alsa-mixer.h b/drivers/media/video/cx18/cx18-alsa-mixer.h
index 2d418db000fe..ec9238793f6f 100644
--- a/drivers/media/video/cx18/cx18-alsa-mixer.h
+++ b/drivers/media/video/cx18/cx18-alsa-mixer.h
@@ -2,7 +2,7 @@
2 * ALSA mixer controls for the 2 * ALSA mixer controls for the
3 * ALSA interface to cx18 PCM capture streams 3 * ALSA interface to cx18 PCM capture streams
4 * 4 *
5 * Copyright (C) 2009 Andy Walls <awalls@radix.net> 5 * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
diff --git a/drivers/media/video/cx18/cx18-alsa-pcm.c b/drivers/media/video/cx18/cx18-alsa-pcm.c
index 2bd312daeb1e..8f55692db36d 100644
--- a/drivers/media/video/cx18/cx18-alsa-pcm.c
+++ b/drivers/media/video/cx18/cx18-alsa-pcm.c
@@ -2,7 +2,7 @@
2 * ALSA PCM device for the 2 * ALSA PCM device for the
3 * ALSA interface to cx18 PCM capture streams 3 * ALSA interface to cx18 PCM capture streams
4 * 4 *
5 * Copyright (C) 2009 Andy Walls <awalls@radix.net> 5 * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net>
6 * Copyright (C) 2009 Devin Heitmueller <dheitmueller@kernellabs.com> 6 * Copyright (C) 2009 Devin Heitmueller <dheitmueller@kernellabs.com>
7 * 7 *
8 * Portions of this work were sponsored by ONELAN Limited. 8 * Portions of this work were sponsored by ONELAN Limited.
diff --git a/drivers/media/video/cx18/cx18-alsa-pcm.h b/drivers/media/video/cx18/cx18-alsa-pcm.h
index 325662c647a0..d26e51f94577 100644
--- a/drivers/media/video/cx18/cx18-alsa-pcm.h
+++ b/drivers/media/video/cx18/cx18-alsa-pcm.h
@@ -2,7 +2,7 @@
2 * ALSA PCM device for the 2 * ALSA PCM device for the
3 * ALSA interface to cx18 PCM capture streams 3 * ALSA interface to cx18 PCM capture streams
4 * 4 *
5 * Copyright (C) 2009 Andy Walls <awalls@radix.net> 5 * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
diff --git a/drivers/media/video/cx18/cx18-alsa.h b/drivers/media/video/cx18/cx18-alsa.h
index 88a1cde7540b..447da374c9e8 100644
--- a/drivers/media/video/cx18/cx18-alsa.h
+++ b/drivers/media/video/cx18/cx18-alsa.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * ALSA interface to cx18 PCM capture streams 2 * ALSA interface to cx18 PCM capture streams
3 * 3 *
4 * Copyright (C) 2009 Andy Walls <awalls@radix.net> 4 * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by 7 * it under the terms of the GNU General Public License as published by
diff --git a/drivers/media/video/cx18/cx18-av-audio.c b/drivers/media/video/cx18/cx18-av-audio.c
index 9e30983f2ff6..43d09a24b262 100644
--- a/drivers/media/video/cx18/cx18-av-audio.c
+++ b/drivers/media/video/cx18/cx18-av-audio.c
@@ -4,7 +4,7 @@
4 * Derived from cx25840-audio.c 4 * Derived from cx25840-audio.c
5 * 5 *
6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> 6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
7 * Copyright (C) 2008 Andy Walls <awalls@radix.net> 7 * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
8 * 8 *
9 * This program is free software; you can redistribute it and/or 9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License 10 * modify it under the terms of the GNU General Public License
diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c
index 0e5006b14279..a41951cab276 100644
--- a/drivers/media/video/cx18/cx18-av-core.c
+++ b/drivers/media/video/cx18/cx18-av-core.c
@@ -4,7 +4,7 @@
4 * Derived from cx25840-core.c 4 * Derived from cx25840-core.c
5 * 5 *
6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> 6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
7 * Copyright (C) 2008 Andy Walls <awalls@radix.net> 7 * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
8 * 8 *
9 * This program is free software; you can redistribute it and/or 9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License 10 * 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)
1021 return -EINVAL; 1021 return -EINVAL;
1022} 1022}
1023 1023
1024static int cx18_av_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) 1024static int cx18_av_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
1025{
1026 if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
1027 return -EINVAL;
1028 return cx18_av_g_sliced_fmt(sd, &fmt->fmt.sliced);
1029}
1030
1031static int cx18_av_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
1032{ 1025{
1033 struct cx18_av_state *state = to_cx18_av_state(sd); 1026 struct cx18_av_state *state = to_cx18_av_state(sd);
1034 struct cx18 *cx = v4l2_get_subdevdata(sd); 1027 struct cx18 *cx = v4l2_get_subdevdata(sd);
1035
1036 struct v4l2_pix_format *pix;
1037 int HSC, VSC, Vsrc, Hsrc, filter, Vlines; 1028 int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
1038 int is_50Hz = !(state->std & V4L2_STD_525_60); 1029 int is_50Hz = !(state->std & V4L2_STD_525_60);
1039 1030
1040 switch (fmt->type) { 1031 if (fmt->code != V4L2_MBUS_FMT_FIXED)
1041 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 1032 return -EINVAL;
1042 pix = &(fmt->fmt.pix);
1043 1033
1044 Vsrc = (cx18_av_read(cx, 0x476) & 0x3f) << 4; 1034 fmt->field = V4L2_FIELD_INTERLACED;
1045 Vsrc |= (cx18_av_read(cx, 0x475) & 0xf0) >> 4; 1035 fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
1046 1036
1047 Hsrc = (cx18_av_read(cx, 0x472) & 0x3f) << 4; 1037 Vsrc = (cx18_av_read(cx, 0x476) & 0x3f) << 4;
1048 Hsrc |= (cx18_av_read(cx, 0x471) & 0xf0) >> 4; 1038 Vsrc |= (cx18_av_read(cx, 0x475) & 0xf0) >> 4;
1049 1039
1050 /* 1040 Hsrc = (cx18_av_read(cx, 0x472) & 0x3f) << 4;
1051 * This adjustment reflects the excess of vactive, set in 1041 Hsrc |= (cx18_av_read(cx, 0x471) & 0xf0) >> 4;
1052 * cx18_av_std_setup(), above standard values:
1053 *
1054 * 480 + 1 for 60 Hz systems
1055 * 576 + 3 for 50 Hz systems
1056 */
1057 Vlines = pix->height + (is_50Hz ? 3 : 1);
1058
1059 /*
1060 * Invalid height and width scaling requests are:
1061 * 1. width less than 1/16 of the source width
1062 * 2. width greater than the source width
1063 * 3. height less than 1/8 of the source height
1064 * 4. height greater than the source height
1065 */
1066 if ((pix->width * 16 < Hsrc) || (Hsrc < pix->width) ||
1067 (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) {
1068 CX18_ERR_DEV(sd, "%dx%d is not a valid size!\n",
1069 pix->width, pix->height);
1070 return -ERANGE;
1071 }
1072 1042
1073 HSC = (Hsrc * (1 << 20)) / pix->width - (1 << 20); 1043 /*
1074 VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9)); 1044 * This adjustment reflects the excess of vactive, set in
1075 VSC &= 0x1fff; 1045 * cx18_av_std_setup(), above standard values:
1046 *
1047 * 480 + 1 for 60 Hz systems
1048 * 576 + 3 for 50 Hz systems
1049 */
1050 Vlines = fmt->height + (is_50Hz ? 3 : 1);
1076 1051
1077 if (pix->width >= 385) 1052 /*
1078 filter = 0; 1053 * Invalid height and width scaling requests are:
1079 else if (pix->width > 192) 1054 * 1. width less than 1/16 of the source width
1080 filter = 1; 1055 * 2. width greater than the source width
1081 else if (pix->width > 96) 1056 * 3. height less than 1/8 of the source height
1082 filter = 2; 1057 * 4. height greater than the source height
1083 else 1058 */
1084 filter = 3; 1059 if ((fmt->width * 16 < Hsrc) || (Hsrc < fmt->width) ||
1060 (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) {
1061 CX18_ERR_DEV(sd, "%dx%d is not a valid size!\n",
1062 fmt->width, fmt->height);
1063 return -ERANGE;
1064 }
1085 1065
1086 CX18_DEBUG_INFO_DEV(sd, 1066 HSC = (Hsrc * (1 << 20)) / fmt->width - (1 << 20);
1087 "decoder set size %dx%d -> scale %ux%u\n", 1067 VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9));
1088 pix->width, pix->height, HSC, VSC); 1068 VSC &= 0x1fff;
1089
1090 /* HSCALE=HSC */
1091 cx18_av_write(cx, 0x418, HSC & 0xff);
1092 cx18_av_write(cx, 0x419, (HSC >> 8) & 0xff);
1093 cx18_av_write(cx, 0x41a, HSC >> 16);
1094 /* VSCALE=VSC */
1095 cx18_av_write(cx, 0x41c, VSC & 0xff);
1096 cx18_av_write(cx, 0x41d, VSC >> 8);
1097 /* VS_INTRLACE=1 VFILT=filter */
1098 cx18_av_write(cx, 0x41e, 0x8 | filter);
1099 break;
1100 1069
1101 default: 1070 if (fmt->width >= 385)
1102 return -EINVAL; 1071 filter = 0;
1103 } 1072 else if (fmt->width > 192)
1073 filter = 1;
1074 else if (fmt->width > 96)
1075 filter = 2;
1076 else
1077 filter = 3;
1078
1079 CX18_DEBUG_INFO_DEV(sd,
1080 "decoder set size %dx%d -> scale %ux%u\n",
1081 fmt->width, fmt->height, HSC, VSC);
1082
1083 /* HSCALE=HSC */
1084 cx18_av_write(cx, 0x418, HSC & 0xff);
1085 cx18_av_write(cx, 0x419, (HSC >> 8) & 0xff);
1086 cx18_av_write(cx, 0x41a, HSC >> 16);
1087 /* VSCALE=VSC */
1088 cx18_av_write(cx, 0x41c, VSC & 0xff);
1089 cx18_av_write(cx, 0x41d, VSC >> 8);
1090 /* VS_INTRLACE=1 VFILT=filter */
1091 cx18_av_write(cx, 0x41e, 0x8 | filter);
1104 return 0; 1092 return 0;
1105} 1093}
1106 1094
@@ -1398,8 +1386,7 @@ static const struct v4l2_subdev_audio_ops cx18_av_audio_ops = {
1398static const struct v4l2_subdev_video_ops cx18_av_video_ops = { 1386static const struct v4l2_subdev_video_ops cx18_av_video_ops = {
1399 .s_routing = cx18_av_s_video_routing, 1387 .s_routing = cx18_av_s_video_routing,
1400 .s_stream = cx18_av_s_stream, 1388 .s_stream = cx18_av_s_stream,
1401 .g_fmt = cx18_av_g_fmt, 1389 .s_mbus_fmt = cx18_av_s_mbus_fmt,
1402 .s_fmt = cx18_av_s_fmt,
1403}; 1390};
1404 1391
1405static const struct v4l2_subdev_vbi_ops cx18_av_vbi_ops = { 1392static const struct v4l2_subdev_vbi_ops cx18_av_vbi_ops = {
diff --git a/drivers/media/video/cx18/cx18-av-core.h b/drivers/media/video/cx18/cx18-av-core.h
index c106967bdcc3..1956991795e3 100644
--- a/drivers/media/video/cx18/cx18-av-core.h
+++ b/drivers/media/video/cx18/cx18-av-core.h
@@ -4,7 +4,7 @@
4 * Derived from cx25840-core.h 4 * Derived from cx25840-core.h
5 * 5 *
6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> 6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
7 * Copyright (C) 2008 Andy Walls <awalls@radix.net> 7 * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
8 * 8 *
9 * This program is free software; you can redistribute it and/or 9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License 10 * modify it under the terms of the GNU General Public License
diff --git a/drivers/media/video/cx18/cx18-av-firmware.c b/drivers/media/video/cx18/cx18-av-firmware.c
index b9e8cc5d264a..280aa4d22488 100644
--- a/drivers/media/video/cx18/cx18-av-firmware.c
+++ b/drivers/media/video/cx18/cx18-av-firmware.c
@@ -2,7 +2,7 @@
2 * cx18 ADEC firmware functions 2 * cx18 ADEC firmware functions
3 * 3 *
4 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> 4 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
5 * Copyright (C) 2008 Andy Walls <awalls@radix.net> 5 * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
6 * 6 *
7 * This program is free software; you can redistribute it and/or 7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License 8 * modify it under the terms of the GNU General Public License
diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c
index 74e122b5fc49..6b805afe5d20 100644
--- a/drivers/media/video/cx18/cx18-cards.c
+++ b/drivers/media/video/cx18/cx18-cards.c
@@ -4,7 +4,7 @@
4 * Derived from ivtv-cards.c 4 * Derived from ivtv-cards.c
5 * 5 *
6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> 6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
7 * Copyright (C) 2008 Andy Walls <awalls@radix.net> 7 * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
8 * 8 *
9 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by 10 * it under the terms of the GNU General Public License as published by
diff --git a/drivers/media/video/cx18/cx18-cards.h b/drivers/media/video/cx18/cx18-cards.h
index 796e517300ac..3e750068f275 100644
--- a/drivers/media/video/cx18/cx18-cards.h
+++ b/drivers/media/video/cx18/cx18-cards.h
@@ -4,7 +4,7 @@
4 * Derived from ivtv-cards.c 4 * Derived from ivtv-cards.c
5 * 5 *
6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> 6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
7 * Copyright (C) 2008 Andy Walls <awalls@radix.net> 7 * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
8 * 8 *
9 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by 10 * it under the terms of the GNU General Public License as published by
diff --git a/drivers/media/video/cx18/cx18-controls.c b/drivers/media/video/cx18/cx18-controls.c
index 4b4b46544d5a..67043c7b452b 100644
--- a/drivers/media/video/cx18/cx18-controls.c
+++ b/drivers/media/video/cx18/cx18-controls.c
@@ -297,14 +297,13 @@ int cx18_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c)
297 if (p.video_encoding != cx->params.video_encoding) { 297 if (p.video_encoding != cx->params.video_encoding) {
298 int is_mpeg1 = p.video_encoding == 298 int is_mpeg1 = p.video_encoding ==
299 V4L2_MPEG_VIDEO_ENCODING_MPEG_1; 299 V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
300 struct v4l2_format fmt; 300 struct v4l2_mbus_framefmt fmt;
301 301
302 /* fix videodecoder resolution */ 302 /* fix videodecoder resolution */
303 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 303 fmt.width = cx->params.width / (is_mpeg1 ? 2 : 1);
304 fmt.fmt.pix.width = cx->params.width 304 fmt.height = cx->params.height;
305 / (is_mpeg1 ? 2 : 1); 305 fmt.code = V4L2_MBUS_FMT_FIXED;
306 fmt.fmt.pix.height = cx->params.height; 306 v4l2_subdev_call(cx->sd_av, video, s_mbus_fmt, &fmt);
307 v4l2_subdev_call(cx->sd_av, video, s_fmt, &fmt);
308 } 307 }
309 priv.cx = cx; 308 priv.cx = cx;
310 priv.s = &cx->streams[id->type]; 309 priv.s = &cx->streams[id->type];
diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c
index c95a86ba33b0..df60f27337cf 100644
--- a/drivers/media/video/cx18/cx18-driver.c
+++ b/drivers/media/video/cx18/cx18-driver.c
@@ -4,7 +4,7 @@
4 * Derived from ivtv-driver.c 4 * Derived from ivtv-driver.c
5 * 5 *
6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> 6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
7 * Copyright (C) 2008 Andy Walls <awalls@radix.net> 7 * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
8 * 8 *
9 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by 10 * it under the terms of the GNU General Public License as published by
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h
index b9728e8eee40..9bc51a99376b 100644
--- a/drivers/media/video/cx18/cx18-driver.h
+++ b/drivers/media/video/cx18/cx18-driver.h
@@ -4,7 +4,7 @@
4 * Derived from ivtv-driver.h 4 * Derived from ivtv-driver.h
5 * 5 *
6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> 6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
7 * Copyright (C) 2008 Andy Walls <awalls@radix.net> 7 * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
8 * 8 *
9 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by 10 * it under the terms of the GNU General Public License as published by
diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c
index 0ae2c2e1eab5..6d19f040d70f 100644
--- a/drivers/media/video/cx18/cx18-dvb.c
+++ b/drivers/media/video/cx18/cx18-dvb.c
@@ -2,7 +2,7 @@
2 * cx18 functions for DVB support 2 * cx18 functions for DVB support
3 * 3 *
4 * Copyright (c) 2008 Steven Toth <stoth@linuxtv.org> 4 * Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
5 * Copyright (C) 2008 Andy Walls <awalls@radix.net> 5 * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c
index e12a15020cda..9f23b90732f2 100644
--- a/drivers/media/video/cx18/cx18-fileops.c
+++ b/drivers/media/video/cx18/cx18-fileops.c
@@ -4,7 +4,7 @@
4 * Derived from ivtv-fileops.c 4 * Derived from ivtv-fileops.c
5 * 5 *
6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> 6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
7 * Copyright (C) 2008 Andy Walls <awalls@radix.net> 7 * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
8 * 8 *
9 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by 10 * it under the terms of the GNU General Public License as published by
diff --git a/drivers/media/video/cx18/cx18-firmware.c b/drivers/media/video/cx18/cx18-firmware.c
index 83cd559cc609..1b3fb502e6be 100644
--- a/drivers/media/video/cx18/cx18-firmware.c
+++ b/drivers/media/video/cx18/cx18-firmware.c
@@ -2,7 +2,7 @@
2 * cx18 firmware functions 2 * cx18 firmware functions
3 * 3 *
4 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> 4 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
5 * Copyright (C) 2008 Andy Walls <awalls@radix.net> 5 * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
diff --git a/drivers/media/video/cx18/cx18-gpio.c b/drivers/media/video/cx18/cx18-gpio.c
index 86a204b5448e..5374aeb0cd22 100644
--- a/drivers/media/video/cx18/cx18-gpio.c
+++ b/drivers/media/video/cx18/cx18-gpio.c
@@ -4,7 +4,7 @@
4 * Derived from ivtv-gpio.c 4 * Derived from ivtv-gpio.c
5 * 5 *
6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> 6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
7 * Copyright (C) 2008 Andy Walls <awalls@radix.net> 7 * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
8 * 8 *
9 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by 10 * it under the terms of the GNU General Public License as published by
diff --git a/drivers/media/video/cx18/cx18-gpio.h b/drivers/media/video/cx18/cx18-gpio.h
index f9a5ca3566af..4aea2ef88e8d 100644
--- a/drivers/media/video/cx18/cx18-gpio.h
+++ b/drivers/media/video/cx18/cx18-gpio.h
@@ -4,7 +4,7 @@
4 * Derived from ivtv-gpio.h 4 * Derived from ivtv-gpio.h
5 * 5 *
6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> 6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
7 * Copyright (C) 2008 Andy Walls <awalls@radix.net> 7 * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
8 * 8 *
9 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by 10 * it under the terms of the GNU General Public License as published by
diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c
index cfa1f289b0f5..809f7d37129c 100644
--- a/drivers/media/video/cx18/cx18-i2c.c
+++ b/drivers/media/video/cx18/cx18-i2c.c
@@ -4,7 +4,7 @@
4 * Derived from ivtv-i2c.c 4 * Derived from ivtv-i2c.c
5 * 5 *
6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> 6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
7 * Copyright (C) 2008 Andy Walls <awalls@radix.net> 7 * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
8 * 8 *
9 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by 10 * it under the terms of the GNU General Public License as published by
diff --git a/drivers/media/video/cx18/cx18-io.c b/drivers/media/video/cx18/cx18-io.c
index ec5b3d7bcc6b..49b9dbd06248 100644
--- a/drivers/media/video/cx18/cx18-io.c
+++ b/drivers/media/video/cx18/cx18-io.c
@@ -2,7 +2,7 @@
2 * cx18 driver PCI memory mapped IO access routines 2 * cx18 driver PCI memory mapped IO access routines
3 * 3 *
4 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> 4 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
5 * Copyright (C) 2008 Andy Walls <awalls@radix.net> 5 * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
diff --git a/drivers/media/video/cx18/cx18-io.h b/drivers/media/video/cx18/cx18-io.h
index 2635b3a8cc96..18974d886cf7 100644
--- a/drivers/media/video/cx18/cx18-io.h
+++ b/drivers/media/video/cx18/cx18-io.h
@@ -2,7 +2,7 @@
2 * cx18 driver PCI memory mapped IO access routines 2 * cx18 driver PCI memory mapped IO access routines
3 * 3 *
4 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> 4 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
5 * Copyright (C) 2008 Andy Walls <awalls@radix.net> 5 * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
@@ -28,7 +28,7 @@
28/* 28/*
29 * Readback and retry of MMIO access for reliability: 29 * Readback and retry of MMIO access for reliability:
30 * The concept was suggested by Steve Toth <stoth@linuxtv.org>. 30 * The concept was suggested by Steve Toth <stoth@linuxtv.org>.
31 * The implmentation is the fault of Andy Walls <awalls@radix.net>. 31 * The implmentation is the fault of Andy Walls <awalls@md.metrocast.net>.
32 * 32 *
33 * *write* functions are implied to retry the mmio unless suffixed with _noretry 33 * *write* functions are implied to retry the mmio unless suffixed with _noretry
34 * *read* functions never retry the mmio (it never helps to do so) 34 * *read* functions never retry the mmio (it never helps to do so)
diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c
index 2530fc54daaf..20eaf38ba959 100644
--- a/drivers/media/video/cx18/cx18-ioctl.c
+++ b/drivers/media/video/cx18/cx18-ioctl.c
@@ -4,7 +4,7 @@
4 * Derived from ivtv-ioctl.c 4 * Derived from ivtv-ioctl.c
5 * 5 *
6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> 6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
7 * Copyright (C) 2008 Andy Walls <awalls@radix.net> 7 * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
8 * 8 *
9 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by 10 * 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,
274{ 274{
275 struct cx18_open_id *id = fh; 275 struct cx18_open_id *id = fh;
276 struct cx18 *cx = id->cx; 276 struct cx18 *cx = id->cx;
277 struct v4l2_mbus_framefmt mbus_fmt;
277 int ret; 278 int ret;
278 int w, h; 279 int w, h;
279 280
@@ -293,9 +294,10 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh,
293 if (atomic_read(&cx->ana_capturing) > 0) 294 if (atomic_read(&cx->ana_capturing) > 0)
294 return -EBUSY; 295 return -EBUSY;
295 296
296 cx->params.width = w; 297 mbus_fmt.width = cx->params.width = w;
297 cx->params.height = h; 298 mbus_fmt.height = cx->params.height = h;
298 v4l2_subdev_call(cx->sd_av, video, s_fmt, fmt); 299 mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
300 v4l2_subdev_call(cx->sd_av, video, s_mbus_fmt, &mbus_fmt);
299 return cx18_g_fmt_vid_cap(file, fh, fmt); 301 return cx18_g_fmt_vid_cap(file, fh, fmt);
300} 302}
301 303
diff --git a/drivers/media/video/cx18/cx18-ioctl.h b/drivers/media/video/cx18/cx18-ioctl.h
index e2ca0d152116..dcb2559ad520 100644
--- a/drivers/media/video/cx18/cx18-ioctl.h
+++ b/drivers/media/video/cx18/cx18-ioctl.h
@@ -4,7 +4,7 @@
4 * Derived from ivtv-ioctl.h 4 * Derived from ivtv-ioctl.h
5 * 5 *
6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> 6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
7 * Copyright (C) 2008 Andy Walls <awalls@radix.net> 7 * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
8 * 8 *
9 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by 10 * it under the terms of the GNU General Public License as published by
diff --git a/drivers/media/video/cx18/cx18-irq.c b/drivers/media/video/cx18/cx18-irq.c
index af2f504eda2b..80edfe93a3d8 100644
--- a/drivers/media/video/cx18/cx18-irq.c
+++ b/drivers/media/video/cx18/cx18-irq.c
@@ -2,7 +2,7 @@
2 * cx18 interrupt handling 2 * cx18 interrupt handling
3 * 3 *
4 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> 4 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
5 * Copyright (C) 2008 Andy Walls <awalls@radix.net> 5 * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
diff --git a/drivers/media/video/cx18/cx18-irq.h b/drivers/media/video/cx18/cx18-irq.h
index 91f0b5278ef9..30e7eaf8cb55 100644
--- a/drivers/media/video/cx18/cx18-irq.h
+++ b/drivers/media/video/cx18/cx18-irq.h
@@ -2,7 +2,7 @@
2 * cx18 interrupt handling 2 * cx18 interrupt handling
3 * 3 *
4 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> 4 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
5 * Copyright (C) 2008 Andy Walls <awalls@radix.net> 5 * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c
index 6dcce297752f..956aa190ecca 100644
--- a/drivers/media/video/cx18/cx18-mailbox.c
+++ b/drivers/media/video/cx18/cx18-mailbox.c
@@ -2,7 +2,7 @@
2 * cx18 mailbox functions 2 * cx18 mailbox functions
3 * 3 *
4 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> 4 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
5 * Copyright (C) 2008 Andy Walls <awalls@radix.net> 5 * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
diff --git a/drivers/media/video/cx18/cx18-mailbox.h b/drivers/media/video/cx18/cx18-mailbox.h
index 33a3491c4537..077952fcbcca 100644
--- a/drivers/media/video/cx18/cx18-mailbox.h
+++ b/drivers/media/video/cx18/cx18-mailbox.h
@@ -2,7 +2,7 @@
2 * cx18 mailbox functions 2 * cx18 mailbox functions
3 * 3 *
4 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> 4 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
5 * Copyright (C) 2008 Andy Walls <awalls@radix.net> 5 * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c
index aefc8c8cf3c1..8884537bd62f 100644
--- a/drivers/media/video/cx18/cx18-queue.c
+++ b/drivers/media/video/cx18/cx18-queue.c
@@ -4,7 +4,7 @@
4 * Derived from ivtv-queue.c 4 * Derived from ivtv-queue.c
5 * 5 *
6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> 6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
7 * Copyright (C) 2008 Andy Walls <awalls@radix.net> 7 * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
8 * 8 *
9 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by 10 * it under the terms of the GNU General Public License as published by
diff --git a/drivers/media/video/cx18/cx18-queue.h b/drivers/media/video/cx18/cx18-queue.h
index 88a6d34ad3bb..4201ddc16091 100644
--- a/drivers/media/video/cx18/cx18-queue.h
+++ b/drivers/media/video/cx18/cx18-queue.h
@@ -4,7 +4,7 @@
4 * Derived from ivtv-queue.h 4 * Derived from ivtv-queue.h
5 * 5 *
6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> 6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
7 * Copyright (C) 2008 Andy Walls <awalls@radix.net> 7 * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
8 * 8 *
9 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by 10 * it under the terms of the GNU General Public License as published by
diff --git a/drivers/media/video/cx18/cx18-scb.c b/drivers/media/video/cx18/cx18-scb.c
index 34b4d03c55cd..85cc59637e54 100644
--- a/drivers/media/video/cx18/cx18-scb.c
+++ b/drivers/media/video/cx18/cx18-scb.c
@@ -2,7 +2,7 @@
2 * cx18 System Control Block initialization 2 * cx18 System Control Block initialization
3 * 3 *
4 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> 4 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
5 * Copyright (C) 2008 Andy Walls <awalls@radix.net> 5 * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
diff --git a/drivers/media/video/cx18/cx18-scb.h b/drivers/media/video/cx18/cx18-scb.h
index 368f23d08709..08877652e321 100644
--- a/drivers/media/video/cx18/cx18-scb.h
+++ b/drivers/media/video/cx18/cx18-scb.h
@@ -2,7 +2,7 @@
2 * cx18 System Control Block initialization 2 * cx18 System Control Block initialization
3 * 3 *
4 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> 4 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
5 * Copyright (C) 2008 Andy Walls <awalls@radix.net> 5 * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c
index f5c91261b2db..9045f1ece0eb 100644
--- a/drivers/media/video/cx18/cx18-streams.c
+++ b/drivers/media/video/cx18/cx18-streams.c
@@ -4,7 +4,7 @@
4 * Derived from ivtv-streams.c 4 * Derived from ivtv-streams.c
5 * 5 *
6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> 6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
7 * Copyright (C) 2008 Andy Walls <awalls@radix.net> 7 * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
8 * 8 *
9 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by 10 * it under the terms of the GNU General Public License as published by
diff --git a/drivers/media/video/cx18/cx18-streams.h b/drivers/media/video/cx18/cx18-streams.h
index 0bff0fa29763..77412bee5963 100644
--- a/drivers/media/video/cx18/cx18-streams.h
+++ b/drivers/media/video/cx18/cx18-streams.h
@@ -4,7 +4,7 @@
4 * Derived from ivtv-streams.h 4 * Derived from ivtv-streams.h
5 * 5 *
6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> 6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
7 * Copyright (C) 2008 Andy Walls <awalls@radix.net> 7 * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
8 * 8 *
9 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by 10 * it under the terms of the GNU General Public License as published by
diff --git a/drivers/media/video/cx231xx/cx231xx-video.c b/drivers/media/video/cx231xx/cx231xx-video.c
index 2782709b263f..e76014561aa7 100644
--- a/drivers/media/video/cx231xx/cx231xx-video.c
+++ b/drivers/media/video/cx231xx/cx231xx-video.c
@@ -993,6 +993,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
993 struct cx231xx *dev = fh->dev; 993 struct cx231xx *dev = fh->dev;
994 int rc; 994 int rc;
995 struct cx231xx_fmt *fmt; 995 struct cx231xx_fmt *fmt;
996 struct v4l2_mbus_framefmt mbus_fmt;
996 997
997 rc = check_dev(dev); 998 rc = check_dev(dev);
998 if (rc < 0) 999 if (rc < 0)
@@ -1026,7 +1027,9 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
1026 dev->format = fmt; 1027 dev->format = fmt;
1027 get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); 1028 get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
1028 1029
1029 call_all(dev, video, s_fmt, f); 1030 v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
1031 call_all(dev, video, s_mbus_fmt, &mbus_fmt);
1032 v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
1030 1033
1031 /* Set the correct alternate setting for this resolution */ 1034 /* Set the correct alternate setting for this resolution */
1032 cx231xx_resolution_set(dev); 1035 cx231xx_resolution_set(dev);
diff --git a/drivers/media/video/cx2341x.c b/drivers/media/video/cx2341x.c
index 022b480918cd..2bf44ef10fec 100644
--- a/drivers/media/video/cx2341x.c
+++ b/drivers/media/video/cx2341x.c
@@ -1113,7 +1113,6 @@ invalid:
1113void cx2341x_log_status(const struct cx2341x_mpeg_params *p, const char *prefix) 1113void cx2341x_log_status(const struct cx2341x_mpeg_params *p, const char *prefix)
1114{ 1114{
1115 int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1; 1115 int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
1116 int temporal = p->video_temporal_filter;
1117 1116
1118 /* Stream */ 1117 /* Stream */
1119 printk(KERN_INFO "%s: Stream: %s", 1118 printk(KERN_INFO "%s: Stream: %s",
@@ -1179,14 +1178,11 @@ void cx2341x_log_status(const struct cx2341x_mpeg_params *p, const char *prefix)
1179 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE), 1178 V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE),
1180 p->video_spatial_filter); 1179 p->video_spatial_filter);
1181 1180
1182 if (p->width != 720 || p->height != (p->is_50hz ? 576 : 480))
1183 temporal = 0;
1184
1185 printk(KERN_INFO "%s: Temporal Filter: %s, %d\n", 1181 printk(KERN_INFO "%s: Temporal Filter: %s, %d\n",
1186 prefix, 1182 prefix,
1187 cx2341x_menu_item(p, 1183 cx2341x_menu_item(p,
1188 V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE), 1184 V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE),
1189 temporal); 1185 p->video_temporal_filter);
1190 printk(KERN_INFO 1186 printk(KERN_INFO
1191 "%s: Median Filter: %s, Luma [%d, %d], Chroma [%d, %d]\n", 1187 "%s: Median Filter: %s, Luma [%d, %d], Chroma [%d, %d]\n",
1192 prefix, 1188 prefix,
diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c
index 9e1460828b2f..0a199d774d9b 100644
--- a/drivers/media/video/cx23885/cx23885-dvb.c
+++ b/drivers/media/video/cx23885/cx23885-dvb.c
@@ -991,6 +991,8 @@ static int dvb_register(struct cx23885_tsport *port)
991 ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port, 991 ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port,
992 &dev->pci->dev, adapter_nr, 0, 992 &dev->pci->dev, adapter_nr, 0,
993 cx23885_dvb_fe_ioctl_override); 993 cx23885_dvb_fe_ioctl_override);
994 if (!ret)
995 return ret;
994 996
995 /* init CI & MAC */ 997 /* init CI & MAC */
996 switch (dev->board) { 998 switch (dev->board) {
diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c
index 4172cb387420..d4746e064516 100644
--- a/drivers/media/video/cx23885/cx23885-i2c.c
+++ b/drivers/media/video/cx23885/cx23885-i2c.c
@@ -365,7 +365,17 @@ int cx23885_i2c_register(struct cx23885_i2c *bus)
365 365
366 memset(&info, 0, sizeof(struct i2c_board_info)); 366 memset(&info, 0, sizeof(struct i2c_board_info));
367 strlcpy(info.type, "ir_video", I2C_NAME_SIZE); 367 strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
368 i2c_new_probed_device(&bus->i2c_adap, &info, addr_list); 368 /*
369 * We can't call i2c_new_probed_device() because it uses
370 * quick writes for probing and the IR receiver device only
371 * replies to reads.
372 */
373 if (i2c_smbus_xfer(&bus->i2c_adap, addr_list[0], 0,
374 I2C_SMBUS_READ, 0, I2C_SMBUS_QUICK,
375 NULL) >= 0) {
376 info.addr = addr_list[0];
377 i2c_new_device(&bus->i2c_adap, &info);
378 }
369 } 379 }
370 380
371 return bus->i2c_rc; 381 return bus->i2c_rc;
diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c
index 8d306d8bb61c..5de6ba98f7a8 100644
--- a/drivers/media/video/cx23885/cx23885-input.c
+++ b/drivers/media/video/cx23885/cx23885-input.c
@@ -5,7 +5,7 @@
5 * 5 *
6 * Most of this file is 6 * Most of this file is
7 * 7 *
8 * Copyright (C) 2009 Andy Walls <awalls@radix.net> 8 * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net>
9 * 9 *
10 * However, the cx23885_input_{init,fini} functions contained herein are 10 * However, the cx23885_input_{init,fini} functions contained herein are
11 * derived from Linux kernel files linux/media/video/.../...-input.c marked as: 11 * derived from Linux kernel files linux/media/video/.../...-input.c marked as:
diff --git a/drivers/media/video/cx23885/cx23885-input.h b/drivers/media/video/cx23885/cx23885-input.h
index 3572cb1ecfc2..75ef15d3f523 100644
--- a/drivers/media/video/cx23885/cx23885-input.h
+++ b/drivers/media/video/cx23885/cx23885-input.h
@@ -3,7 +3,7 @@
3 * 3 *
4 * Infrared remote control input device 4 * Infrared remote control input device
5 * 5 *
6 * Copyright (C) 2009 Andy Walls <awalls@radix.net> 6 * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net>
7 * 7 *
8 * This program is free software; you can redistribute it and/or 8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License 9 * modify it under the terms of the GNU General Public License
diff --git a/drivers/media/video/cx23885/cx23885-ioctl.c b/drivers/media/video/cx23885/cx23885-ioctl.c
index dfb4627fb340..44812ca78899 100644
--- a/drivers/media/video/cx23885/cx23885-ioctl.c
+++ b/drivers/media/video/cx23885/cx23885-ioctl.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Various common ioctl() support functions 4 * Various common ioctl() support functions
5 * 5 *
6 * Copyright (c) 2009 Andy Walls <awalls@radix.net> 6 * Copyright (c) 2009 Andy Walls <awalls@md.metrocast.net>
7 * 7 *
8 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License as published by
diff --git a/drivers/media/video/cx23885/cx23885-ioctl.h b/drivers/media/video/cx23885/cx23885-ioctl.h
index 80b0f4923c6a..315be0ca5a04 100644
--- a/drivers/media/video/cx23885/cx23885-ioctl.h
+++ b/drivers/media/video/cx23885/cx23885-ioctl.h
@@ -3,7 +3,7 @@
3 * 3 *
4 * Various common ioctl() support functions 4 * Various common ioctl() support functions
5 * 5 *
6 * Copyright (c) 2009 Andy Walls <awalls@radix.net> 6 * Copyright (c) 2009 Andy Walls <awalls@md.metrocast.net>
7 * 7 *
8 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License as published by
diff --git a/drivers/media/video/cx23885/cx23885-ir.c b/drivers/media/video/cx23885/cx23885-ir.c
index 6ae982cc9856..9a677eb080af 100644
--- a/drivers/media/video/cx23885/cx23885-ir.c
+++ b/drivers/media/video/cx23885/cx23885-ir.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Infrared device support routines - non-input, non-vl42_subdev routines 4 * Infrared device support routines - non-input, non-vl42_subdev routines
5 * 5 *
6 * Copyright (C) 2009 Andy Walls <awalls@radix.net> 6 * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net>
7 * 7 *
8 * This program is free software; you can redistribute it and/or 8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License 9 * modify it under the terms of the GNU General Public License
diff --git a/drivers/media/video/cx23885/cx23885-ir.h b/drivers/media/video/cx23885/cx23885-ir.h
index 9b8a6d5d1ef6..0c9d8bda9e28 100644
--- a/drivers/media/video/cx23885/cx23885-ir.h
+++ b/drivers/media/video/cx23885/cx23885-ir.h
@@ -3,7 +3,7 @@
3 * 3 *
4 * Infrared device support routines - non-input, non-vl42_subdev routines 4 * Infrared device support routines - non-input, non-vl42_subdev routines
5 * 5 *
6 * Copyright (C) 2009 Andy Walls <awalls@radix.net> 6 * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net>
7 * 7 *
8 * This program is free software; you can redistribute it and/or 8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License 9 * modify it under the terms of the GNU General Public License
diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c
index 543b854f6a62..4e44dcda3875 100644
--- a/drivers/media/video/cx23885/cx23885-video.c
+++ b/drivers/media/video/cx23885/cx23885-video.c
@@ -976,6 +976,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
976{ 976{
977 struct cx23885_fh *fh = priv; 977 struct cx23885_fh *fh = priv;
978 struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; 978 struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
979 struct v4l2_mbus_framefmt mbus_fmt;
979 int err; 980 int err;
980 981
981 dprintk(2, "%s()\n", __func__); 982 dprintk(2, "%s()\n", __func__);
@@ -989,7 +990,9 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
989 fh->vidq.field = f->fmt.pix.field; 990 fh->vidq.field = f->fmt.pix.field;
990 dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, 991 dprintk(2, "%s() width=%d height=%d field=%d\n", __func__,
991 fh->width, fh->height, fh->vidq.field); 992 fh->width, fh->height, fh->vidq.field);
992 call_all(dev, video, s_fmt, f); 993 v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
994 call_all(dev, video, s_mbus_fmt, &mbus_fmt);
995 v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
993 return 0; 996 return 0;
994} 997}
995 998
diff --git a/drivers/media/video/cx23885/cx23888-ir.c b/drivers/media/video/cx23885/cx23888-ir.c
index ad728d767d69..f63d378257a7 100644
--- a/drivers/media/video/cx23885/cx23888-ir.c
+++ b/drivers/media/video/cx23885/cx23888-ir.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * CX23888 Integrated Consumer Infrared Controller 4 * CX23888 Integrated Consumer Infrared Controller
5 * 5 *
6 * Copyright (C) 2009 Andy Walls <awalls@radix.net> 6 * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net>
7 * 7 *
8 * This program is free software; you can redistribute it and/or 8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License 9 * modify it under the terms of the GNU General Public License
diff --git a/drivers/media/video/cx23885/cx23888-ir.h b/drivers/media/video/cx23885/cx23888-ir.h
index 3d446f9eb94b..d2de41caaf1d 100644
--- a/drivers/media/video/cx23885/cx23888-ir.h
+++ b/drivers/media/video/cx23885/cx23888-ir.h
@@ -3,7 +3,7 @@
3 * 3 *
4 * CX23888 Integrated Consumer Infrared Controller 4 * CX23888 Integrated Consumer Infrared Controller
5 * 5 *
6 * Copyright (C) 2009 Andy Walls <awalls@radix.net> 6 * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net>
7 * 7 *
8 * This program is free software; you can redistribute it and/or 8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License 9 * modify it under the terms of the GNU General Public License
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index 8b6fb3544376..bb4872b2ceb0 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -1014,75 +1014,59 @@ static int cx25840_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
1014 1014
1015/* ----------------------------------------------------------------------- */ 1015/* ----------------------------------------------------------------------- */
1016 1016
1017static int cx25840_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) 1017static int cx25840_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
1018{
1019 switch (fmt->type) {
1020 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
1021 return cx25840_g_sliced_fmt(sd, &fmt->fmt.sliced);
1022 default:
1023 return -EINVAL;
1024 }
1025 return 0;
1026}
1027
1028static int cx25840_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
1029{ 1018{
1030 struct cx25840_state *state = to_state(sd); 1019 struct cx25840_state *state = to_state(sd);
1031 struct i2c_client *client = v4l2_get_subdevdata(sd); 1020 struct i2c_client *client = v4l2_get_subdevdata(sd);
1032 struct v4l2_pix_format *pix;
1033 int HSC, VSC, Vsrc, Hsrc, filter, Vlines; 1021 int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
1034 int is_50Hz = !(state->std & V4L2_STD_525_60); 1022 int is_50Hz = !(state->std & V4L2_STD_525_60);
1035 1023
1036 switch (fmt->type) { 1024 if (fmt->code != V4L2_MBUS_FMT_FIXED)
1037 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 1025 return -EINVAL;
1038 pix = &(fmt->fmt.pix);
1039
1040 Vsrc = (cx25840_read(client, 0x476) & 0x3f) << 4;
1041 Vsrc |= (cx25840_read(client, 0x475) & 0xf0) >> 4;
1042
1043 Hsrc = (cx25840_read(client, 0x472) & 0x3f) << 4;
1044 Hsrc |= (cx25840_read(client, 0x471) & 0xf0) >> 4;
1045 1026
1046 Vlines = pix->height + (is_50Hz ? 4 : 7); 1027 fmt->field = V4L2_FIELD_INTERLACED;
1028 fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
1047 1029
1048 if ((pix->width * 16 < Hsrc) || (Hsrc < pix->width) || 1030 Vsrc = (cx25840_read(client, 0x476) & 0x3f) << 4;
1049 (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) { 1031 Vsrc |= (cx25840_read(client, 0x475) & 0xf0) >> 4;
1050 v4l_err(client, "%dx%d is not a valid size!\n",
1051 pix->width, pix->height);
1052 return -ERANGE;
1053 }
1054 1032
1055 HSC = (Hsrc * (1 << 20)) / pix->width - (1 << 20); 1033 Hsrc = (cx25840_read(client, 0x472) & 0x3f) << 4;
1056 VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9)); 1034 Hsrc |= (cx25840_read(client, 0x471) & 0xf0) >> 4;
1057 VSC &= 0x1fff;
1058 1035
1059 if (pix->width >= 385) 1036 Vlines = fmt->height + (is_50Hz ? 4 : 7);
1060 filter = 0;
1061 else if (pix->width > 192)
1062 filter = 1;
1063 else if (pix->width > 96)
1064 filter = 2;
1065 else
1066 filter = 3;
1067
1068 v4l_dbg(1, cx25840_debug, client, "decoder set size %dx%d -> scale %ux%u\n",
1069 pix->width, pix->height, HSC, VSC);
1070
1071 /* HSCALE=HSC */
1072 cx25840_write(client, 0x418, HSC & 0xff);
1073 cx25840_write(client, 0x419, (HSC >> 8) & 0xff);
1074 cx25840_write(client, 0x41a, HSC >> 16);
1075 /* VSCALE=VSC */
1076 cx25840_write(client, 0x41c, VSC & 0xff);
1077 cx25840_write(client, 0x41d, VSC >> 8);
1078 /* VS_INTRLACE=1 VFILT=filter */
1079 cx25840_write(client, 0x41e, 0x8 | filter);
1080 break;
1081 1037
1082 default: 1038 if ((fmt->width * 16 < Hsrc) || (Hsrc < fmt->width) ||
1083 return -EINVAL; 1039 (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) {
1040 v4l_err(client, "%dx%d is not a valid size!\n",
1041 fmt->width, fmt->height);
1042 return -ERANGE;
1084 } 1043 }
1085 1044
1045 HSC = (Hsrc * (1 << 20)) / fmt->width - (1 << 20);
1046 VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9));
1047 VSC &= 0x1fff;
1048
1049 if (fmt->width >= 385)
1050 filter = 0;
1051 else if (fmt->width > 192)
1052 filter = 1;
1053 else if (fmt->width > 96)
1054 filter = 2;
1055 else
1056 filter = 3;
1057
1058 v4l_dbg(1, cx25840_debug, client, "decoder set size %dx%d -> scale %ux%u\n",
1059 fmt->width, fmt->height, HSC, VSC);
1060
1061 /* HSCALE=HSC */
1062 cx25840_write(client, 0x418, HSC & 0xff);
1063 cx25840_write(client, 0x419, (HSC >> 8) & 0xff);
1064 cx25840_write(client, 0x41a, HSC >> 16);
1065 /* VSCALE=VSC */
1066 cx25840_write(client, 0x41c, VSC & 0xff);
1067 cx25840_write(client, 0x41d, VSC >> 8);
1068 /* VS_INTRLACE=1 VFILT=filter */
1069 cx25840_write(client, 0x41e, 0x8 | filter);
1086 return 0; 1070 return 0;
1087} 1071}
1088 1072
@@ -1627,8 +1611,7 @@ static const struct v4l2_subdev_audio_ops cx25840_audio_ops = {
1627 1611
1628static const struct v4l2_subdev_video_ops cx25840_video_ops = { 1612static const struct v4l2_subdev_video_ops cx25840_video_ops = {
1629 .s_routing = cx25840_s_video_routing, 1613 .s_routing = cx25840_s_video_routing,
1630 .g_fmt = cx25840_g_fmt, 1614 .s_mbus_fmt = cx25840_s_mbus_fmt,
1631 .s_fmt = cx25840_s_fmt,
1632 .s_stream = cx25840_s_stream, 1615 .s_stream = cx25840_s_stream,
1633}; 1616};
1634 1617
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c
index ee1ca39db06a..fb39f1184558 100644
--- a/drivers/media/video/cx88/cx88-i2c.c
+++ b/drivers/media/video/cx88/cx88-i2c.c
@@ -188,10 +188,24 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci)
188 0x18, 0x6b, 0x71, 188 0x18, 0x6b, 0x71,
189 I2C_CLIENT_END 189 I2C_CLIENT_END
190 }; 190 };
191 const unsigned short *addrp;
191 192
192 memset(&info, 0, sizeof(struct i2c_board_info)); 193 memset(&info, 0, sizeof(struct i2c_board_info));
193 strlcpy(info.type, "ir_video", I2C_NAME_SIZE); 194 strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
194 i2c_new_probed_device(&core->i2c_adap, &info, addr_list); 195 /*
196 * We can't call i2c_new_probed_device() because it uses
197 * quick writes for probing and at least some R receiver
198 * devices only reply to reads.
199 */
200 for (addrp = addr_list; *addrp != I2C_CLIENT_END; addrp++) {
201 if (i2c_smbus_xfer(&core->i2c_adap, *addrp, 0,
202 I2C_SMBUS_READ, 0,
203 I2C_SMBUS_QUICK, NULL) >= 0) {
204 info.addr = *addrp;
205 i2c_new_device(&core->i2c_adap, &info);
206 break;
207 }
208 }
195 } 209 }
196 return core->i2c_rc; 210 return core->i2c_rc;
197} 211}
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c
index 331e1cac4272..44c63cbd6dda 100644
--- a/drivers/media/video/em28xx/em28xx-core.c
+++ b/drivers/media/video/em28xx/em28xx-core.c
@@ -1186,8 +1186,7 @@ int em28xx_register_extension(struct em28xx_ops *ops)
1186 mutex_lock(&em28xx_devlist_mutex); 1186 mutex_lock(&em28xx_devlist_mutex);
1187 list_add_tail(&ops->next, &em28xx_extension_devlist); 1187 list_add_tail(&ops->next, &em28xx_extension_devlist);
1188 list_for_each_entry(dev, &em28xx_devlist, devlist) { 1188 list_for_each_entry(dev, &em28xx_devlist, devlist) {
1189 if (dev) 1189 ops->init(dev);
1190 ops->init(dev);
1191 } 1190 }
1192 printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name); 1191 printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name);
1193 mutex_unlock(&em28xx_devlist_mutex); 1192 mutex_unlock(&em28xx_devlist_mutex);
@@ -1201,10 +1200,8 @@ void em28xx_unregister_extension(struct em28xx_ops *ops)
1201 1200
1202 mutex_lock(&em28xx_devlist_mutex); 1201 mutex_lock(&em28xx_devlist_mutex);
1203 list_for_each_entry(dev, &em28xx_devlist, devlist) { 1202 list_for_each_entry(dev, &em28xx_devlist, devlist) {
1204 if (dev) 1203 ops->fini(dev);
1205 ops->fini(dev);
1206 } 1204 }
1207
1208 printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name); 1205 printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name);
1209 list_del(&ops->next); 1206 list_del(&ops->next);
1210 mutex_unlock(&em28xx_devlist_mutex); 1207 mutex_unlock(&em28xx_devlist_mutex);
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c
index 785eeb4c2014..95354a339e3d 100644
--- a/drivers/media/video/gspca/sonixb.c
+++ b/drivers/media/video/gspca/sonixb.c
@@ -1453,9 +1453,7 @@ static const struct usb_device_id device_table[] __devinitconst = {
1453 {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)}, 1453 {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)},
1454 {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)}, 1454 {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)},
1455 {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)}, 1455 {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)},
1456#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1457 {USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)}, 1456 {USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)},
1458#endif
1459 {USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)}, 1457 {USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)},
1460#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE 1458#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1461 {USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)}, 1459 {USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)},
diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c
index bb923efb75bd..176c5b3d5e6f 100644
--- a/drivers/media/video/gspca/sonixj.c
+++ b/drivers/media/video/gspca/sonixj.c
@@ -3022,16 +3022,18 @@ static const __devinitdata struct usb_device_id device_table[] = {
3022/* {USB_DEVICE(0x0c45, 0x60c2), BS(SN9C105, P1030xC)}, */ 3022/* {USB_DEVICE(0x0c45, 0x60c2), BS(SN9C105, P1030xC)}, */
3023/* {USB_DEVICE(0x0c45, 0x60c8), BS(SN9C105, OM6802)}, */ 3023/* {USB_DEVICE(0x0c45, 0x60c8), BS(SN9C105, OM6802)}, */
3024/* {USB_DEVICE(0x0c45, 0x60cc), BS(SN9C105, HV7131GP)}, */ 3024/* {USB_DEVICE(0x0c45, 0x60cc), BS(SN9C105, HV7131GP)}, */
3025 {USB_DEVICE(0x0c45, 0x60ce), BS(SN9C105, SP80708)},
3025 {USB_DEVICE(0x0c45, 0x60ec), BS(SN9C105, MO4000)}, 3026 {USB_DEVICE(0x0c45, 0x60ec), BS(SN9C105, MO4000)},
3026/* {USB_DEVICE(0x0c45, 0x60ef), BS(SN9C105, ICM105C)}, */ 3027/* {USB_DEVICE(0x0c45, 0x60ef), BS(SN9C105, ICM105C)}, */
3027/* {USB_DEVICE(0x0c45, 0x60fa), BS(SN9C105, OV7648)}, */ 3028/* {USB_DEVICE(0x0c45, 0x60fa), BS(SN9C105, OV7648)}, */
3029/* {USB_DEVICE(0x0c45, 0x60f2), BS(SN9C105, OV7660)}, */
3028 {USB_DEVICE(0x0c45, 0x60fb), BS(SN9C105, OV7660)}, 3030 {USB_DEVICE(0x0c45, 0x60fb), BS(SN9C105, OV7660)},
3029#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE 3031#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
3030 {USB_DEVICE(0x0c45, 0x60fc), BS(SN9C105, HV7131R)}, 3032 {USB_DEVICE(0x0c45, 0x60fc), BS(SN9C105, HV7131R)},
3031 {USB_DEVICE(0x0c45, 0x60fe), BS(SN9C105, OV7630)}, 3033 {USB_DEVICE(0x0c45, 0x60fe), BS(SN9C105, OV7630)},
3032#endif 3034#endif
3033 {USB_DEVICE(0x0c45, 0x6100), BS(SN9C120, MI0360)}, /*sn9c128*/ 3035 {USB_DEVICE(0x0c45, 0x6100), BS(SN9C120, MI0360)}, /*sn9c128*/
3034/* {USB_DEVICE(0x0c45, 0x6102), BS(SN9C120, P1030xC)}, */ 3036/* {USB_DEVICE(0x0c45, 0x6102), BS(SN9C120, PO2030N)}, * / GC0305*/
3035/* {USB_DEVICE(0x0c45, 0x6108), BS(SN9C120, OM6802)}, */ 3037/* {USB_DEVICE(0x0c45, 0x6108), BS(SN9C120, OM6802)}, */
3036 {USB_DEVICE(0x0c45, 0x610a), BS(SN9C120, OV7648)}, /*sn9c128*/ 3038 {USB_DEVICE(0x0c45, 0x610a), BS(SN9C120, OV7648)}, /*sn9c128*/
3037 {USB_DEVICE(0x0c45, 0x610b), BS(SN9C120, OV7660)}, /*sn9c128*/ 3039 {USB_DEVICE(0x0c45, 0x610b), BS(SN9C120, OV7660)}, /*sn9c128*/
@@ -3058,6 +3060,7 @@ static const __devinitdata struct usb_device_id device_table[] = {
3058 {USB_DEVICE(0x0c45, 0x613c), BS(SN9C120, HV7131R)}, 3060 {USB_DEVICE(0x0c45, 0x613c), BS(SN9C120, HV7131R)},
3059 {USB_DEVICE(0x0c45, 0x613e), BS(SN9C120, OV7630)}, 3061 {USB_DEVICE(0x0c45, 0x613e), BS(SN9C120, OV7630)},
3060 {USB_DEVICE(0x0c45, 0x6142), BS(SN9C120, PO2030N)}, /*sn9c120b*/ 3062 {USB_DEVICE(0x0c45, 0x6142), BS(SN9C120, PO2030N)}, /*sn9c120b*/
3063 /* or GC0305 / GC0307 */
3061 {USB_DEVICE(0x0c45, 0x6143), BS(SN9C120, SP80708)}, /*sn9c120b*/ 3064 {USB_DEVICE(0x0c45, 0x6143), BS(SN9C120, SP80708)}, /*sn9c120b*/
3062 {USB_DEVICE(0x0c45, 0x6148), BS(SN9C120, OM6802)}, /*sn9c120b*/ 3065 {USB_DEVICE(0x0c45, 0x6148), BS(SN9C120, OM6802)}, /*sn9c120b*/
3063 {USB_DEVICE(0x0c45, 0x614a), BS(SN9C120, ADCM1700)}, /*sn9c120b*/ 3066 {USB_DEVICE(0x0c45, 0x614a), BS(SN9C120, ADCM1700)}, /*sn9c120b*/
diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/video/hdpvr/hdpvr-video.c
index 7cfccfd1b870..c338f3f62e77 100644
--- a/drivers/media/video/hdpvr/hdpvr-video.c
+++ b/drivers/media/video/hdpvr/hdpvr-video.c
@@ -366,7 +366,7 @@ static int hdpvr_open(struct file *file)
366 366
367 dev = (struct hdpvr_device *)video_get_drvdata(video_devdata(file)); 367 dev = (struct hdpvr_device *)video_get_drvdata(video_devdata(file));
368 if (!dev) { 368 if (!dev) {
369 v4l2_err(&dev->v4l2_dev, "open failing with with ENODEV\n"); 369 pr_err("open failing with with ENODEV\n");
370 retval = -ENODEV; 370 retval = -ENODEV;
371 goto err; 371 goto err;
372 } 372 }
diff --git a/drivers/media/video/ivtv/ivtv-controls.c b/drivers/media/video/ivtv/ivtv-controls.c
index b59475bfc243..b588e30cbcf0 100644
--- a/drivers/media/video/ivtv/ivtv-controls.c
+++ b/drivers/media/video/ivtv/ivtv-controls.c
@@ -267,13 +267,13 @@ int ivtv_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c)
267 if (p.video_encoding != itv->params.video_encoding) { 267 if (p.video_encoding != itv->params.video_encoding) {
268 int is_mpeg1 = p.video_encoding == 268 int is_mpeg1 = p.video_encoding ==
269 V4L2_MPEG_VIDEO_ENCODING_MPEG_1; 269 V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
270 struct v4l2_format fmt; 270 struct v4l2_mbus_framefmt fmt;
271 271
272 /* fix videodecoder resolution */ 272 /* fix videodecoder resolution */
273 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 273 fmt.width = itv->params.width / (is_mpeg1 ? 2 : 1);
274 fmt.fmt.pix.width = itv->params.width / (is_mpeg1 ? 2 : 1); 274 fmt.height = itv->params.height;
275 fmt.fmt.pix.height = itv->params.height; 275 fmt.code = V4L2_MBUS_FMT_FIXED;
276 v4l2_subdev_call(itv->sd_video, video, s_fmt, &fmt); 276 v4l2_subdev_call(itv->sd_video, video, s_mbus_fmt, &fmt);
277 } 277 }
278 err = cx2341x_update(itv, ivtv_api_func, &itv->params, &p); 278 err = cx2341x_update(itv, ivtv_api_func, &itv->params, &p);
279 if (!err && itv->params.stream_vbi_fmt != p.stream_vbi_fmt) 279 if (!err && itv->params.stream_vbi_fmt != p.stream_vbi_fmt)
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c
index abf410943cc9..3c2cc270ccd5 100644
--- a/drivers/media/video/ivtv/ivtv-fileops.c
+++ b/drivers/media/video/ivtv/ivtv-fileops.c
@@ -823,6 +823,12 @@ static void ivtv_stop_decoding(struct ivtv_open_id *id, int flags, u64 pts)
823 823
824 IVTV_DEBUG_FILE("close() of %s\n", s->name); 824 IVTV_DEBUG_FILE("close() of %s\n", s->name);
825 825
826 if (id->type == IVTV_DEC_STREAM_TYPE_YUV &&
827 test_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags)) {
828 /* Restore registers we've changed & clean up any mess */
829 ivtv_yuv_close(itv);
830 }
831
826 /* Stop decoding */ 832 /* Stop decoding */
827 if (test_bit(IVTV_F_S_STREAMING, &s->s_flags)) { 833 if (test_bit(IVTV_F_S_STREAMING, &s->s_flags)) {
828 IVTV_DEBUG_INFO("close stopping decode\n"); 834 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)
832 } 838 }
833 clear_bit(IVTV_F_S_APPL_IO, &s->s_flags); 839 clear_bit(IVTV_F_S_APPL_IO, &s->s_flags);
834 clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags); 840 clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
835 if (id->type == IVTV_DEC_STREAM_TYPE_YUV && test_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags)) { 841
836 /* Restore registers we've changed & clean up any mess we've made */
837 ivtv_yuv_close(itv);
838 }
839 if (itv->output_mode == OUT_UDMA_YUV && id->yuv_frames) 842 if (itv->output_mode == OUT_UDMA_YUV && id->yuv_frames)
840 itv->output_mode = OUT_NONE; 843 itv->output_mode = OUT_NONE;
841 844
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c
index fa9f0d958f96..11ac2fa33ef7 100644
--- a/drivers/media/video/ivtv/ivtv-ioctl.c
+++ b/drivers/media/video/ivtv/ivtv-ioctl.c
@@ -569,6 +569,7 @@ static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f
569 struct ivtv_open_id *id = fh; 569 struct ivtv_open_id *id = fh;
570 struct ivtv *itv = id->itv; 570 struct ivtv *itv = id->itv;
571 struct cx2341x_mpeg_params *p = &itv->params; 571 struct cx2341x_mpeg_params *p = &itv->params;
572 struct v4l2_mbus_framefmt mbus_fmt;
572 int ret = ivtv_try_fmt_vid_cap(file, fh, fmt); 573 int ret = ivtv_try_fmt_vid_cap(file, fh, fmt);
573 int w = fmt->fmt.pix.width; 574 int w = fmt->fmt.pix.width;
574 int h = fmt->fmt.pix.height; 575 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
586 p->height = h; 587 p->height = h;
587 if (p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) 588 if (p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
588 fmt->fmt.pix.width /= 2; 589 fmt->fmt.pix.width /= 2;
589 v4l2_subdev_call(itv->sd_video, video, s_fmt, fmt); 590 mbus_fmt.width = fmt->fmt.pix.width;
591 mbus_fmt.height = h;
592 mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
593 v4l2_subdev_call(itv->sd_video, video, s_mbus_fmt, &mbus_fmt);
590 return ivtv_g_fmt_vid_cap(file, fh, fmt); 594 return ivtv_g_fmt_vid_cap(file, fh, fmt);
591} 595}
592 596
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c
index de4288cc1889..9ecacab4b89b 100644
--- a/drivers/media/video/ivtv/ivtv-streams.c
+++ b/drivers/media/video/ivtv/ivtv-streams.c
@@ -618,12 +618,17 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s)
618 struct ivtv *itv = s->itv; 618 struct ivtv *itv = s->itv;
619 struct cx2341x_mpeg_params *p = &itv->params; 619 struct cx2341x_mpeg_params *p = &itv->params;
620 int datatype; 620 int datatype;
621 u16 width;
622 u16 height;
621 623
622 if (s->vdev == NULL) 624 if (s->vdev == NULL)
623 return -EINVAL; 625 return -EINVAL;
624 626
625 IVTV_DEBUG_INFO("Setting some initial decoder settings\n"); 627 IVTV_DEBUG_INFO("Setting some initial decoder settings\n");
626 628
629 width = p->width;
630 height = p->height;
631
627 /* set audio mode to left/stereo for dual/stereo mode. */ 632 /* set audio mode to left/stereo for dual/stereo mode. */
628 ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); 633 ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
629 634
@@ -646,7 +651,14 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s)
646 2 = yuv_from_host */ 651 2 = yuv_from_host */
647 switch (s->type) { 652 switch (s->type) {
648 case IVTV_DEC_STREAM_TYPE_YUV: 653 case IVTV_DEC_STREAM_TYPE_YUV:
649 datatype = itv->output_mode == OUT_PASSTHROUGH ? 1 : 2; 654 if (itv->output_mode == OUT_PASSTHROUGH) {
655 datatype = 1;
656 } else {
657 /* Fake size to avoid switching video standard */
658 datatype = 2;
659 width = 720;
660 height = itv->is_out_50hz ? 576 : 480;
661 }
650 IVTV_DEBUG_INFO("Setup DEC YUV Stream data[0] = %d\n", datatype); 662 IVTV_DEBUG_INFO("Setup DEC YUV Stream data[0] = %d\n", datatype);
651 break; 663 break;
652 case IVTV_DEC_STREAM_TYPE_MPG: 664 case IVTV_DEC_STREAM_TYPE_MPG:
@@ -655,9 +667,13 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s)
655 break; 667 break;
656 } 668 }
657 if (ivtv_vapi(itv, CX2341X_DEC_SET_DECODER_SOURCE, 4, datatype, 669 if (ivtv_vapi(itv, CX2341X_DEC_SET_DECODER_SOURCE, 4, datatype,
658 p->width, p->height, p->audio_properties)) { 670 width, height, p->audio_properties)) {
659 IVTV_DEBUG_WARN("Couldn't initialize decoder source\n"); 671 IVTV_DEBUG_WARN("Couldn't initialize decoder source\n");
660 } 672 }
673
674 /* Decoder sometimes dies here, so wait a moment */
675 ivtv_msleep_timeout(10, 0);
676
661 return 0; 677 return 0;
662} 678}
663 679
@@ -697,6 +713,9 @@ int ivtv_start_v4l2_decode_stream(struct ivtv_stream *s, int gop_offset)
697 /* start playback */ 713 /* start playback */
698 ivtv_vapi(itv, CX2341X_DEC_START_PLAYBACK, 2, gop_offset, 0); 714 ivtv_vapi(itv, CX2341X_DEC_START_PLAYBACK, 2, gop_offset, 0);
699 715
716 /* Let things settle before we actually start */
717 ivtv_msleep_timeout(10, 0);
718
700 /* Clear the following Interrupt mask bits for decoding */ 719 /* Clear the following Interrupt mask bits for decoding */
701 ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_DECODE); 720 ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_DECODE);
702 IVTV_DEBUG_IRQ("IRQ Mask is now: 0x%08x\n", itv->irqmask); 721 IVTV_DEBUG_IRQ("IRQ Mask is now: 0x%08x\n", itv->irqmask);
diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c
index 49e1a283ed36..9ff3425891ed 100644
--- a/drivers/media/video/ivtv/ivtvfb.c
+++ b/drivers/media/video/ivtv/ivtvfb.c
@@ -1066,7 +1066,11 @@ static int ivtvfb_init_io(struct ivtv *itv)
1066 } 1066 }
1067 mutex_unlock(&itv->serialize_lock); 1067 mutex_unlock(&itv->serialize_lock);
1068 1068
1069 ivtvfb_get_framebuffer(itv, &oi->video_rbase, &oi->video_buffer_size); 1069 if (ivtvfb_get_framebuffer(itv, &oi->video_rbase,
1070 &oi->video_buffer_size) < 0) {
1071 IVTVFB_ERR("Firmware failed to respond\n");
1072 return -EIO;
1073 }
1070 1074
1071 /* The osd buffer size depends on the number of video buffers allocated 1075 /* The osd buffer size depends on the number of video buffers allocated
1072 on the PVR350 itself. For now we'll hardcode the smallest osd buffer 1076 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)
1158 } 1162 }
1159 1163
1160 /* Find & setup the OSD buffer */ 1164 /* Find & setup the OSD buffer */
1161 if ((rc = ivtvfb_init_io(itv))) 1165 rc = ivtvfb_init_io(itv);
1166 if (rc) {
1167 ivtvfb_release_buffers(itv);
1162 return rc; 1168 return rc;
1169 }
1163 1170
1164 /* Set the startup video mode information */ 1171 /* Set the startup video mode information */
1165 if ((rc = ivtvfb_init_vidmode(itv))) { 1172 if ((rc = ivtvfb_init_vidmode(itv))) {
@@ -1210,6 +1217,7 @@ static int ivtvfb_callback_cleanup(struct device *dev, void *p)
1210{ 1217{
1211 struct v4l2_device *v4l2_dev = dev_get_drvdata(dev); 1218 struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
1212 struct ivtv *itv = container_of(v4l2_dev, struct ivtv, v4l2_dev); 1219 struct ivtv *itv = container_of(v4l2_dev, struct ivtv, v4l2_dev);
1220 struct osd_info *oi = itv->osd_info;
1213 1221
1214 if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { 1222 if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
1215 if (unregister_framebuffer(&itv->osd_info->ivtvfb_info)) { 1223 if (unregister_framebuffer(&itv->osd_info->ivtvfb_info)) {
@@ -1218,7 +1226,7 @@ static int ivtvfb_callback_cleanup(struct device *dev, void *p)
1218 return 0; 1226 return 0;
1219 } 1227 }
1220 IVTVFB_INFO("Unregister framebuffer %d\n", itv->instance); 1228 IVTVFB_INFO("Unregister framebuffer %d\n", itv->instance);
1221 ivtvfb_blank(FB_BLANK_POWERDOWN, &itv->osd_info->ivtvfb_info); 1229 ivtvfb_blank(FB_BLANK_VSYNC_SUSPEND, &oi->ivtvfb_info);
1222 ivtvfb_release_buffers(itv); 1230 ivtvfb_release_buffers(itv);
1223 itv->osd_video_pbase = 0; 1231 itv->osd_video_pbase = 0;
1224 } 1232 }
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c
index b62c0bd3f8ea..79f096ddcf5d 100644
--- a/drivers/media/video/mt9m001.c
+++ b/drivers/media/video/mt9m001.c
@@ -701,13 +701,13 @@ static struct v4l2_subdev_core_ops mt9m001_subdev_core_ops = {
701#endif 701#endif
702}; 702};
703 703
704static int mt9m001_enum_fmt(struct v4l2_subdev *sd, int index, 704static int mt9m001_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
705 enum v4l2_mbus_pixelcode *code) 705 enum v4l2_mbus_pixelcode *code)
706{ 706{
707 struct i2c_client *client = sd->priv; 707 struct i2c_client *client = sd->priv;
708 struct mt9m001 *mt9m001 = to_mt9m001(client); 708 struct mt9m001 *mt9m001 = to_mt9m001(client);
709 709
710 if ((unsigned int)index >= mt9m001->num_fmts) 710 if (index >= mt9m001->num_fmts)
711 return -EINVAL; 711 return -EINVAL;
712 712
713 *code = mt9m001->fmts[index].code; 713 *code = mt9m001->fmts[index].code;
@@ -785,7 +785,6 @@ static int mt9m001_probe(struct i2c_client *client,
785 ret = mt9m001_video_probe(icd, client); 785 ret = mt9m001_video_probe(icd, client);
786 if (ret) { 786 if (ret) {
787 icd->ops = NULL; 787 icd->ops = NULL;
788 i2c_set_clientdata(client, NULL);
789 kfree(mt9m001); 788 kfree(mt9m001);
790 } 789 }
791 790
@@ -799,7 +798,6 @@ static int mt9m001_remove(struct i2c_client *client)
799 798
800 icd->ops = NULL; 799 icd->ops = NULL;
801 mt9m001_video_remove(icd); 800 mt9m001_video_remove(icd);
802 i2c_set_clientdata(client, NULL);
803 client->driver = NULL; 801 client->driver = NULL;
804 kfree(mt9m001); 802 kfree(mt9m001);
805 803
diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c
index d35f536f9fc3..fbd0fc794720 100644
--- a/drivers/media/video/mt9m111.c
+++ b/drivers/media/video/mt9m111.c
@@ -999,10 +999,10 @@ static struct v4l2_subdev_core_ops mt9m111_subdev_core_ops = {
999#endif 999#endif
1000}; 1000};
1001 1001
1002static int mt9m111_enum_fmt(struct v4l2_subdev *sd, int index, 1002static int mt9m111_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
1003 enum v4l2_mbus_pixelcode *code) 1003 enum v4l2_mbus_pixelcode *code)
1004{ 1004{
1005 if ((unsigned int)index >= ARRAY_SIZE(mt9m111_colour_fmts)) 1005 if (index >= ARRAY_SIZE(mt9m111_colour_fmts))
1006 return -EINVAL; 1006 return -EINVAL;
1007 1007
1008 *code = mt9m111_colour_fmts[index].code; 1008 *code = mt9m111_colour_fmts[index].code;
@@ -1068,7 +1068,6 @@ static int mt9m111_probe(struct i2c_client *client,
1068 ret = mt9m111_video_probe(icd, client); 1068 ret = mt9m111_video_probe(icd, client);
1069 if (ret) { 1069 if (ret) {
1070 icd->ops = NULL; 1070 icd->ops = NULL;
1071 i2c_set_clientdata(client, NULL);
1072 kfree(mt9m111); 1071 kfree(mt9m111);
1073 } 1072 }
1074 1073
@@ -1081,7 +1080,6 @@ static int mt9m111_remove(struct i2c_client *client)
1081 struct soc_camera_device *icd = client->dev.platform_data; 1080 struct soc_camera_device *icd = client->dev.platform_data;
1082 1081
1083 icd->ops = NULL; 1082 icd->ops = NULL;
1084 i2c_set_clientdata(client, NULL);
1085 client->driver = NULL; 1083 client->driver = NULL;
1086 kfree(mt9m111); 1084 kfree(mt9m111);
1087 1085
diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c
index 78b4e091d2d5..a9a28b214235 100644
--- a/drivers/media/video/mt9t031.c
+++ b/drivers/media/video/mt9t031.c
@@ -798,7 +798,7 @@ static struct v4l2_subdev_core_ops mt9t031_subdev_core_ops = {
798#endif 798#endif
799}; 799};
800 800
801static int mt9t031_enum_fmt(struct v4l2_subdev *sd, int index, 801static int mt9t031_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
802 enum v4l2_mbus_pixelcode *code) 802 enum v4l2_mbus_pixelcode *code)
803{ 803{
804 if (index) 804 if (index)
@@ -883,7 +883,6 @@ static int mt9t031_probe(struct i2c_client *client,
883 if (ret) { 883 if (ret) {
884 if (icd) 884 if (icd)
885 icd->ops = NULL; 885 icd->ops = NULL;
886 i2c_set_clientdata(client, NULL);
887 kfree(mt9t031); 886 kfree(mt9t031);
888 } 887 }
889 888
@@ -897,7 +896,6 @@ static int mt9t031_remove(struct i2c_client *client)
897 896
898 if (icd) 897 if (icd)
899 icd->ops = NULL; 898 icd->ops = NULL;
900 i2c_set_clientdata(client, NULL);
901 client->driver = NULL; 899 client->driver = NULL;
902 kfree(mt9t031); 900 kfree(mt9t031);
903 901
diff --git a/drivers/media/video/mt9t112.c b/drivers/media/video/mt9t112.c
index 7438f8d775ba..e4bf1db9a87b 100644
--- a/drivers/media/video/mt9t112.c
+++ b/drivers/media/video/mt9t112.c
@@ -1017,10 +1017,10 @@ static int mt9t112_try_fmt(struct v4l2_subdev *sd,
1017 return 0; 1017 return 0;
1018} 1018}
1019 1019
1020static int mt9t112_enum_fmt(struct v4l2_subdev *sd, int index, 1020static int mt9t112_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
1021 enum v4l2_mbus_pixelcode *code) 1021 enum v4l2_mbus_pixelcode *code)
1022{ 1022{
1023 if ((unsigned int)index >= ARRAY_SIZE(mt9t112_cfmts)) 1023 if (index >= ARRAY_SIZE(mt9t112_cfmts))
1024 return -EINVAL; 1024 return -EINVAL;
1025 1025
1026 *code = mt9t112_cfmts[index].code; 1026 *code = mt9t112_cfmts[index].code;
@@ -1119,7 +1119,6 @@ static int mt9t112_probe(struct i2c_client *client,
1119 ret = mt9t112_camera_probe(icd, client); 1119 ret = mt9t112_camera_probe(icd, client);
1120 if (ret) { 1120 if (ret) {
1121 icd->ops = NULL; 1121 icd->ops = NULL;
1122 i2c_set_clientdata(client, NULL);
1123 kfree(priv); 1122 kfree(priv);
1124 } 1123 }
1125 1124
@@ -1132,7 +1131,6 @@ static int mt9t112_remove(struct i2c_client *client)
1132 struct soc_camera_device *icd = client->dev.platform_data; 1131 struct soc_camera_device *icd = client->dev.platform_data;
1133 1132
1134 icd->ops = NULL; 1133 icd->ops = NULL;
1135 i2c_set_clientdata(client, NULL);
1136 kfree(priv); 1134 kfree(priv);
1137 return 0; 1135 return 0;
1138} 1136}
diff --git a/drivers/media/video/mt9v011.c b/drivers/media/video/mt9v011.c
index 72e55be0b4ab..f5e778d5ca9f 100644
--- a/drivers/media/video/mt9v011.c
+++ b/drivers/media/video/mt9v011.c
@@ -392,27 +392,25 @@ static int mt9v011_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
392 return 0; 392 return 0;
393} 393}
394 394
395static int mt9v011_enum_fmt(struct v4l2_subdev *sd, struct v4l2_fmtdesc *fmt) 395static int mt9v011_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
396 enum v4l2_mbus_pixelcode *code)
396{ 397{
397 if (fmt->index > 0) 398 if (index > 0)
398 return -EINVAL; 399 return -EINVAL;
399 400
400 fmt->flags = 0; 401 *code = V4L2_MBUS_FMT_SGRBG8_1X8;
401 strcpy(fmt->description, "8 bpp Bayer GRGR..BGBG");
402 fmt->pixelformat = V4L2_PIX_FMT_SGRBG8;
403
404 return 0; 402 return 0;
405} 403}
406 404
407static int mt9v011_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) 405static int mt9v011_try_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
408{ 406{
409 struct v4l2_pix_format *pix = &fmt->fmt.pix; 407 if (fmt->code != V4L2_MBUS_FMT_SGRBG8_1X8)
410
411 if (pix->pixelformat != V4L2_PIX_FMT_SGRBG8)
412 return -EINVAL; 408 return -EINVAL;
413 409
414 v4l_bound_align_image(&pix->width, 48, 639, 1, 410 v4l_bound_align_image(&fmt->width, 48, 639, 1,
415 &pix->height, 32, 480, 1, 0); 411 &fmt->height, 32, 480, 1, 0);
412 fmt->field = V4L2_FIELD_NONE;
413 fmt->colorspace = V4L2_COLORSPACE_SRGB;
416 414
417 return 0; 415 return 0;
418} 416}
@@ -455,18 +453,17 @@ static int mt9v011_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
455 return 0; 453 return 0;
456} 454}
457 455
458static int mt9v011_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) 456static int mt9v011_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
459{ 457{
460 struct v4l2_pix_format *pix = &fmt->fmt.pix;
461 struct mt9v011 *core = to_mt9v011(sd); 458 struct mt9v011 *core = to_mt9v011(sd);
462 int rc; 459 int rc;
463 460
464 rc = mt9v011_try_fmt(sd, fmt); 461 rc = mt9v011_try_mbus_fmt(sd, fmt);
465 if (rc < 0) 462 if (rc < 0)
466 return -EINVAL; 463 return -EINVAL;
467 464
468 core->width = pix->width; 465 core->width = fmt->width;
469 core->height = pix->height; 466 core->height = fmt->height;
470 467
471 set_res(sd); 468 set_res(sd);
472 469
@@ -549,9 +546,9 @@ static const struct v4l2_subdev_core_ops mt9v011_core_ops = {
549}; 546};
550 547
551static const struct v4l2_subdev_video_ops mt9v011_video_ops = { 548static const struct v4l2_subdev_video_ops mt9v011_video_ops = {
552 .enum_fmt = mt9v011_enum_fmt, 549 .enum_mbus_fmt = mt9v011_enum_mbus_fmt,
553 .try_fmt = mt9v011_try_fmt, 550 .try_mbus_fmt = mt9v011_try_mbus_fmt,
554 .s_fmt = mt9v011_s_fmt, 551 .s_mbus_fmt = mt9v011_s_mbus_fmt,
555 .g_parm = mt9v011_g_parm, 552 .g_parm = mt9v011_g_parm,
556 .s_parm = mt9v011_s_parm, 553 .s_parm = mt9v011_s_parm,
557}; 554};
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c
index e5bae4c9393b..e7cd23cd6394 100644
--- a/drivers/media/video/mt9v022.c
+++ b/drivers/media/video/mt9v022.c
@@ -838,13 +838,13 @@ static struct v4l2_subdev_core_ops mt9v022_subdev_core_ops = {
838#endif 838#endif
839}; 839};
840 840
841static int mt9v022_enum_fmt(struct v4l2_subdev *sd, int index, 841static int mt9v022_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
842 enum v4l2_mbus_pixelcode *code) 842 enum v4l2_mbus_pixelcode *code)
843{ 843{
844 struct i2c_client *client = sd->priv; 844 struct i2c_client *client = sd->priv;
845 struct mt9v022 *mt9v022 = to_mt9v022(client); 845 struct mt9v022 *mt9v022 = to_mt9v022(client);
846 846
847 if ((unsigned int)index >= mt9v022->num_fmts) 847 if (index >= mt9v022->num_fmts)
848 return -EINVAL; 848 return -EINVAL;
849 849
850 *code = mt9v022->fmts[index].code; 850 *code = mt9v022->fmts[index].code;
@@ -920,7 +920,6 @@ static int mt9v022_probe(struct i2c_client *client,
920 ret = mt9v022_video_probe(icd, client); 920 ret = mt9v022_video_probe(icd, client);
921 if (ret) { 921 if (ret) {
922 icd->ops = NULL; 922 icd->ops = NULL;
923 i2c_set_clientdata(client, NULL);
924 kfree(mt9v022); 923 kfree(mt9v022);
925 } 924 }
926 925
@@ -934,7 +933,6 @@ static int mt9v022_remove(struct i2c_client *client)
934 933
935 icd->ops = NULL; 934 icd->ops = NULL;
936 mt9v022_video_remove(icd); 935 mt9v022_video_remove(icd);
937 i2c_set_clientdata(client, NULL);
938 client->driver = NULL; 936 client->driver = NULL;
939 kfree(mt9v022); 937 kfree(mt9v022);
940 938
diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c
index d477e3058002..a9be14c23912 100644
--- a/drivers/media/video/mx3_camera.c
+++ b/drivers/media/video/mx3_camera.c
@@ -672,7 +672,7 @@ static bool mx3_camera_packing_supported(const struct soc_mbus_pixelfmt *fmt)
672 fmt->packing == SOC_MBUS_PACKING_EXTEND16); 672 fmt->packing == SOC_MBUS_PACKING_EXTEND16);
673} 673}
674 674
675static int mx3_camera_get_formats(struct soc_camera_device *icd, int idx, 675static int mx3_camera_get_formats(struct soc_camera_device *icd, unsigned int idx,
676 struct soc_camera_format_xlate *xlate) 676 struct soc_camera_format_xlate *xlate)
677{ 677{
678 struct v4l2_subdev *sd = soc_camera_to_subdev(icd); 678 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,
689 fmt = soc_mbus_get_fmtdesc(code); 689 fmt = soc_mbus_get_fmtdesc(code);
690 if (!fmt) { 690 if (!fmt) {
691 dev_err(icd->dev.parent, 691 dev_err(icd->dev.parent,
692 "Invalid format code #%d: %d\n", idx, code); 692 "Invalid format code #%u: %d\n", idx, code);
693 return 0; 693 return 0;
694 } 694 }
695 695
diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c
index 4c0ab499228b..e7db0554949a 100644
--- a/drivers/media/video/omap/omap_vout.c
+++ b/drivers/media/video/omap/omap_vout.c
@@ -2371,12 +2371,11 @@ static int __init omap_vout_create_video_devices(struct platform_device *pdev)
2371 2371
2372 for (k = 0; k < pdev->num_resources; k++) { 2372 for (k = 0; k < pdev->num_resources; k++) {
2373 2373
2374 vout = kmalloc(sizeof(struct omap_vout_device), GFP_KERNEL); 2374 vout = kzalloc(sizeof(struct omap_vout_device), GFP_KERNEL);
2375 if (!vout) { 2375 if (!vout) {
2376 dev_err(&pdev->dev, ": could not allocate memory\n"); 2376 dev_err(&pdev->dev, ": could not allocate memory\n");
2377 return -ENOMEM; 2377 return -ENOMEM;
2378 } 2378 }
2379 memset(vout, 0, sizeof(struct omap_vout_device));
2380 2379
2381 vout->vid = k; 2380 vout->vid = k;
2382 vid_dev->vouts[k] = vout; 2381 vid_dev->vouts[k] = vout;
diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c
index 7f8ece30c77b..34034a710214 100644
--- a/drivers/media/video/ov772x.c
+++ b/drivers/media/video/ov772x.c
@@ -1092,10 +1092,10 @@ static struct v4l2_subdev_core_ops ov772x_subdev_core_ops = {
1092#endif 1092#endif
1093}; 1093};
1094 1094
1095static int ov772x_enum_fmt(struct v4l2_subdev *sd, int index, 1095static int ov772x_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
1096 enum v4l2_mbus_pixelcode *code) 1096 enum v4l2_mbus_pixelcode *code)
1097{ 1097{
1098 if ((unsigned int)index >= ARRAY_SIZE(ov772x_cfmts)) 1098 if (index >= ARRAY_SIZE(ov772x_cfmts))
1099 return -EINVAL; 1099 return -EINVAL;
1100 1100
1101 *code = ov772x_cfmts[index].code; 1101 *code = ov772x_cfmts[index].code;
@@ -1159,7 +1159,6 @@ static int ov772x_probe(struct i2c_client *client,
1159 ret = ov772x_video_probe(icd, client); 1159 ret = ov772x_video_probe(icd, client);
1160 if (ret) { 1160 if (ret) {
1161 icd->ops = NULL; 1161 icd->ops = NULL;
1162 i2c_set_clientdata(client, NULL);
1163 kfree(priv); 1162 kfree(priv);
1164 } 1163 }
1165 1164
@@ -1172,7 +1171,6 @@ static int ov772x_remove(struct i2c_client *client)
1172 struct soc_camera_device *icd = client->dev.platform_data; 1171 struct soc_camera_device *icd = client->dev.platform_data;
1173 1172
1174 icd->ops = NULL; 1173 icd->ops = NULL;
1175 i2c_set_clientdata(client, NULL);
1176 kfree(priv); 1174 kfree(priv);
1177 return 0; 1175 return 0;
1178} 1176}
diff --git a/drivers/media/video/ov9640.c b/drivers/media/video/ov9640.c
index 36599a65f548..7ce9e05b4781 100644
--- a/drivers/media/video/ov9640.c
+++ b/drivers/media/video/ov9640.c
@@ -614,10 +614,10 @@ static int ov9640_try_fmt(struct v4l2_subdev *sd,
614 return 0; 614 return 0;
615} 615}
616 616
617static int ov9640_enum_fmt(struct v4l2_subdev *sd, int index, 617static int ov9640_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
618 enum v4l2_mbus_pixelcode *code) 618 enum v4l2_mbus_pixelcode *code)
619{ 619{
620 if ((unsigned int)index >= ARRAY_SIZE(ov9640_codes)) 620 if (index >= ARRAY_SIZE(ov9640_codes))
621 return -EINVAL; 621 return -EINVAL;
622 622
623 *code = ov9640_codes[index]; 623 *code = ov9640_codes[index];
@@ -783,7 +783,6 @@ static int ov9640_probe(struct i2c_client *client,
783 783
784 if (ret) { 784 if (ret) {
785 icd->ops = NULL; 785 icd->ops = NULL;
786 i2c_set_clientdata(client, NULL);
787 kfree(priv); 786 kfree(priv);
788 } 787 }
789 788
@@ -794,7 +793,6 @@ static int ov9640_remove(struct i2c_client *client)
794{ 793{
795 struct ov9640_priv *priv = i2c_get_clientdata(client); 794 struct ov9640_priv *priv = i2c_get_clientdata(client);
796 795
797 i2c_set_clientdata(client, NULL);
798 kfree(priv); 796 kfree(priv);
799 return 0; 797 return 0;
800} 798}
diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c
index 6bc16c13ccef..3092abfd66a2 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c
@@ -117,6 +117,7 @@ static const struct pvr2_device_desc pvr2_device_24xxx = {
117static const struct pvr2_device_client_desc pvr2_cli_gotview_2[] = { 117static const struct pvr2_device_client_desc pvr2_cli_gotview_2[] = {
118 { .module_id = PVR2_CLIENT_ID_CX25840 }, 118 { .module_id = PVR2_CLIENT_ID_CX25840 },
119 { .module_id = PVR2_CLIENT_ID_TUNER }, 119 { .module_id = PVR2_CLIENT_ID_TUNER },
120 { .module_id = PVR2_CLIENT_ID_DEMOD },
120}; 121};
121 122
122static const struct pvr2_device_desc pvr2_device_gotview_2 = { 123static const struct pvr2_device_desc pvr2_device_gotview_2 = {
diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/drivers/media/video/pvrusb2/pvrusb2-devattr.h
index e5b9594eb5f6..273c8d4b3853 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-devattr.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.h
@@ -177,6 +177,11 @@ struct pvr2_device_desc {
177 unsigned int flag_has_composite:1; /* Has composite input */ 177 unsigned int flag_has_composite:1; /* Has composite input */
178 unsigned int flag_has_svideo:1; /* Has s-video input */ 178 unsigned int flag_has_svideo:1; /* Has s-video input */
179 unsigned int flag_fx2_16kb:1; /* 16KB FX2 firmware OK here */ 179 unsigned int flag_fx2_16kb:1; /* 16KB FX2 firmware OK here */
180
181 /* If this driver is considered experimental, i.e. not all aspects
182 are working correctly and/or it is untested, mark that fact
183 with this flag. */
184 unsigned int flag_is_experimental:1;
180}; 185};
181 186
182extern struct usb_device_id pvr2_device_table[]; 187extern struct usb_device_id pvr2_device_table[];
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
index 301ef197d038..70ea578d6266 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -2459,6 +2459,19 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
2459 hdw,hdw_desc->description); 2459 hdw,hdw_desc->description);
2460 pvr2_trace(PVR2_TRACE_INFO, "Hardware description: %s", 2460 pvr2_trace(PVR2_TRACE_INFO, "Hardware description: %s",
2461 hdw_desc->description); 2461 hdw_desc->description);
2462 if (hdw_desc->flag_is_experimental) {
2463 pvr2_trace(PVR2_TRACE_INFO, "**********");
2464 pvr2_trace(PVR2_TRACE_INFO,
2465 "WARNING: Support for this device (%s) is"
2466 " experimental.", hdw_desc->description);
2467 pvr2_trace(PVR2_TRACE_INFO,
2468 "Important functionality might not be"
2469 " entirely working.");
2470 pvr2_trace(PVR2_TRACE_INFO,
2471 "Please consider contacting the driver author to"
2472 " help with further stabilization of the driver.");
2473 pvr2_trace(PVR2_TRACE_INFO, "**********");
2474 }
2462 if (!hdw) goto fail; 2475 if (!hdw) goto fail;
2463 2476
2464 init_timer(&hdw->quiescent_timer); 2477 init_timer(&hdw->quiescent_timer);
@@ -3056,14 +3069,14 @@ static void pvr2_subdev_update(struct pvr2_hdw *hdw)
3056 } 3069 }
3057 3070
3058 if (hdw->res_hor_dirty || hdw->res_ver_dirty || hdw->force_dirty) { 3071 if (hdw->res_hor_dirty || hdw->res_ver_dirty || hdw->force_dirty) {
3059 struct v4l2_format fmt; 3072 struct v4l2_mbus_framefmt fmt;
3060 memset(&fmt, 0, sizeof(fmt)); 3073 memset(&fmt, 0, sizeof(fmt));
3061 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 3074 fmt.width = hdw->res_hor_val;
3062 fmt.fmt.pix.width = hdw->res_hor_val; 3075 fmt.height = hdw->res_ver_val;
3063 fmt.fmt.pix.height = hdw->res_ver_val; 3076 fmt.code = V4L2_MBUS_FMT_FIXED;
3064 pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_size(%dx%d)", 3077 pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_size(%dx%d)",
3065 fmt.fmt.pix.width, fmt.fmt.pix.height); 3078 fmt.width, fmt.height);
3066 v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_fmt, &fmt); 3079 v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_mbus_fmt, &fmt);
3067 } 3080 }
3068 3081
3069 if (hdw->srate_dirty || hdw->force_dirty) { 3082 if (hdw->srate_dirty || hdw->force_dirty) {
@@ -4084,12 +4097,20 @@ void pvr2_hdw_device_reset(struct pvr2_hdw *hdw)
4084 4097
4085void pvr2_hdw_cpureset_assert(struct pvr2_hdw *hdw,int val) 4098void pvr2_hdw_cpureset_assert(struct pvr2_hdw *hdw,int val)
4086{ 4099{
4087 char da[1]; 4100 char *da;
4088 unsigned int pipe; 4101 unsigned int pipe;
4089 int ret; 4102 int ret;
4090 4103
4091 if (!hdw->usb_dev) return; 4104 if (!hdw->usb_dev) return;
4092 4105
4106 da = kmalloc(16, GFP_KERNEL);
4107
4108 if (da == NULL) {
4109 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
4110 "Unable to allocate memory to control CPU reset");
4111 return;
4112 }
4113
4093 pvr2_trace(PVR2_TRACE_INIT,"cpureset_assert(%d)",val); 4114 pvr2_trace(PVR2_TRACE_INIT,"cpureset_assert(%d)",val);
4094 4115
4095 da[0] = val ? 0x01 : 0x00; 4116 da[0] = val ? 0x01 : 0x00;
@@ -4103,6 +4124,8 @@ void pvr2_hdw_cpureset_assert(struct pvr2_hdw *hdw,int val)
4103 "cpureset_assert(%d) error=%d",val,ret); 4124 "cpureset_assert(%d) error=%d",val,ret);
4104 pvr2_hdw_render_useless(hdw); 4125 pvr2_hdw_render_useless(hdw);
4105 } 4126 }
4127
4128 kfree(da);
4106} 4129}
4107 4130
4108 4131
diff --git a/drivers/media/video/pvrusb2/pvrusb2-main.c b/drivers/media/video/pvrusb2/pvrusb2-main.c
index eeacd0f67855..2254194aad57 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-main.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-main.c
@@ -153,12 +153,12 @@ static void __exit pvr_exit(void)
153 153
154 usb_deregister(&pvr_driver); 154 usb_deregister(&pvr_driver);
155 155
156 pvr2_context_global_done();
157
156#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS 158#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
157 pvr2_sysfs_class_destroy(class_ptr); 159 pvr2_sysfs_class_destroy(class_ptr);
158#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */ 160#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
159 161
160 pvr2_context_global_done();
161
162 pvr2_trace(PVR2_TRACE_INIT,"pvr_exit complete"); 162 pvr2_trace(PVR2_TRACE_INIT,"pvr_exit complete");
163} 163}
164 164
diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
index 71f50565f637..3d7e5aab547f 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
@@ -74,7 +74,7 @@ struct pvr2_sysfs_ctl_item {
74 int ctl_id; 74 int ctl_id;
75 struct pvr2_sysfs *chptr; 75 struct pvr2_sysfs *chptr;
76 struct pvr2_sysfs_ctl_item *item_next; 76 struct pvr2_sysfs_ctl_item *item_next;
77 struct attribute *attr_gen[7]; 77 struct attribute *attr_gen[8];
78 struct attribute_group grp; 78 struct attribute_group grp;
79 int created_ok; 79 int created_ok;
80 char name[80]; 80 char name[80];
@@ -511,6 +511,7 @@ static void pvr2_sysfs_release(struct device *class_dev)
511 511
512static void class_dev_destroy(struct pvr2_sysfs *sfp) 512static void class_dev_destroy(struct pvr2_sysfs *sfp)
513{ 513{
514 struct device *dev;
514 if (!sfp->class_dev) return; 515 if (!sfp->class_dev) return;
515#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC 516#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
516 pvr2_sysfs_tear_down_debugifc(sfp); 517 pvr2_sysfs_tear_down_debugifc(sfp);
@@ -542,6 +543,9 @@ static void class_dev_destroy(struct pvr2_sysfs *sfp)
542 } 543 }
543 pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev); 544 pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev);
544 dev_set_drvdata(sfp->class_dev, NULL); 545 dev_set_drvdata(sfp->class_dev, NULL);
546 dev = sfp->class_dev->parent;
547 sfp->class_dev->parent = NULL;
548 put_device(dev);
545 device_unregister(sfp->class_dev); 549 device_unregister(sfp->class_dev);
546 sfp->class_dev = NULL; 550 sfp->class_dev = NULL;
547} 551}
@@ -631,10 +635,11 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
631 pvr2_sysfs_trace("Creating class_dev id=%p",class_dev); 635 pvr2_sysfs_trace("Creating class_dev id=%p",class_dev);
632 636
633 class_dev->class = &class_ptr->class; 637 class_dev->class = &class_ptr->class;
638
634 dev_set_name(class_dev, "%s", 639 dev_set_name(class_dev, "%s",
635 pvr2_hdw_get_device_identifier(sfp->channel.hdw)); 640 pvr2_hdw_get_device_identifier(sfp->channel.hdw));
636 641
637 class_dev->parent = &usb_dev->dev; 642 class_dev->parent = get_device(&usb_dev->dev);
638 643
639 sfp->class_dev = class_dev; 644 sfp->class_dev = class_dev;
640 dev_set_drvdata(class_dev, sfp); 645 dev_set_drvdata(class_dev, sfp);
@@ -775,7 +780,8 @@ struct pvr2_sysfs_class *pvr2_sysfs_class_create(void)
775 struct pvr2_sysfs_class *clp; 780 struct pvr2_sysfs_class *clp;
776 clp = kzalloc(sizeof(*clp),GFP_KERNEL); 781 clp = kzalloc(sizeof(*clp),GFP_KERNEL);
777 if (!clp) return clp; 782 if (!clp) return clp;
778 pvr2_sysfs_trace("Creating pvr2_sysfs_class id=%p",clp); 783 pvr2_sysfs_trace("Creating and registering pvr2_sysfs_class id=%p",
784 clp);
779 clp->class.name = "pvrusb2"; 785 clp->class.name = "pvrusb2";
780 clp->class.class_release = pvr2_sysfs_class_release; 786 clp->class.class_release = pvr2_sysfs_class_release;
781 clp->class.dev_release = pvr2_sysfs_release; 787 clp->class.dev_release = pvr2_sysfs_release;
@@ -791,6 +797,7 @@ struct pvr2_sysfs_class *pvr2_sysfs_class_create(void)
791 797
792void pvr2_sysfs_class_destroy(struct pvr2_sysfs_class *clp) 798void pvr2_sysfs_class_destroy(struct pvr2_sysfs_class *clp)
793{ 799{
800 pvr2_sysfs_trace("Unregistering pvr2_sysfs_class id=%p", clp);
794 class_unregister(&clp->class); 801 class_unregister(&clp->class);
795} 802}
796 803
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
index 5ffa0d2b0b0d..aaafa0398fd5 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
@@ -883,6 +883,17 @@ static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
883{ 883{
884 struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw; 884 struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw;
885 enum pvr2_config cfg = dip->config; 885 enum pvr2_config cfg = dip->config;
886 char msg[80];
887 unsigned int mcnt;
888
889 /* Construct the unregistration message *before* we actually
890 perform the unregistration step. By doing it this way we don't
891 have to worry about potentially touching deleted resources. */
892 mcnt = scnprintf(msg, sizeof(msg) - 1,
893 "pvrusb2: unregistered device %s [%s]",
894 video_device_node_name(&dip->devbase),
895 pvr2_config_get_name(cfg));
896 msg[mcnt] = 0;
886 897
887 pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1); 898 pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1);
888 899
@@ -894,9 +905,7 @@ static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
894 are gone. */ 905 are gone. */
895 video_unregister_device(&dip->devbase); 906 video_unregister_device(&dip->devbase);
896 907
897 printk(KERN_INFO "pvrusb2: unregistered device %s [%s]\n", 908 printk(KERN_INFO "%s\n", msg);
898 video_device_node_name(&dip->devbase),
899 pvr2_config_get_name(cfg));
900 909
901} 910}
902 911
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c
index 7fe70e718656..fb242f6cfb1f 100644
--- a/drivers/media/video/pxa_camera.c
+++ b/drivers/media/video/pxa_camera.c
@@ -1247,7 +1247,7 @@ static bool pxa_camera_packing_supported(const struct soc_mbus_pixelfmt *fmt)
1247 fmt->packing == SOC_MBUS_PACKING_EXTEND16); 1247 fmt->packing == SOC_MBUS_PACKING_EXTEND16);
1248} 1248}
1249 1249
1250static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, 1250static int pxa_camera_get_formats(struct soc_camera_device *icd, unsigned int idx,
1251 struct soc_camera_format_xlate *xlate) 1251 struct soc_camera_format_xlate *xlate)
1252{ 1252{
1253 struct v4l2_subdev *sd = soc_camera_to_subdev(icd); 1253 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,
1264 1264
1265 fmt = soc_mbus_get_fmtdesc(code); 1265 fmt = soc_mbus_get_fmtdesc(code);
1266 if (!fmt) { 1266 if (!fmt) {
1267 dev_err(dev, "Invalid format code #%d: %d\n", idx, code); 1267 dev_err(dev, "Invalid format code #%u: %d\n", idx, code);
1268 return 0; 1268 return 0;
1269 } 1269 }
1270 1270
diff --git a/drivers/media/video/rj54n1cb0c.c b/drivers/media/video/rj54n1cb0c.c
index bbd9c11e2c5a..47fd207ba3b1 100644
--- a/drivers/media/video/rj54n1cb0c.c
+++ b/drivers/media/video/rj54n1cb0c.c
@@ -481,10 +481,10 @@ static int reg_write_multiple(struct i2c_client *client,
481 return 0; 481 return 0;
482} 482}
483 483
484static int rj54n1_enum_fmt(struct v4l2_subdev *sd, int index, 484static int rj54n1_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
485 enum v4l2_mbus_pixelcode *code) 485 enum v4l2_mbus_pixelcode *code)
486{ 486{
487 if ((unsigned int)index >= ARRAY_SIZE(rj54n1_colour_fmts)) 487 if (index >= ARRAY_SIZE(rj54n1_colour_fmts))
488 return -EINVAL; 488 return -EINVAL;
489 489
490 *code = rj54n1_colour_fmts[index].code; 490 *code = rj54n1_colour_fmts[index].code;
@@ -1444,7 +1444,6 @@ static int rj54n1_probe(struct i2c_client *client,
1444 ret = rj54n1_video_probe(icd, client, rj54n1_priv); 1444 ret = rj54n1_video_probe(icd, client, rj54n1_priv);
1445 if (ret < 0) { 1445 if (ret < 0) {
1446 icd->ops = NULL; 1446 icd->ops = NULL;
1447 i2c_set_clientdata(client, NULL);
1448 kfree(rj54n1); 1447 kfree(rj54n1);
1449 return ret; 1448 return ret;
1450 } 1449 }
@@ -1461,7 +1460,6 @@ static int rj54n1_remove(struct i2c_client *client)
1461 icd->ops = NULL; 1460 icd->ops = NULL;
1462 if (icl->free_bus) 1461 if (icl->free_bus)
1463 icl->free_bus(icl); 1462 icl->free_bus(icl);
1464 i2c_set_clientdata(client, NULL);
1465 client->driver = NULL; 1463 client->driver = NULL;
1466 kfree(rj54n1); 1464 kfree(rj54n1);
1467 1465
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c
index 53b6fcde3800..76da74368680 100644
--- a/drivers/media/video/saa7115.c
+++ b/drivers/media/video/saa7115.c
@@ -1117,13 +1117,6 @@ static int saa711x_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f
1117 return 0; 1117 return 0;
1118} 1118}
1119 1119
1120static int saa711x_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
1121{
1122 if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
1123 return -EINVAL;
1124 return saa711x_g_sliced_fmt(sd, &fmt->fmt.sliced);
1125}
1126
1127static int saa711x_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt) 1120static int saa711x_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt)
1128{ 1121{
1129 saa711x_set_lcr(sd, NULL); 1122 saa711x_set_lcr(sd, NULL);
@@ -1136,12 +1129,13 @@ static int saa711x_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f
1136 return 0; 1129 return 0;
1137} 1130}
1138 1131
1139static int saa711x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) 1132static int saa711x_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
1140{ 1133{
1141 if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 1134 if (fmt->code != V4L2_MBUS_FMT_FIXED)
1142 return -EINVAL; 1135 return -EINVAL;
1143 1136 fmt->field = V4L2_FIELD_INTERLACED;
1144 return saa711x_set_size(sd, fmt->fmt.pix.width, fmt->fmt.pix.height); 1137 fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
1138 return saa711x_set_size(sd, fmt->width, fmt->height);
1145} 1139}
1146 1140
1147/* Decode the sliced VBI data stream as created by the saa7115. 1141/* 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 = {
1556static const struct v4l2_subdev_video_ops saa711x_video_ops = { 1550static const struct v4l2_subdev_video_ops saa711x_video_ops = {
1557 .s_routing = saa711x_s_routing, 1551 .s_routing = saa711x_s_routing,
1558 .s_crystal_freq = saa711x_s_crystal_freq, 1552 .s_crystal_freq = saa711x_s_crystal_freq,
1559 .g_fmt = saa711x_g_fmt, 1553 .s_mbus_fmt = saa711x_s_mbus_fmt,
1560 .s_fmt = saa711x_s_fmt,
1561 .s_stream = saa711x_s_stream, 1554 .s_stream = saa711x_s_stream,
1562 .querystd = saa711x_querystd, 1555 .querystd = saa711x_querystd,
1563 .g_input_status = saa711x_g_input_status, 1556 .g_input_status = saa711x_g_input_status,
diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c
index 87986ad62f86..79fffcf39ba8 100644
--- a/drivers/media/video/saa7127.c
+++ b/drivers/media/video/saa7127.c
@@ -645,13 +645,6 @@ static int saa7127_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f
645 return 0; 645 return 0;
646} 646}
647 647
648static int saa7127_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
649{
650 if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
651 return -EINVAL;
652 return saa7127_g_sliced_fmt(sd, &fmt->fmt.sliced);
653}
654
655static int saa7127_s_vbi_data(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data) 648static int saa7127_s_vbi_data(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data)
656{ 649{
657 switch (data->id) { 650 switch (data->id) {
@@ -731,7 +724,6 @@ static const struct v4l2_subdev_core_ops saa7127_core_ops = {
731}; 724};
732 725
733static const struct v4l2_subdev_video_ops saa7127_video_ops = { 726static const struct v4l2_subdev_video_ops saa7127_video_ops = {
734 .g_fmt = saa7127_g_fmt,
735 .s_std_output = saa7127_s_std_output, 727 .s_std_output = saa7127_s_std_output,
736 .s_routing = saa7127_s_routing, 728 .s_routing = saa7127_s_routing,
737 .s_stream = saa7127_s_stream, 729 .s_stream = saa7127_s_stream,
diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c
index 1eabff6b2456..40fd31ca7716 100644
--- a/drivers/media/video/saa7134/saa6752hs.c
+++ b/drivers/media/video/saa7134/saa6752hs.c
@@ -846,24 +846,28 @@ static int saa6752hs_g_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_control
846 return 0; 846 return 0;
847} 847}
848 848
849static int saa6752hs_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) 849static int saa6752hs_g_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
850{ 850{
851 struct saa6752hs_state *h = to_state(sd); 851 struct saa6752hs_state *h = to_state(sd);
852 852
853 if (h->video_format == SAA6752HS_VF_UNKNOWN) 853 if (h->video_format == SAA6752HS_VF_UNKNOWN)
854 h->video_format = SAA6752HS_VF_D1; 854 h->video_format = SAA6752HS_VF_D1;
855 f->fmt.pix.width = 855 f->width = v4l2_format_table[h->video_format].fmt.pix.width;
856 v4l2_format_table[h->video_format].fmt.pix.width; 856 f->height = v4l2_format_table[h->video_format].fmt.pix.height;
857 f->fmt.pix.height = 857 f->code = V4L2_MBUS_FMT_FIXED;
858 v4l2_format_table[h->video_format].fmt.pix.height; 858 f->field = V4L2_FIELD_INTERLACED;
859 f->colorspace = V4L2_COLORSPACE_SMPTE170M;
859 return 0; 860 return 0;
860} 861}
861 862
862static int saa6752hs_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) 863static int saa6752hs_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
863{ 864{
864 struct saa6752hs_state *h = to_state(sd); 865 struct saa6752hs_state *h = to_state(sd);
865 int dist_352, dist_480, dist_720; 866 int dist_352, dist_480, dist_720;
866 867
868 if (f->code != V4L2_MBUS_FMT_FIXED)
869 return -EINVAL;
870
867 /* 871 /*
868 FIXME: translate and round width/height into EMPRESS 872 FIXME: translate and round width/height into EMPRESS
869 subsample type: 873 subsample type:
@@ -876,28 +880,30 @@ static int saa6752hs_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
876 D1 | 720x576 | 720x480 880 D1 | 720x576 | 720x480
877 */ 881 */
878 882
879 dist_352 = abs(f->fmt.pix.width - 352); 883 dist_352 = abs(f->width - 352);
880 dist_480 = abs(f->fmt.pix.width - 480); 884 dist_480 = abs(f->width - 480);
881 dist_720 = abs(f->fmt.pix.width - 720); 885 dist_720 = abs(f->width - 720);
882 if (dist_720 < dist_480) { 886 if (dist_720 < dist_480) {
883 f->fmt.pix.width = 720; 887 f->width = 720;
884 f->fmt.pix.height = 576; 888 f->height = 576;
885 h->video_format = SAA6752HS_VF_D1; 889 h->video_format = SAA6752HS_VF_D1;
886 } else if (dist_480 < dist_352) { 890 } else if (dist_480 < dist_352) {
887 f->fmt.pix.width = 480; 891 f->width = 480;
888 f->fmt.pix.height = 576; 892 f->height = 576;
889 h->video_format = SAA6752HS_VF_2_3_D1; 893 h->video_format = SAA6752HS_VF_2_3_D1;
890 } else { 894 } else {
891 f->fmt.pix.width = 352; 895 f->width = 352;
892 if (abs(f->fmt.pix.height - 576) < 896 if (abs(f->height - 576) <
893 abs(f->fmt.pix.height - 288)) { 897 abs(f->height - 288)) {
894 f->fmt.pix.height = 576; 898 f->height = 576;
895 h->video_format = SAA6752HS_VF_1_2_D1; 899 h->video_format = SAA6752HS_VF_1_2_D1;
896 } else { 900 } else {
897 f->fmt.pix.height = 288; 901 f->height = 288;
898 h->video_format = SAA6752HS_VF_SIF; 902 h->video_format = SAA6752HS_VF_SIF;
899 } 903 }
900 } 904 }
905 f->field = V4L2_FIELD_INTERLACED;
906 f->colorspace = V4L2_COLORSPACE_SMPTE170M;
901 return 0; 907 return 0;
902} 908}
903 909
@@ -932,8 +938,8 @@ static const struct v4l2_subdev_core_ops saa6752hs_core_ops = {
932}; 938};
933 939
934static const struct v4l2_subdev_video_ops saa6752hs_video_ops = { 940static const struct v4l2_subdev_video_ops saa6752hs_video_ops = {
935 .s_fmt = saa6752hs_s_fmt, 941 .s_mbus_fmt = saa6752hs_s_mbus_fmt,
936 .g_fmt = saa6752hs_g_fmt, 942 .g_mbus_fmt = saa6752hs_g_mbus_fmt,
937}; 943};
938 944
939static const struct v4l2_subdev_ops saa6752hs_ops = { 945static const struct v4l2_subdev_ops saa6752hs_ops = {
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index 72700d4e3941..07f6bb8ef9d9 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -3897,6 +3897,40 @@ struct saa7134_board saa7134_boards[] = {
3897 .gpio = 0x01, 3897 .gpio = 0x01,
3898 }, 3898 },
3899 }, 3899 },
3900 [SAA7134_BOARD_AVERMEDIA_M733A] = {
3901 .name = "Avermedia PCI M733A",
3902 .audio_clock = 0x00187de7,
3903 .tuner_type = TUNER_PHILIPS_TDA8290,
3904 .radio_type = UNSET,
3905 .tuner_addr = ADDR_UNSET,
3906 .radio_addr = ADDR_UNSET,
3907 .tuner_config = 0,
3908 .gpiomask = 0x020200000,
3909 .inputs = {{
3910 .name = name_tv,
3911 .vmux = 1,
3912 .amux = TV,
3913 .tv = 1,
3914 }, {
3915 .name = name_comp1,
3916 .vmux = 3,
3917 .amux = LINE1,
3918 }, {
3919 .name = name_svideo,
3920 .vmux = 8,
3921 .amux = LINE1,
3922 } },
3923 .radio = {
3924 .name = name_radio,
3925 .amux = TV,
3926 .gpio = 0x00200000,
3927 },
3928 .mute = {
3929 .name = name_mute,
3930 .amux = TV,
3931 .gpio = 0x01,
3932 },
3933 },
3900 [SAA7134_BOARD_BEHOLD_401] = { 3934 [SAA7134_BOARD_BEHOLD_401] = {
3901 /* Beholder Intl. Ltd. 2008 */ 3935 /* Beholder Intl. Ltd. 2008 */
3902 /*Dmitry Belimov <d.belimov@gmail.com> */ 3936 /*Dmitry Belimov <d.belimov@gmail.com> */
@@ -5822,6 +5856,18 @@ struct pci_device_id saa7134_pci_tbl[] = {
5822 .driver_data = SAA7134_BOARD_AVERMEDIA_M135A, 5856 .driver_data = SAA7134_BOARD_AVERMEDIA_M135A,
5823 }, { 5857 }, {
5824 .vendor = PCI_VENDOR_ID_PHILIPS, 5858 .vendor = PCI_VENDOR_ID_PHILIPS,
5859 .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
5860 .subvendor = 0x1461, /* Avermedia Technologies Inc */
5861 .subdevice = 0x4155,
5862 .driver_data = SAA7134_BOARD_AVERMEDIA_M733A,
5863 }, {
5864 .vendor = PCI_VENDOR_ID_PHILIPS,
5865 .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
5866 .subvendor = 0x1461, /* Avermedia Technologies Inc */
5867 .subdevice = 0x4255,
5868 .driver_data = SAA7134_BOARD_AVERMEDIA_M733A,
5869 }, {
5870 .vendor = PCI_VENDOR_ID_PHILIPS,
5825 .device = PCI_DEVICE_ID_PHILIPS_SAA7130, 5871 .device = PCI_DEVICE_ID_PHILIPS_SAA7130,
5826 .subvendor = PCI_VENDOR_ID_PHILIPS, 5872 .subvendor = PCI_VENDOR_ID_PHILIPS,
5827 .subdevice = 0x2004, 5873 .subdevice = 0x2004,
@@ -6786,6 +6832,7 @@ static int saa7134_tda8290_callback(struct saa7134_dev *dev,
6786 switch (dev->board) { 6832 switch (dev->board) {
6787 case SAA7134_BOARD_HAUPPAUGE_HVR1150: 6833 case SAA7134_BOARD_HAUPPAUGE_HVR1150:
6788 case SAA7134_BOARD_HAUPPAUGE_HVR1120: 6834 case SAA7134_BOARD_HAUPPAUGE_HVR1120:
6835 case SAA7134_BOARD_AVERMEDIA_M733A:
6789 /* tda8290 + tda18271 */ 6836 /* tda8290 + tda18271 */
6790 ret = saa7134_tda8290_18271_callback(dev, command, arg); 6837 ret = saa7134_tda8290_18271_callback(dev, command, arg);
6791 break; 6838 break;
@@ -7087,6 +7134,14 @@ int saa7134_board_init1(struct saa7134_dev *dev)
7087 saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x0000C000, 0x0000C000); 7134 saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x0000C000, 0x0000C000);
7088 saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0000C000, 0x0000C000); 7135 saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0000C000, 0x0000C000);
7089 break; 7136 break;
7137 case SAA7134_BOARD_AVERMEDIA_M733A:
7138 saa7134_set_gpio(dev, 1, 1);
7139 msleep(10);
7140 saa7134_set_gpio(dev, 1, 0);
7141 msleep(10);
7142 saa7134_set_gpio(dev, 1, 1);
7143 dev->has_remote = SAA7134_REMOTE_GPIO;
7144 break;
7090 } 7145 }
7091 return 0; 7146 return 0;
7092} 7147}
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c
index ea877a50f52d..e763f9fd0133 100644
--- a/drivers/media/video/saa7134/saa7134-empress.c
+++ b/drivers/media/video/saa7134/saa7134-empress.c
@@ -223,9 +223,11 @@ static int empress_g_fmt_vid_cap(struct file *file, void *priv,
223 struct v4l2_format *f) 223 struct v4l2_format *f)
224{ 224{
225 struct saa7134_dev *dev = file->private_data; 225 struct saa7134_dev *dev = file->private_data;
226 struct v4l2_mbus_framefmt mbus_fmt;
226 227
227 saa_call_all(dev, video, g_fmt, f); 228 saa_call_all(dev, video, g_mbus_fmt, &mbus_fmt);
228 229
230 v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
229 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; 231 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
230 f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets; 232 f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets;
231 233
@@ -236,8 +238,11 @@ static int empress_s_fmt_vid_cap(struct file *file, void *priv,
236 struct v4l2_format *f) 238 struct v4l2_format *f)
237{ 239{
238 struct saa7134_dev *dev = file->private_data; 240 struct saa7134_dev *dev = file->private_data;
241 struct v4l2_mbus_framefmt mbus_fmt;
239 242
240 saa_call_all(dev, video, s_fmt, f); 243 v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
244 saa_call_all(dev, video, s_mbus_fmt, &mbus_fmt);
245 v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
241 246
242 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; 247 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
243 f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets; 248 f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets;
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
index e5565e2fd426..0b336ca6d55b 100644
--- a/drivers/media/video/saa7134/saa7134-input.c
+++ b/drivers/media/video/saa7134/saa7134-input.c
@@ -141,8 +141,8 @@ static int get_key_flydvb_trio(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
141 struct saa7134_dev *dev = ir->c->adapter->algo_data; 141 struct saa7134_dev *dev = ir->c->adapter->algo_data;
142 142
143 if (dev == NULL) { 143 if (dev == NULL) {
144 dprintk("get_key_flydvb_trio: " 144 i2cdprintk("get_key_flydvb_trio: "
145 "gir->c->adapter->algo_data is NULL!\n"); 145 "ir->c->adapter->algo_data is NULL!\n");
146 return -EIO; 146 return -EIO;
147 } 147 }
148 148
@@ -195,8 +195,8 @@ static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, u32 *ir_key,
195 /* <dev> is needed to access GPIO. Used by the saa_readl macro. */ 195 /* <dev> is needed to access GPIO. Used by the saa_readl macro. */
196 struct saa7134_dev *dev = ir->c->adapter->algo_data; 196 struct saa7134_dev *dev = ir->c->adapter->algo_data;
197 if (dev == NULL) { 197 if (dev == NULL) {
198 dprintk("get_key_msi_tvanywhere_plus: " 198 i2cdprintk("get_key_msi_tvanywhere_plus: "
199 "gir->c->adapter->algo_data is NULL!\n"); 199 "ir->c->adapter->algo_data is NULL!\n");
200 return -EIO; 200 return -EIO;
201 } 201 }
202 202
@@ -657,12 +657,19 @@ int saa7134_input_init1(struct saa7134_dev *dev)
657 saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4); 657 saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4);
658 break; 658 break;
659 case SAA7134_BOARD_AVERMEDIA_M135A: 659 case SAA7134_BOARD_AVERMEDIA_M135A:
660 ir_codes = RC_MAP_AVERMEDIA_M135A_RM_JX; 660 ir_codes = RC_MAP_AVERMEDIA_M135A;
661 mask_keydown = 0x0040000; /* Enable GPIO18 line on both edges */ 661 mask_keydown = 0x0040000; /* Enable GPIO18 line on both edges */
662 mask_keyup = 0x0040000; 662 mask_keyup = 0x0040000;
663 mask_keycode = 0xffff; 663 mask_keycode = 0xffff;
664 raw_decode = 1; 664 raw_decode = 1;
665 break; 665 break;
666 case SAA7134_BOARD_AVERMEDIA_M733A:
667 ir_codes = RC_MAP_AVERMEDIA_M733A_RM_K6;
668 mask_keydown = 0x0040000;
669 mask_keyup = 0x0040000;
670 mask_keycode = 0xffff;
671 raw_decode = 1;
672 break;
666 case SAA7134_BOARD_AVERMEDIA_777: 673 case SAA7134_BOARD_AVERMEDIA_777:
667 case SAA7134_BOARD_AVERMEDIA_A16AR: 674 case SAA7134_BOARD_AVERMEDIA_A16AR:
668 ir_codes = RC_MAP_AVERMEDIA; 675 ir_codes = RC_MAP_AVERMEDIA;
@@ -815,7 +822,6 @@ int saa7134_input_init1(struct saa7134_dev *dev)
815 mask_keyup = 0x020000; 822 mask_keyup = 0x020000;
816 polling = 50; /* ms */ 823 polling = 50; /* ms */
817 break; 824 break;
818 break;
819 } 825 }
820 if (NULL == ir_codes) { 826 if (NULL == ir_codes) {
821 printk("%s: Oops: IR config error [card=%d]\n", 827 printk("%s: Oops: IR config error [card=%d]\n",
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index 3962534267be..756a1ca8833d 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -303,6 +303,7 @@ struct saa7134_format {
303#define SAA7134_BOARD_HAWELL_HW_404M7 177 303#define SAA7134_BOARD_HAWELL_HW_404M7 177
304#define SAA7134_BOARD_BEHOLD_H7 178 304#define SAA7134_BOARD_BEHOLD_H7 178
305#define SAA7134_BOARD_BEHOLD_A7 179 305#define SAA7134_BOARD_BEHOLD_A7 179
306#define SAA7134_BOARD_AVERMEDIA_M733A 180
306 307
307#define SAA7134_MAXBOARDS 32 308#define SAA7134_MAXBOARDS 32
308#define SAA7134_INPUT_MAX 8 309#define SAA7134_INPUT_MAX 8
diff --git a/drivers/media/video/saa717x.c b/drivers/media/video/saa717x.c
index d521c648e157..78d69950c00a 100644
--- a/drivers/media/video/saa717x.c
+++ b/drivers/media/video/saa717x.c
@@ -1199,28 +1199,32 @@ static int saa717x_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *
1199} 1199}
1200#endif 1200#endif
1201 1201
1202static int saa717x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) 1202static int saa717x_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
1203{ 1203{
1204 struct v4l2_pix_format *pix;
1205 int prescale, h_scale, v_scale; 1204 int prescale, h_scale, v_scale;
1206 1205
1207 pix = &fmt->fmt.pix;
1208 v4l2_dbg(1, debug, sd, "decoder set size\n"); 1206 v4l2_dbg(1, debug, sd, "decoder set size\n");
1209 1207
1208 if (fmt->code != V4L2_MBUS_FMT_FIXED)
1209 return -EINVAL;
1210
1210 /* FIXME need better bounds checking here */ 1211 /* FIXME need better bounds checking here */
1211 if (pix->width < 1 || pix->width > 1440) 1212 if (fmt->width < 1 || fmt->width > 1440)
1212 return -EINVAL; 1213 return -EINVAL;
1213 if (pix->height < 1 || pix->height > 960) 1214 if (fmt->height < 1 || fmt->height > 960)
1214 return -EINVAL; 1215 return -EINVAL;
1215 1216
1217 fmt->field = V4L2_FIELD_INTERLACED;
1218 fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
1219
1216 /* scaling setting */ 1220 /* scaling setting */
1217 /* NTSC and interlace only */ 1221 /* NTSC and interlace only */
1218 prescale = SAA717X_NTSC_WIDTH / pix->width; 1222 prescale = SAA717X_NTSC_WIDTH / fmt->width;
1219 if (prescale == 0) 1223 if (prescale == 0)
1220 prescale = 1; 1224 prescale = 1;
1221 h_scale = 1024 * SAA717X_NTSC_WIDTH / prescale / pix->width; 1225 h_scale = 1024 * SAA717X_NTSC_WIDTH / prescale / fmt->width;
1222 /* interlace */ 1226 /* interlace */
1223 v_scale = 512 * 2 * SAA717X_NTSC_HEIGHT / pix->height; 1227 v_scale = 512 * 2 * SAA717X_NTSC_HEIGHT / fmt->height;
1224 1228
1225 /* Horizontal prescaling etc */ 1229 /* Horizontal prescaling etc */
1226 set_h_prescale(sd, 0, prescale); 1230 set_h_prescale(sd, 0, prescale);
@@ -1241,19 +1245,19 @@ static int saa717x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
1241 /* set video output size */ 1245 /* set video output size */
1242 /* video number of pixels at output */ 1246 /* video number of pixels at output */
1243 /* TASK A */ 1247 /* TASK A */
1244 saa717x_write(sd, 0x5C, (u8)(pix->width & 0xFF)); 1248 saa717x_write(sd, 0x5C, (u8)(fmt->width & 0xFF));
1245 saa717x_write(sd, 0x5D, (u8)((pix->width >> 8) & 0xFF)); 1249 saa717x_write(sd, 0x5D, (u8)((fmt->width >> 8) & 0xFF));
1246 /* TASK B */ 1250 /* TASK B */
1247 saa717x_write(sd, 0x9C, (u8)(pix->width & 0xFF)); 1251 saa717x_write(sd, 0x9C, (u8)(fmt->width & 0xFF));
1248 saa717x_write(sd, 0x9D, (u8)((pix->width >> 8) & 0xFF)); 1252 saa717x_write(sd, 0x9D, (u8)((fmt->width >> 8) & 0xFF));
1249 1253
1250 /* video number of lines at output */ 1254 /* video number of lines at output */
1251 /* TASK A */ 1255 /* TASK A */
1252 saa717x_write(sd, 0x5E, (u8)(pix->height & 0xFF)); 1256 saa717x_write(sd, 0x5E, (u8)(fmt->height & 0xFF));
1253 saa717x_write(sd, 0x5F, (u8)((pix->height >> 8) & 0xFF)); 1257 saa717x_write(sd, 0x5F, (u8)((fmt->height >> 8) & 0xFF));
1254 /* TASK B */ 1258 /* TASK B */
1255 saa717x_write(sd, 0x9E, (u8)(pix->height & 0xFF)); 1259 saa717x_write(sd, 0x9E, (u8)(fmt->height & 0xFF));
1256 saa717x_write(sd, 0x9F, (u8)((pix->height >> 8) & 0xFF)); 1260 saa717x_write(sd, 0x9F, (u8)((fmt->height >> 8) & 0xFF));
1257 return 0; 1261 return 0;
1258} 1262}
1259 1263
@@ -1403,7 +1407,7 @@ static const struct v4l2_subdev_tuner_ops saa717x_tuner_ops = {
1403 1407
1404static const struct v4l2_subdev_video_ops saa717x_video_ops = { 1408static const struct v4l2_subdev_video_ops saa717x_video_ops = {
1405 .s_routing = saa717x_s_video_routing, 1409 .s_routing = saa717x_s_video_routing,
1406 .s_fmt = saa717x_s_fmt, 1410 .s_mbus_fmt = saa717x_s_mbus_fmt,
1407 .s_stream = saa717x_s_stream, 1411 .s_stream = saa717x_s_stream,
1408}; 1412};
1409 1413
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
index 4ac3b482fbb4..961bfa2fea97 100644
--- a/drivers/media/video/sh_mobile_ceu_camera.c
+++ b/drivers/media/video/sh_mobile_ceu_camera.c
@@ -878,7 +878,7 @@ static bool sh_mobile_ceu_packing_supported(const struct soc_mbus_pixelfmt *fmt)
878 878
879static int client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect); 879static int client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect);
880 880
881static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, 881static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, unsigned int idx,
882 struct soc_camera_format_xlate *xlate) 882 struct soc_camera_format_xlate *xlate)
883{ 883{
884 struct v4l2_subdev *sd = soc_camera_to_subdev(icd); 884 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,
897 fmt = soc_mbus_get_fmtdesc(code); 897 fmt = soc_mbus_get_fmtdesc(code);
898 if (!fmt) { 898 if (!fmt) {
899 dev_err(icd->dev.parent, 899 dev_err(icd->dev.parent,
900 "Invalid format code #%d: %d\n", idx, code); 900 "Invalid format code #%u: %d\n", idx, code);
901 return -EINVAL; 901 return -EINVAL;
902 } 902 }
903 903
diff --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/video/sn9c102/sn9c102_devtable.h
index 522ba3f4c285..b6643ca7656a 100644
--- a/drivers/media/video/sn9c102/sn9c102_devtable.h
+++ b/drivers/media/video/sn9c102/sn9c102_devtable.h
@@ -62,8 +62,8 @@ static const struct usb_device_id sn9c102_id_table[] = {
62#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE 62#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE
63 { SN9C102_USB_DEVICE(0x0c45, 0x602c, BRIDGE_SN9C102), }, 63 { SN9C102_USB_DEVICE(0x0c45, 0x602c, BRIDGE_SN9C102), },
64/* { SN9C102_USB_DEVICE(0x0c45, 0x602d, BRIDGE_SN9C102), }, HV7131R */ 64/* { SN9C102_USB_DEVICE(0x0c45, 0x602d, BRIDGE_SN9C102), }, HV7131R */
65#endif
66 { SN9C102_USB_DEVICE(0x0c45, 0x602e, BRIDGE_SN9C102), }, 65 { SN9C102_USB_DEVICE(0x0c45, 0x602e, BRIDGE_SN9C102), },
66#endif
67 { SN9C102_USB_DEVICE(0x0c45, 0x6030, BRIDGE_SN9C102), }, 67 { SN9C102_USB_DEVICE(0x0c45, 0x6030, BRIDGE_SN9C102), },
68 /* SN9C103 */ 68 /* SN9C103 */
69 { SN9C102_USB_DEVICE(0x0c45, 0x6080, BRIDGE_SN9C103), }, 69 { SN9C102_USB_DEVICE(0x0c45, 0x6080, BRIDGE_SN9C103), },
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
index db1ca0e90d76..475757bfd7ba 100644
--- a/drivers/media/video/soc_camera.c
+++ b/drivers/media/video/soc_camera.c
@@ -200,7 +200,8 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd)
200{ 200{
201 struct v4l2_subdev *sd = soc_camera_to_subdev(icd); 201 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
202 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); 202 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
203 int i, fmts = 0, raw_fmts = 0, ret; 203 unsigned int i, fmts = 0, raw_fmts = 0;
204 int ret;
204 enum v4l2_mbus_pixelcode code; 205 enum v4l2_mbus_pixelcode code;
205 206
206 while (!v4l2_subdev_call(sd, video, enum_mbus_fmt, raw_fmts, &code)) 207 while (!v4l2_subdev_call(sd, video, enum_mbus_fmt, raw_fmts, &code))
diff --git a/drivers/media/video/soc_camera_platform.c b/drivers/media/video/soc_camera_platform.c
index 10b003a8be83..248c986f0989 100644
--- a/drivers/media/video/soc_camera_platform.c
+++ b/drivers/media/video/soc_camera_platform.c
@@ -71,7 +71,7 @@ static int soc_camera_platform_try_fmt(struct v4l2_subdev *sd,
71 71
72static struct v4l2_subdev_core_ops platform_subdev_core_ops; 72static struct v4l2_subdev_core_ops platform_subdev_core_ops;
73 73
74static int soc_camera_platform_enum_fmt(struct v4l2_subdev *sd, int index, 74static int soc_camera_platform_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
75 enum v4l2_mbus_pixelcode *code) 75 enum v4l2_mbus_pixelcode *code)
76{ 76{
77 struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd); 77 struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd);
diff --git a/drivers/media/video/tcm825x.c b/drivers/media/video/tcm825x.c
index b90e9da3167d..54681a535822 100644
--- a/drivers/media/video/tcm825x.c
+++ b/drivers/media/video/tcm825x.c
@@ -850,7 +850,6 @@ static int tcm825x_probe(struct i2c_client *client,
850 const struct i2c_device_id *did) 850 const struct i2c_device_id *did)
851{ 851{
852 struct tcm825x_sensor *sensor = &tcm825x; 852 struct tcm825x_sensor *sensor = &tcm825x;
853 int rval;
854 853
855 if (i2c_get_clientdata(client)) 854 if (i2c_get_clientdata(client))
856 return -EBUSY; 855 return -EBUSY;
@@ -871,11 +870,7 @@ static int tcm825x_probe(struct i2c_client *client,
871 sensor->pix.height = tcm825x_sizes[QVGA].height; 870 sensor->pix.height = tcm825x_sizes[QVGA].height;
872 sensor->pix.pixelformat = V4L2_PIX_FMT_RGB565; 871 sensor->pix.pixelformat = V4L2_PIX_FMT_RGB565;
873 872
874 rval = v4l2_int_device_register(sensor->v4l2_int_device); 873 return v4l2_int_device_register(sensor->v4l2_int_device);
875 if (rval)
876 i2c_set_clientdata(client, NULL);
877
878 return rval;
879} 874}
880 875
881static int tcm825x_remove(struct i2c_client *client) 876static int tcm825x_remove(struct i2c_client *client)
@@ -886,7 +881,6 @@ static int tcm825x_remove(struct i2c_client *client)
886 return -ENODEV; /* our client isn't attached */ 881 return -ENODEV; /* our client isn't attached */
887 882
888 v4l2_int_device_unregister(sensor->v4l2_int_device); 883 v4l2_int_device_unregister(sensor->v4l2_int_device);
889 i2c_set_clientdata(client, NULL);
890 884
891 return 0; 885 return 0;
892} 886}
diff --git a/drivers/media/video/tvp514x.c b/drivers/media/video/tvp514x.c
index e826114b7fb8..71c73fa0d68c 100644
--- a/drivers/media/video/tvp514x.c
+++ b/drivers/media/video/tvp514x.c
@@ -88,9 +88,6 @@ static int tvp514x_s_stream(struct v4l2_subdev *sd, int enable);
88 * @pdata: Board specific 88 * @pdata: Board specific
89 * @ver: Chip version 89 * @ver: Chip version
90 * @streaming: TVP5146/47 decoder streaming - enabled or disabled. 90 * @streaming: TVP5146/47 decoder streaming - enabled or disabled.
91 * @pix: Current pixel format
92 * @num_fmts: Number of formats
93 * @fmt_list: Format list
94 * @current_std: Current standard 91 * @current_std: Current standard
95 * @num_stds: Number of standards 92 * @num_stds: Number of standards
96 * @std_list: Standards list 93 * @std_list: Standards list
@@ -105,13 +102,9 @@ struct tvp514x_decoder {
105 int ver; 102 int ver;
106 int streaming; 103 int streaming;
107 104
108 struct v4l2_pix_format pix;
109 int num_fmts;
110 const struct v4l2_fmtdesc *fmt_list;
111
112 enum tvp514x_std current_std; 105 enum tvp514x_std current_std;
113 int num_stds; 106 int num_stds;
114 struct tvp514x_std_info *std_list; 107 const struct tvp514x_std_info *std_list;
115 /* Input and Output Routing parameters */ 108 /* Input and Output Routing parameters */
116 u32 input; 109 u32 input;
117 u32 output; 110 u32 output;
@@ -203,27 +196,12 @@ static struct tvp514x_reg tvp514x_reg_list_default[] = {
203}; 196};
204 197
205/** 198/**
206 * List of image formats supported by TVP5146/47 decoder
207 * Currently we are using 8 bit mode only, but can be
208 * extended to 10/20 bit mode.
209 */
210static const struct v4l2_fmtdesc tvp514x_fmt_list[] = {
211 {
212 .index = 0,
213 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
214 .flags = 0,
215 .description = "8-bit UYVY 4:2:2 Format",
216 .pixelformat = V4L2_PIX_FMT_UYVY,
217 },
218};
219
220/**
221 * Supported standards - 199 * Supported standards -
222 * 200 *
223 * Currently supports two standards only, need to add support for rest of the 201 * Currently supports two standards only, need to add support for rest of the
224 * modes, like SECAM, etc... 202 * modes, like SECAM, etc...
225 */ 203 */
226static struct tvp514x_std_info tvp514x_std_list[] = { 204static const struct tvp514x_std_info tvp514x_std_list[] = {
227 /* Standard: STD_NTSC_MJ */ 205 /* Standard: STD_NTSC_MJ */
228 [STD_NTSC_MJ] = { 206 [STD_NTSC_MJ] = {
229 .width = NTSC_NUM_ACTIVE_PIXELS, 207 .width = NTSC_NUM_ACTIVE_PIXELS,
@@ -366,13 +344,13 @@ static int tvp514x_write_regs(struct v4l2_subdev *sd,
366} 344}
367 345
368/** 346/**
369 * tvp514x_get_current_std() : Get the current standard detected by TVP5146/47 347 * tvp514x_query_current_std() : Query the current standard detected by TVP5146/47
370 * @sd: ptr to v4l2_subdev struct 348 * @sd: ptr to v4l2_subdev struct
371 * 349 *
372 * Get current standard detected by TVP5146/47, STD_INVALID if there is no 350 * Returns the current standard detected by TVP5146/47, STD_INVALID if there is no
373 * standard detected. 351 * standard detected.
374 */ 352 */
375static enum tvp514x_std tvp514x_get_current_std(struct v4l2_subdev *sd) 353static enum tvp514x_std tvp514x_query_current_std(struct v4l2_subdev *sd)
376{ 354{
377 u8 std, std_status; 355 u8 std, std_status;
378 356
@@ -518,7 +496,7 @@ static int tvp514x_detect(struct v4l2_subdev *sd,
518 * @std_id: standard V4L2 std_id ioctl enum 496 * @std_id: standard V4L2 std_id ioctl enum
519 * 497 *
520 * Returns the current standard detected by TVP5146/47. If no active input is 498 * Returns the current standard detected by TVP5146/47. If no active input is
521 * detected, returns -EINVAL 499 * detected then *std_id is set to 0 and the function returns 0.
522 */ 500 */
523static int tvp514x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id) 501static int tvp514x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
524{ 502{
@@ -530,10 +508,12 @@ static int tvp514x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
530 if (std_id == NULL) 508 if (std_id == NULL)
531 return -EINVAL; 509 return -EINVAL;
532 510
533 /* get the current standard */ 511 *std_id = V4L2_STD_UNKNOWN;
534 current_std = tvp514x_get_current_std(sd); 512
513 /* query the current standard */
514 current_std = tvp514x_query_current_std(sd);
535 if (current_std == STD_INVALID) 515 if (current_std == STD_INVALID)
536 return -EINVAL; 516 return 0;
537 517
538 input_sel = decoder->input; 518 input_sel = decoder->input;
539 519
@@ -575,12 +555,11 @@ static int tvp514x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
575 /* check whether signal is locked */ 555 /* check whether signal is locked */
576 sync_lock_status = tvp514x_read_reg(sd, REG_STATUS1); 556 sync_lock_status = tvp514x_read_reg(sd, REG_STATUS1);
577 if (lock_mask != (sync_lock_status & lock_mask)) 557 if (lock_mask != (sync_lock_status & lock_mask))
578 return -EINVAL; /* No input detected */ 558 return 0; /* No input detected */
579 559
580 decoder->current_std = current_std;
581 *std_id = decoder->std_list[current_std].standard.id; 560 *std_id = decoder->std_list[current_std].standard.id;
582 561
583 v4l2_dbg(1, debug, sd, "Current STD: %s", 562 v4l2_dbg(1, debug, sd, "Current STD: %s\n",
584 decoder->std_list[current_std].standard.name); 563 decoder->std_list[current_std].standard.name);
585 return 0; 564 return 0;
586} 565}
@@ -614,7 +593,7 @@ static int tvp514x_s_std(struct v4l2_subdev *sd, v4l2_std_id std_id)
614 decoder->tvp514x_regs[REG_VIDEO_STD].val = 593 decoder->tvp514x_regs[REG_VIDEO_STD].val =
615 decoder->std_list[i].video_std; 594 decoder->std_list[i].video_std;
616 595
617 v4l2_dbg(1, debug, sd, "Standard set to: %s", 596 v4l2_dbg(1, debug, sd, "Standard set to: %s\n",
618 decoder->std_list[i].standard.name); 597 decoder->std_list[i].standard.name);
619 return 0; 598 return 0;
620} 599}
@@ -637,7 +616,6 @@ static int tvp514x_s_routing(struct v4l2_subdev *sd,
637 int err; 616 int err;
638 enum tvp514x_input input_sel; 617 enum tvp514x_input input_sel;
639 enum tvp514x_output output_sel; 618 enum tvp514x_output output_sel;
640 enum tvp514x_std current_std = STD_INVALID;
641 u8 sync_lock_status, lock_mask; 619 u8 sync_lock_status, lock_mask;
642 int try_count = LOCK_RETRY_COUNT; 620 int try_count = LOCK_RETRY_COUNT;
643 621
@@ -721,11 +699,6 @@ static int tvp514x_s_routing(struct v4l2_subdev *sd,
721 /* Allow decoder to sync up with new input */ 699 /* Allow decoder to sync up with new input */
722 msleep(LOCK_RETRY_DELAY); 700 msleep(LOCK_RETRY_DELAY);
723 701
724 /* get the current standard for future reference */
725 current_std = tvp514x_get_current_std(sd);
726 if (current_std == STD_INVALID)
727 continue;
728
729 sync_lock_status = tvp514x_read_reg(sd, 702 sync_lock_status = tvp514x_read_reg(sd,
730 REG_STATUS1); 703 REG_STATUS1);
731 if (lock_mask == (sync_lock_status & lock_mask)) 704 if (lock_mask == (sync_lock_status & lock_mask))
@@ -733,15 +706,13 @@ static int tvp514x_s_routing(struct v4l2_subdev *sd,
733 break; 706 break;
734 } 707 }
735 708
736 if ((current_std == STD_INVALID) || (try_count < 0)) 709 if (try_count < 0)
737 return -EINVAL; 710 return -EINVAL;
738 711
739 decoder->current_std = current_std;
740 decoder->input = input; 712 decoder->input = input;
741 decoder->output = output; 713 decoder->output = output;
742 714
743 v4l2_dbg(1, debug, sd, "Input set to: %d, std : %d", 715 v4l2_dbg(1, debug, sd, "Input set to: %d\n", input_sel);
744 input_sel, current_std);
745 716
746 return 0; 717 return 0;
747} 718}
@@ -794,7 +765,7 @@ tvp514x_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qctrl)
794 return err; 765 return err;
795 } 766 }
796 767
797 v4l2_dbg(1, debug, sd, "Query Control:%s: Min - %d, Max - %d, Def - %d", 768 v4l2_dbg(1, debug, sd, "Query Control:%s: Min - %d, Max - %d, Def - %d\n",
798 qctrl->name, qctrl->minimum, qctrl->maximum, 769 qctrl->name, qctrl->minimum, qctrl->maximum,
799 qctrl->default_value); 770 qctrl->default_value);
800 771
@@ -851,7 +822,7 @@ tvp514x_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
851 return -EINVAL; 822 return -EINVAL;
852 } 823 }
853 824
854 v4l2_dbg(1, debug, sd, "Get Control: ID - %d - %d", 825 v4l2_dbg(1, debug, sd, "Get Control: ID - %d - %d\n",
855 ctrl->id, ctrl->value); 826 ctrl->id, ctrl->value);
856 return 0; 827 return 0;
857} 828}
@@ -951,7 +922,7 @@ tvp514x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
951 return err; 922 return err;
952 } 923 }
953 924
954 v4l2_dbg(1, debug, sd, "Set Control: ID - %d - %d", 925 v4l2_dbg(1, debug, sd, "Set Control: ID - %d - %d\n",
955 ctrl->id, ctrl->value); 926 ctrl->id, ctrl->value);
956 927
957 return err; 928 return err;
@@ -967,44 +938,33 @@ tvp514x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
967static int 938static int
968tvp514x_enum_fmt_cap(struct v4l2_subdev *sd, struct v4l2_fmtdesc *fmt) 939tvp514x_enum_fmt_cap(struct v4l2_subdev *sd, struct v4l2_fmtdesc *fmt)
969{ 940{
970 struct tvp514x_decoder *decoder = to_decoder(sd); 941 if (fmt == NULL || fmt->index)
971 int index;
972
973 if (fmt == NULL)
974 return -EINVAL;
975
976 index = fmt->index;
977 if ((index >= decoder->num_fmts) || (index < 0))
978 /* Index out of bound */
979 return -EINVAL; 942 return -EINVAL;
980 943
981 if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 944 if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
982 /* only capture is supported */ 945 /* only capture is supported */
983 return -EINVAL; 946 return -EINVAL;
984 947
985 memcpy(fmt, &decoder->fmt_list[index], 948 /* only one format */
986 sizeof(struct v4l2_fmtdesc)); 949 fmt->flags = 0;
987 950 strlcpy(fmt->description, "8-bit UYVY 4:2:2 Format",
988 v4l2_dbg(1, debug, sd, "Current FMT: index - %d (%s)", 951 sizeof(fmt->description));
989 decoder->fmt_list[index].index, 952 fmt->pixelformat = V4L2_PIX_FMT_UYVY;
990 decoder->fmt_list[index].description);
991 return 0; 953 return 0;
992} 954}
993 955
994/** 956/**
995 * tvp514x_try_fmt_cap() - V4L2 decoder interface handler for try_fmt 957 * tvp514x_fmt_cap() - V4L2 decoder interface handler for try/s/g_fmt
996 * @sd: pointer to standard V4L2 sub-device structure 958 * @sd: pointer to standard V4L2 sub-device structure
997 * @f: pointer to standard V4L2 VIDIOC_TRY_FMT ioctl structure 959 * @f: pointer to standard V4L2 VIDIOC_TRY_FMT ioctl structure
998 * 960 *
999 * Implement the VIDIOC_TRY_FMT ioctl for the CAPTURE buffer type. This 961 * Implement the VIDIOC_TRY/S/G_FMT ioctl for the CAPTURE buffer type. This
1000 * ioctl is used to negotiate the image capture size and pixel format 962 * ioctl is used to negotiate the image capture size and pixel format.
1001 * without actually making it take effect.
1002 */ 963 */
1003static int 964static int
1004tvp514x_try_fmt_cap(struct v4l2_subdev *sd, struct v4l2_format *f) 965tvp514x_fmt_cap(struct v4l2_subdev *sd, struct v4l2_format *f)
1005{ 966{
1006 struct tvp514x_decoder *decoder = to_decoder(sd); 967 struct tvp514x_decoder *decoder = to_decoder(sd);
1007 int ifmt;
1008 struct v4l2_pix_format *pix; 968 struct v4l2_pix_format *pix;
1009 enum tvp514x_std current_std; 969 enum tvp514x_std current_std;
1010 970
@@ -1012,106 +972,30 @@ tvp514x_try_fmt_cap(struct v4l2_subdev *sd, struct v4l2_format *f)
1012 return -EINVAL; 972 return -EINVAL;
1013 973
1014 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 974 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1015 /* only capture is supported */ 975 return -EINVAL;
1016 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1017 976
1018 pix = &f->fmt.pix; 977 pix = &f->fmt.pix;
1019 978
1020 /* Calculate height and width based on current standard */ 979 /* Calculate height and width based on current standard */
1021 current_std = tvp514x_get_current_std(sd); 980 current_std = decoder->current_std;
1022 if (current_std == STD_INVALID)
1023 return -EINVAL;
1024 981
1025 decoder->current_std = current_std; 982 pix->pixelformat = V4L2_PIX_FMT_UYVY;
1026 pix->width = decoder->std_list[current_std].width; 983 pix->width = decoder->std_list[current_std].width;
1027 pix->height = decoder->std_list[current_std].height; 984 pix->height = decoder->std_list[current_std].height;
1028
1029 for (ifmt = 0; ifmt < decoder->num_fmts; ifmt++) {
1030 if (pix->pixelformat ==
1031 decoder->fmt_list[ifmt].pixelformat)
1032 break;
1033 }
1034 if (ifmt == decoder->num_fmts)
1035 /* None of the format matched, select default */
1036 ifmt = 0;
1037 pix->pixelformat = decoder->fmt_list[ifmt].pixelformat;
1038
1039 pix->field = V4L2_FIELD_INTERLACED; 985 pix->field = V4L2_FIELD_INTERLACED;
1040 pix->bytesperline = pix->width * 2; 986 pix->bytesperline = pix->width * 2;
1041 pix->sizeimage = pix->bytesperline * pix->height; 987 pix->sizeimage = pix->bytesperline * pix->height;
1042 pix->colorspace = V4L2_COLORSPACE_SMPTE170M; 988 pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
1043 pix->priv = 0; 989 pix->priv = 0;
1044 990
1045 v4l2_dbg(1, debug, sd, "Try FMT: pixelformat - %s, bytesperline - %d" 991 v4l2_dbg(1, debug, sd, "FMT: bytesperline - %d"
1046 "Width - %d, Height - %d", 992 "Width - %d, Height - %d\n",
1047 decoder->fmt_list[ifmt].description, pix->bytesperline, 993 pix->bytesperline,
1048 pix->width, pix->height); 994 pix->width, pix->height);
1049 return 0; 995 return 0;
1050} 996}
1051 997
1052/** 998/**
1053 * tvp514x_s_fmt_cap() - V4L2 decoder interface handler for s_fmt
1054 * @sd: pointer to standard V4L2 sub-device structure
1055 * @f: pointer to standard V4L2 VIDIOC_S_FMT ioctl structure
1056 *
1057 * If the requested format is supported, configures the HW to use that
1058 * format, returns error code if format not supported or HW can't be
1059 * correctly configured.
1060 */
1061static int
1062tvp514x_s_fmt_cap(struct v4l2_subdev *sd, struct v4l2_format *f)
1063{
1064 struct tvp514x_decoder *decoder = to_decoder(sd);
1065 struct v4l2_pix_format *pix;
1066 int rval;
1067
1068 if (f == NULL)
1069 return -EINVAL;
1070
1071 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1072 /* only capture is supported */
1073 return -EINVAL;
1074
1075 pix = &f->fmt.pix;
1076 rval = tvp514x_try_fmt_cap(sd, f);
1077 if (rval)
1078 return rval;
1079
1080 decoder->pix = *pix;
1081
1082 return rval;
1083}
1084
1085/**
1086 * tvp514x_g_fmt_cap() - V4L2 decoder interface handler for tvp514x_g_fmt_cap
1087 * @sd: pointer to standard V4L2 sub-device structure
1088 * @f: pointer to standard V4L2 v4l2_format structure
1089 *
1090 * Returns the decoder's current pixel format in the v4l2_format
1091 * parameter.
1092 */
1093static int
1094tvp514x_g_fmt_cap(struct v4l2_subdev *sd, struct v4l2_format *f)
1095{
1096 struct tvp514x_decoder *decoder = to_decoder(sd);
1097
1098 if (f == NULL)
1099 return -EINVAL;
1100
1101 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1102 /* only capture is supported */
1103 return -EINVAL;
1104
1105 f->fmt.pix = decoder->pix;
1106
1107 v4l2_dbg(1, debug, sd, "Current FMT: bytesperline - %d"
1108 "Width - %d, Height - %d",
1109 decoder->pix.bytesperline,
1110 decoder->pix.width, decoder->pix.height);
1111 return 0;
1112}
1113
1114/**
1115 * tvp514x_g_parm() - V4L2 decoder interface handler for g_parm 999 * tvp514x_g_parm() - V4L2 decoder interface handler for g_parm
1116 * @sd: pointer to standard V4L2 sub-device structure 1000 * @sd: pointer to standard V4L2 sub-device structure
1117 * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure 1001 * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure
@@ -1132,15 +1016,8 @@ tvp514x_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a)
1132 /* only capture is supported */ 1016 /* only capture is supported */
1133 return -EINVAL; 1017 return -EINVAL;
1134 1018
1135 memset(a, 0, sizeof(*a));
1136 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1137
1138 /* get the current standard */ 1019 /* get the current standard */
1139 current_std = tvp514x_get_current_std(sd); 1020 current_std = decoder->current_std;
1140 if (current_std == STD_INVALID)
1141 return -EINVAL;
1142
1143 decoder->current_std = current_std;
1144 1021
1145 cparm = &a->parm.capture; 1022 cparm = &a->parm.capture;
1146 cparm->capability = V4L2_CAP_TIMEPERFRAME; 1023 cparm->capability = V4L2_CAP_TIMEPERFRAME;
@@ -1175,11 +1052,7 @@ tvp514x_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a)
1175 timeperframe = &a->parm.capture.timeperframe; 1052 timeperframe = &a->parm.capture.timeperframe;
1176 1053
1177 /* get the current standard */ 1054 /* get the current standard */
1178 current_std = tvp514x_get_current_std(sd); 1055 current_std = decoder->current_std;
1179 if (current_std == STD_INVALID)
1180 return -EINVAL;
1181
1182 decoder->current_std = current_std;
1183 1056
1184 *timeperframe = 1057 *timeperframe =
1185 decoder->std_list[current_std].standard.frameperiod; 1058 decoder->std_list[current_std].standard.frameperiod;
@@ -1259,9 +1132,9 @@ static const struct v4l2_subdev_video_ops tvp514x_video_ops = {
1259 .s_routing = tvp514x_s_routing, 1132 .s_routing = tvp514x_s_routing,
1260 .querystd = tvp514x_querystd, 1133 .querystd = tvp514x_querystd,
1261 .enum_fmt = tvp514x_enum_fmt_cap, 1134 .enum_fmt = tvp514x_enum_fmt_cap,
1262 .g_fmt = tvp514x_g_fmt_cap, 1135 .g_fmt = tvp514x_fmt_cap,
1263 .try_fmt = tvp514x_try_fmt_cap, 1136 .try_fmt = tvp514x_fmt_cap,
1264 .s_fmt = tvp514x_s_fmt_cap, 1137 .s_fmt = tvp514x_fmt_cap,
1265 .g_parm = tvp514x_g_parm, 1138 .g_parm = tvp514x_g_parm,
1266 .s_parm = tvp514x_s_parm, 1139 .s_parm = tvp514x_s_parm,
1267 .s_stream = tvp514x_s_stream, 1140 .s_stream = tvp514x_s_stream,
@@ -1274,22 +1147,6 @@ static const struct v4l2_subdev_ops tvp514x_ops = {
1274 1147
1275static struct tvp514x_decoder tvp514x_dev = { 1148static struct tvp514x_decoder tvp514x_dev = {
1276 .streaming = 0, 1149 .streaming = 0,
1277
1278 .fmt_list = tvp514x_fmt_list,
1279 .num_fmts = ARRAY_SIZE(tvp514x_fmt_list),
1280
1281 .pix = {
1282 /* Default to NTSC 8-bit YUV 422 */
1283 .width = NTSC_NUM_ACTIVE_PIXELS,
1284 .height = NTSC_NUM_ACTIVE_LINES,
1285 .pixelformat = V4L2_PIX_FMT_UYVY,
1286 .field = V4L2_FIELD_INTERLACED,
1287 .bytesperline = NTSC_NUM_ACTIVE_PIXELS * 2,
1288 .sizeimage =
1289 NTSC_NUM_ACTIVE_PIXELS * 2 * NTSC_NUM_ACTIVE_LINES,
1290 .colorspace = V4L2_COLORSPACE_SMPTE170M,
1291 },
1292
1293 .current_std = STD_NTSC_MJ, 1150 .current_std = STD_NTSC_MJ,
1294 .std_list = tvp514x_std_list, 1151 .std_list = tvp514x_std_list,
1295 .num_stds = ARRAY_SIZE(tvp514x_std_list), 1152 .num_stds = ARRAY_SIZE(tvp514x_std_list),
diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c
index 47f0582d50a5..1654f65cca7c 100644
--- a/drivers/media/video/tvp5150.c
+++ b/drivers/media/video/tvp5150.c
@@ -934,17 +934,6 @@ static int tvp5150_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f
934 return 0; 934 return 0;
935} 935}
936 936
937static int tvp5150_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
938{
939 switch (fmt->type) {
940 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
941 return tvp5150_s_sliced_fmt(sd, &fmt->fmt.sliced);
942
943 default:
944 return -EINVAL;
945 }
946}
947
948static int tvp5150_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi) 937static int tvp5150_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi)
949{ 938{
950 int i, mask = 0; 939 int i, mask = 0;
@@ -960,13 +949,6 @@ static int tvp5150_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f
960 return 0; 949 return 0;
961} 950}
962 951
963static int tvp5150_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
964{
965 if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
966 return -EINVAL;
967 return tvp5150_g_sliced_fmt(sd, &fmt->fmt.sliced);
968}
969
970static int tvp5150_g_chip_ident(struct v4l2_subdev *sd, 952static int tvp5150_g_chip_ident(struct v4l2_subdev *sd,
971 struct v4l2_dbg_chip_ident *chip) 953 struct v4l2_dbg_chip_ident *chip)
972{ 954{
@@ -1054,8 +1036,6 @@ static const struct v4l2_subdev_tuner_ops tvp5150_tuner_ops = {
1054 1036
1055static const struct v4l2_subdev_video_ops tvp5150_video_ops = { 1037static const struct v4l2_subdev_video_ops tvp5150_video_ops = {
1056 .s_routing = tvp5150_s_routing, 1038 .s_routing = tvp5150_s_routing,
1057 .g_fmt = tvp5150_g_fmt,
1058 .s_fmt = tvp5150_s_fmt,
1059}; 1039};
1060 1040
1061static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = { 1041static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = {
diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c
index 76be733eabfd..445dc93413e3 100644
--- a/drivers/media/video/tw9910.c
+++ b/drivers/media/video/tw9910.c
@@ -903,7 +903,7 @@ static struct v4l2_subdev_core_ops tw9910_subdev_core_ops = {
903#endif 903#endif
904}; 904};
905 905
906static int tw9910_enum_fmt(struct v4l2_subdev *sd, int index, 906static int tw9910_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
907 enum v4l2_mbus_pixelcode *code) 907 enum v4l2_mbus_pixelcode *code)
908{ 908{
909 if (index) 909 if (index)
@@ -977,7 +977,6 @@ static int tw9910_probe(struct i2c_client *client,
977 ret = tw9910_video_probe(icd, client); 977 ret = tw9910_video_probe(icd, client);
978 if (ret) { 978 if (ret) {
979 icd->ops = NULL; 979 icd->ops = NULL;
980 i2c_set_clientdata(client, NULL);
981 kfree(priv); 980 kfree(priv);
982 } 981 }
983 982
@@ -990,7 +989,6 @@ static int tw9910_remove(struct i2c_client *client)
990 struct soc_camera_device *icd = client->dev.platform_data; 989 struct soc_camera_device *icd = client->dev.platform_data;
991 990
992 icd->ops = NULL; 991 icd->ops = NULL;
993 i2c_set_clientdata(client, NULL);
994 kfree(priv); 992 kfree(priv);
995 return 0; 993 return 0;
996} 994}
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c
index 6248a639ba2d..c2690df33438 100644
--- a/drivers/media/video/usbvision/usbvision-video.c
+++ b/drivers/media/video/usbvision/usbvision-video.c
@@ -1671,8 +1671,7 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf)
1671 PDEBUG(DBG_PROBE, ""); 1671 PDEBUG(DBG_PROBE, "");
1672 1672
1673 if (usbvision == NULL) { 1673 if (usbvision == NULL) {
1674 dev_err(&usbvision->dev->dev, 1674 pr_err("%s: usb_get_intfdata() failed\n", __func__);
1675 "%s: usb_get_intfdata() failed\n", __func__);
1676 return; 1675 return;
1677 } 1676 }
1678 1677
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c
index d33693c13368..c4b117f5fb70 100644
--- a/drivers/message/i2o/i2o_config.c
+++ b/drivers/message/i2o/i2o_config.c
@@ -186,14 +186,9 @@ static int i2o_cfg_parms(unsigned long arg, unsigned int type)
186 if (!dev) 186 if (!dev)
187 return -ENXIO; 187 return -ENXIO;
188 188
189 ops = kmalloc(kcmd.oplen, GFP_KERNEL); 189 ops = memdup_user(kcmd.opbuf, kcmd.oplen);
190 if (!ops) 190 if (IS_ERR(ops))
191 return -ENOMEM; 191 return PTR_ERR(ops);
192
193 if (copy_from_user(ops, kcmd.opbuf, kcmd.oplen)) {
194 kfree(ops);
195 return -EFAULT;
196 }
197 192
198 /* 193 /*
199 * It's possible to have a _very_ large table 194 * It's possible to have a _very_ large table
diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c
index 405d2d5183cf..2c65a2c57294 100644
--- a/drivers/mfd/88pm860x-core.c
+++ b/drivers/mfd/88pm860x-core.c
@@ -566,7 +566,7 @@ out:
566 return ret; 566 return ret;
567} 567}
568 568
569static void __devexit device_irq_exit(struct pm860x_chip *chip) 569static void device_irq_exit(struct pm860x_chip *chip)
570{ 570{
571 if (chip->core_irq) 571 if (chip->core_irq)
572 free_irq(chip->core_irq, chip); 572 free_irq(chip->core_irq, chip);
@@ -703,7 +703,7 @@ out:
703 return; 703 return;
704} 704}
705 705
706int pm860x_device_init(struct pm860x_chip *chip, 706int __devinit pm860x_device_init(struct pm860x_chip *chip,
707 struct pm860x_platform_data *pdata) 707 struct pm860x_platform_data *pdata)
708{ 708{
709 chip->core_irq = 0; 709 chip->core_irq = 0;
@@ -731,7 +731,7 @@ int pm860x_device_init(struct pm860x_chip *chip,
731 return 0; 731 return 0;
732} 732}
733 733
734void pm860x_device_exit(struct pm860x_chip *chip) 734void __devexit pm860x_device_exit(struct pm860x_chip *chip)
735{ 735{
736 device_irq_exit(chip); 736 device_irq_exit(chip);
737 mfd_remove_devices(chip->dev); 737 mfd_remove_devices(chip->dev);
diff --git a/drivers/mfd/88pm860x-i2c.c b/drivers/mfd/88pm860x-i2c.c
index 4a6e7186334e..bc02e6b21608 100644
--- a/drivers/mfd/88pm860x-i2c.c
+++ b/drivers/mfd/88pm860x-i2c.c
@@ -200,8 +200,6 @@ static int __devexit pm860x_remove(struct i2c_client *client)
200 200
201 pm860x_device_exit(chip); 201 pm860x_device_exit(chip);
202 i2c_unregister_device(chip->companion); 202 i2c_unregister_device(chip->companion);
203 i2c_set_clientdata(chip->companion, NULL);
204 i2c_set_clientdata(chip->client, NULL);
205 kfree(chip); 203 kfree(chip);
206 return 0; 204 return 0;
207} 205}
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 3c6a9860dd9c..9da0e504bbe9 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -2,8 +2,14 @@
2# Multifunction miscellaneous devices 2# Multifunction miscellaneous devices
3# 3#
4 4
5menu "Multifunction device drivers" 5menuconfig MFD_SUPPORT
6 bool "Multifunction device drivers"
6 depends on HAS_IOMEM 7 depends on HAS_IOMEM
8 default y
9 help
10 Configure MFD device drivers.
11
12if MFD_SUPPORT
7 13
8config MFD_CORE 14config MFD_CORE
9 tristate 15 tristate
@@ -116,6 +122,18 @@ config TPS65010
116 This driver can also be built as a module. If so, the module 122 This driver can also be built as a module. If so, the module
117 will be called tps65010. 123 will be called tps65010.
118 124
125config TPS6507X
126 tristate "TPS6507x Power Management / Touch Screen chips"
127 select MFD_CORE
128 depends on I2C
129 help
130 If you say yes here you get support for the TPS6507x series of
131 Power Management / Touch Screen chips. These include voltage
132 regulators, lithium ion/polymer battery charging, touch screen
133 and other features that are often used in portable devices.
134 This driver can also be built as a module. If so, the module
135 will be called tps6507x.
136
119config MENELAUS 137config MENELAUS
120 bool "Texas Instruments TWL92330/Menelaus PM chip" 138 bool "Texas Instruments TWL92330/Menelaus PM chip"
121 depends on I2C=y && ARCH_OMAP2 139 depends on I2C=y && ARCH_OMAP2
@@ -159,6 +177,17 @@ config TWL4030_CODEC
159 select MFD_CORE 177 select MFD_CORE
160 default n 178 default n
161 179
180config MFD_TC35892
181 bool "Support Toshiba TC35892"
182 depends on I2C=y && GENERIC_HARDIRQS
183 select MFD_CORE
184 help
185 Support for the Toshiba TC35892 I/O Expander.
186
187 This driver provides common support for accessing the device,
188 additional drivers must be enabled in order to use the
189 functionality of the device.
190
162config MFD_TMIO 191config MFD_TMIO
163 bool 192 bool
164 default n 193 default n
@@ -351,9 +380,19 @@ config PCF50633_GPIO
351 Say yes here if you want to include support GPIO for pins on 380 Say yes here if you want to include support GPIO for pins on
352 the PCF50633 chip. 381 the PCF50633 chip.
353 382
383config ABX500_CORE
384 bool "ST-Ericsson ABX500 Mixed Signal Circuit register functions"
385 default y if ARCH_U300
386 help
387 Say yes here if you have the ABX500 Mixed Signal IC family
388 chips. This core driver expose register access functions.
389 Functionality specific drivers using these functions can
390 remain unchanged when IC changes. Binding of the functions to
391 actual register access is done by the IC core driver.
392
354config AB3100_CORE 393config AB3100_CORE
355 bool "ST-Ericsson AB3100 Mixed Signal Circuit core functions" 394 bool "ST-Ericsson AB3100 Mixed Signal Circuit core functions"
356 depends on I2C=y 395 depends on I2C=y && ABX500_CORE
357 default y if ARCH_U300 396 default y if ARCH_U300
358 help 397 help
359 Select this to enable the AB3100 Mixed Signal IC core 398 Select this to enable the AB3100 Mixed Signal IC core
@@ -381,15 +420,30 @@ config EZX_PCAP
381 This enables the PCAP ASIC present on EZX Phones. This is 420 This enables the PCAP ASIC present on EZX Phones. This is
382 needed for MMC, TouchScreen, Sound, USB, etc.. 421 needed for MMC, TouchScreen, Sound, USB, etc..
383 422
384config AB4500_CORE 423config AB8500_CORE
385 tristate "ST-Ericsson's AB4500 Mixed Signal Power management chip" 424 bool "ST-Ericsson AB8500 Mixed Signal Power Management chip"
386 depends on SPI 425 depends on SPI=y && GENERIC_HARDIRQS
426 select MFD_CORE
387 help 427 help
388 Select this option to enable access to AB4500 power management 428 Select this option to enable access to AB8500 power management
389 chip. This connects to U8500 on the SSP/SPI bus and exports 429 chip. This connects to U8500 on the SSP/SPI bus and exports
390 read/write functions for the devices to get access to this chip. 430 read/write functions for the devices to get access to this chip.
391 This chip embeds various other multimedia funtionalities as well. 431 This chip embeds various other multimedia funtionalities as well.
392 432
433config AB3550_CORE
434 bool "ST-Ericsson AB3550 Mixed Signal Circuit core functions"
435 select MFD_CORE
436 depends on I2C=y && GENERIC_HARDIRQS && ABX500_CORE
437 help
438 Select this to enable the AB3550 Mixed Signal IC core
439 functionality. This connects to a AB3550 on the I2C bus
440 and expose a number of symbols needed for dependent devices
441 to read and write registers and subscribe to events from
442 this multi-functional IC. This is needed to use other features
443 of the AB3550 such as battery-backed RTC, charging control,
444 LEDs, vibrator, system power and temperature, power management
445 and ALSA sound.
446
393config MFD_TIMBERDALE 447config MFD_TIMBERDALE
394 tristate "Support for the Timberdale FPGA" 448 tristate "Support for the Timberdale FPGA"
395 select MFD_CORE 449 select MFD_CORE
@@ -409,7 +463,26 @@ config LPC_SCH
409 LPC bridge function of the Intel SCH provides support for 463 LPC bridge function of the Intel SCH provides support for
410 System Management Bus and General Purpose I/O. 464 System Management Bus and General Purpose I/O.
411 465
412endmenu 466config MFD_RDC321X
467 tristate "Support for RDC-R321x southbridge"
468 select MFD_CORE
469 depends on PCI
470 help
471 Say yes here if you want to have support for the RDC R-321x SoC
472 southbridge which provides access to GPIOs and Watchdog using the
473 southbridge PCI device configuration space.
474
475config MFD_JANZ_CMODIO
476 tristate "Support for Janz CMOD-IO PCI MODULbus Carrier Board"
477 select MFD_CORE
478 depends on PCI
479 help
480 This is the core driver for the Janz CMOD-IO PCI MODULbus
481 carrier board. This device is a PCI to MODULbus bridge which may
482 host many different types of MODULbus daughterboards, including
483 CAN and GPIO controllers.
484
485endif # MFD_SUPPORT
413 486
414menu "Multimedia Capabilities Port drivers" 487menu "Multimedia Capabilities Port drivers"
415 depends on ARCH_SA1100 488 depends on ARCH_SA1100
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 87935f967aa0..fb503e77dc60 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_HTC_I2CPLD) += htc-i2cpld.o
15obj-$(CONFIG_MFD_DAVINCI_VOICECODEC) += davinci_voicecodec.o 15obj-$(CONFIG_MFD_DAVINCI_VOICECODEC) += davinci_voicecodec.o
16obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o 16obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o
17 17
18obj-$(CONFIG_MFD_TC35892) += tc35892.o
18obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o 19obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o
19obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o tmio_core.o 20obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o tmio_core.o
20obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o tmio_core.o 21obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o tmio_core.o
@@ -29,6 +30,7 @@ obj-$(CONFIG_MFD_WM8350_I2C) += wm8350-i2c.o
29obj-$(CONFIG_MFD_WM8994) += wm8994-core.o wm8994-irq.o 30obj-$(CONFIG_MFD_WM8994) += wm8994-core.o wm8994-irq.o
30 31
31obj-$(CONFIG_TPS65010) += tps65010.o 32obj-$(CONFIG_TPS65010) += tps65010.o
33obj-$(CONFIG_TPS6507X) += tps6507x.o
32obj-$(CONFIG_MENELAUS) += menelaus.o 34obj-$(CONFIG_MENELAUS) += menelaus.o
33 35
34obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o twl6030-irq.o 36obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o twl6030-irq.o
@@ -55,12 +57,17 @@ obj-$(CONFIG_PMIC_DA903X) += da903x.o
55max8925-objs := max8925-core.o max8925-i2c.o 57max8925-objs := max8925-core.o max8925-i2c.o
56obj-$(CONFIG_MFD_MAX8925) += max8925.o 58obj-$(CONFIG_MFD_MAX8925) += max8925.o
57 59
58obj-$(CONFIG_MFD_PCF50633) += pcf50633-core.o 60pcf50633-objs := pcf50633-core.o pcf50633-irq.o
61obj-$(CONFIG_MFD_PCF50633) += pcf50633.o
59obj-$(CONFIG_PCF50633_ADC) += pcf50633-adc.o 62obj-$(CONFIG_PCF50633_ADC) += pcf50633-adc.o
60obj-$(CONFIG_PCF50633_GPIO) += pcf50633-gpio.o 63obj-$(CONFIG_PCF50633_GPIO) += pcf50633-gpio.o
64obj-$(CONFIG_ABX500_CORE) += abx500-core.o
61obj-$(CONFIG_AB3100_CORE) += ab3100-core.o 65obj-$(CONFIG_AB3100_CORE) += ab3100-core.o
62obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o 66obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o
63obj-$(CONFIG_AB4500_CORE) += ab4500-core.o 67obj-$(CONFIG_AB3550_CORE) += ab3550-core.o
68obj-$(CONFIG_AB8500_CORE) += ab8500-core.o ab8500-spi.o
64obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o 69obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o
65obj-$(CONFIG_PMIC_ADP5520) += adp5520.o 70obj-$(CONFIG_PMIC_ADP5520) += adp5520.o
66obj-$(CONFIG_LPC_SCH) += lpc_sch.o \ No newline at end of file 71obj-$(CONFIG_LPC_SCH) += lpc_sch.o
72obj-$(CONFIG_MFD_RDC321X) += rdc321x-southbridge.o
73obj-$(CONFIG_MFD_JANZ_CMODIO) += janz-cmodio.o
diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c
index e4ca5909e424..66379b413906 100644
--- a/drivers/mfd/ab3100-core.c
+++ b/drivers/mfd/ab3100-core.c
@@ -19,7 +19,7 @@
19#include <linux/debugfs.h> 19#include <linux/debugfs.h>
20#include <linux/seq_file.h> 20#include <linux/seq_file.h>
21#include <linux/uaccess.h> 21#include <linux/uaccess.h>
22#include <linux/mfd/ab3100.h> 22#include <linux/mfd/abx500.h>
23 23
24/* These are the only registers inside AB3100 used in this main file */ 24/* These are the only registers inside AB3100 used in this main file */
25 25
@@ -59,24 +59,15 @@
59 * The AB3100 is usually assigned address 0x48 (7-bit) 59 * The AB3100 is usually assigned address 0x48 (7-bit)
60 * The chip is defined in the platform i2c_board_data section. 60 * The chip is defined in the platform i2c_board_data section.
61 */ 61 */
62 62static int ab3100_get_chip_id(struct device *dev)
63u8 ab3100_get_chip_type(struct ab3100 *ab3100)
64{ 63{
65 u8 chip = ABUNKNOWN; 64 struct ab3100 *ab3100 = dev_get_drvdata(dev->parent);
66 65
67 switch (ab3100->chip_id & 0xf0) { 66 return (int)ab3100->chip_id;
68 case 0xa0:
69 chip = AB3000;
70 break;
71 case 0xc0:
72 chip = AB3100;
73 break;
74 }
75 return chip;
76} 67}
77EXPORT_SYMBOL(ab3100_get_chip_type);
78 68
79int ab3100_set_register_interruptible(struct ab3100 *ab3100, u8 reg, u8 regval) 69static int ab3100_set_register_interruptible(struct ab3100 *ab3100,
70 u8 reg, u8 regval)
80{ 71{
81 u8 regandval[2] = {reg, regval}; 72 u8 regandval[2] = {reg, regval};
82 int err; 73 int err;
@@ -108,8 +99,14 @@ int ab3100_set_register_interruptible(struct ab3100 *ab3100, u8 reg, u8 regval)
108 mutex_unlock(&ab3100->access_mutex); 99 mutex_unlock(&ab3100->access_mutex);
109 return err; 100 return err;
110} 101}
111EXPORT_SYMBOL(ab3100_set_register_interruptible);
112 102
103static int set_register_interruptible(struct device *dev,
104 u8 bank, u8 reg, u8 value)
105{
106 struct ab3100 *ab3100 = dev_get_drvdata(dev->parent);
107
108 return ab3100_set_register_interruptible(ab3100, reg, value);
109}
113 110
114/* 111/*
115 * The test registers exist at an I2C bus address up one 112 * The test registers exist at an I2C bus address up one
@@ -148,8 +145,8 @@ static int ab3100_set_test_register_interruptible(struct ab3100 *ab3100,
148 return err; 145 return err;
149} 146}
150 147
151 148static int ab3100_get_register_interruptible(struct ab3100 *ab3100,
152int ab3100_get_register_interruptible(struct ab3100 *ab3100, u8 reg, u8 *regval) 149 u8 reg, u8 *regval)
153{ 150{
154 int err; 151 int err;
155 152
@@ -203,10 +200,16 @@ int ab3100_get_register_interruptible(struct ab3100 *ab3100, u8 reg, u8 *regval)
203 mutex_unlock(&ab3100->access_mutex); 200 mutex_unlock(&ab3100->access_mutex);
204 return err; 201 return err;
205} 202}
206EXPORT_SYMBOL(ab3100_get_register_interruptible);
207 203
204static int get_register_interruptible(struct device *dev, u8 bank, u8 reg,
205 u8 *value)
206{
207 struct ab3100 *ab3100 = dev_get_drvdata(dev->parent);
208
209 return ab3100_get_register_interruptible(ab3100, reg, value);
210}
208 211
209int ab3100_get_register_page_interruptible(struct ab3100 *ab3100, 212static int ab3100_get_register_page_interruptible(struct ab3100 *ab3100,
210 u8 first_reg, u8 *regvals, u8 numregs) 213 u8 first_reg, u8 *regvals, u8 numregs)
211{ 214{
212 int err; 215 int err;
@@ -260,10 +263,17 @@ int ab3100_get_register_page_interruptible(struct ab3100 *ab3100,
260 mutex_unlock(&ab3100->access_mutex); 263 mutex_unlock(&ab3100->access_mutex);
261 return err; 264 return err;
262} 265}
263EXPORT_SYMBOL(ab3100_get_register_page_interruptible);
264 266
267static int get_register_page_interruptible(struct device *dev, u8 bank,
268 u8 first_reg, u8 *regvals, u8 numregs)
269{
270 struct ab3100 *ab3100 = dev_get_drvdata(dev->parent);
271
272 return ab3100_get_register_page_interruptible(ab3100,
273 first_reg, regvals, numregs);
274}
265 275
266int ab3100_mask_and_set_register_interruptible(struct ab3100 *ab3100, 276static int ab3100_mask_and_set_register_interruptible(struct ab3100 *ab3100,
267 u8 reg, u8 andmask, u8 ormask) 277 u8 reg, u8 andmask, u8 ormask)
268{ 278{
269 u8 regandval[2] = {reg, 0}; 279 u8 regandval[2] = {reg, 0};
@@ -331,8 +341,15 @@ int ab3100_mask_and_set_register_interruptible(struct ab3100 *ab3100,
331 mutex_unlock(&ab3100->access_mutex); 341 mutex_unlock(&ab3100->access_mutex);
332 return err; 342 return err;
333} 343}
334EXPORT_SYMBOL(ab3100_mask_and_set_register_interruptible);
335 344
345static int mask_and_set_register_interruptible(struct device *dev, u8 bank,
346 u8 reg, u8 bitmask, u8 bitvalues)
347{
348 struct ab3100 *ab3100 = dev_get_drvdata(dev->parent);
349
350 return ab3100_mask_and_set_register_interruptible(ab3100,
351 reg, bitmask, (bitmask & bitvalues));
352}
336 353
337/* 354/*
338 * Register a simple callback for handling any AB3100 events. 355 * Register a simple callback for handling any AB3100 events.
@@ -357,15 +374,27 @@ int ab3100_event_unregister(struct ab3100 *ab3100,
357EXPORT_SYMBOL(ab3100_event_unregister); 374EXPORT_SYMBOL(ab3100_event_unregister);
358 375
359 376
360int ab3100_event_registers_startup_state_get(struct ab3100 *ab3100, 377static int ab3100_event_registers_startup_state_get(struct device *dev,
361 u32 *fatevent) 378 u8 *event)
362{ 379{
380 struct ab3100 *ab3100 = dev_get_drvdata(dev->parent);
363 if (!ab3100->startup_events_read) 381 if (!ab3100->startup_events_read)
364 return -EAGAIN; /* Try again later */ 382 return -EAGAIN; /* Try again later */
365 *fatevent = ab3100->startup_events; 383 memcpy(event, ab3100->startup_events, 3);
366 return 0; 384 return 0;
367} 385}
368EXPORT_SYMBOL(ab3100_event_registers_startup_state_get); 386
387static struct abx500_ops ab3100_ops = {
388 .get_chip_id = ab3100_get_chip_id,
389 .set_register = set_register_interruptible,
390 .get_register = get_register_interruptible,
391 .get_register_page = get_register_page_interruptible,
392 .set_register_page = NULL,
393 .mask_and_set_register = mask_and_set_register_interruptible,
394 .event_registers_startup_state_get =
395 ab3100_event_registers_startup_state_get,
396 .startup_irq_enabled = NULL,
397};
369 398
370/* 399/*
371 * This is a threaded interrupt handler so we can make some 400 * This is a threaded interrupt handler so we can make some
@@ -390,7 +419,9 @@ static irqreturn_t ab3100_irq_handler(int irq, void *data)
390 event_regs[2]; 419 event_regs[2];
391 420
392 if (!ab3100->startup_events_read) { 421 if (!ab3100->startup_events_read) {
393 ab3100->startup_events = fatevent; 422 ab3100->startup_events[0] = event_regs[0];
423 ab3100->startup_events[1] = event_regs[1];
424 ab3100->startup_events[2] = event_regs[2];
394 ab3100->startup_events_read = true; 425 ab3100->startup_events_read = true;
395 } 426 }
396 /* 427 /*
@@ -703,7 +734,8 @@ static int __init ab3100_setup(struct ab3100 *ab3100)
703 dev_warn(ab3100->dev, 734 dev_warn(ab3100->dev,
704 "AB3100 P1E variant detected, " 735 "AB3100 P1E variant detected, "
705 "forcing chip to 32KHz\n"); 736 "forcing chip to 32KHz\n");
706 err = ab3100_set_test_register_interruptible(ab3100, 0x02, 0x08); 737 err = ab3100_set_test_register_interruptible(ab3100,
738 0x02, 0x08);
707 } 739 }
708 740
709 exit_no_setup: 741 exit_no_setup:
@@ -898,6 +930,10 @@ static int __init ab3100_probe(struct i2c_client *client,
898 if (err) 930 if (err)
899 goto exit_no_irq; 931 goto exit_no_irq;
900 932
933 err = abx500_register_ops(&client->dev, &ab3100_ops);
934 if (err)
935 goto exit_no_ops;
936
901 /* Set parent and a pointer back to the container in device data */ 937 /* Set parent and a pointer back to the container in device data */
902 for (i = 0; i < ARRAY_SIZE(ab3100_platform_devs); i++) { 938 for (i = 0; i < ARRAY_SIZE(ab3100_platform_devs); i++) {
903 ab3100_platform_devs[i]->dev.parent = 939 ab3100_platform_devs[i]->dev.parent =
@@ -915,6 +951,7 @@ static int __init ab3100_probe(struct i2c_client *client,
915 951
916 return 0; 952 return 0;
917 953
954 exit_no_ops:
918 exit_no_irq: 955 exit_no_irq:
919 exit_no_setup: 956 exit_no_setup:
920 i2c_unregister_device(ab3100->testreg_client); 957 i2c_unregister_device(ab3100->testreg_client);
diff --git a/drivers/mfd/ab3100-otp.c b/drivers/mfd/ab3100-otp.c
index 2d14655fdebd..63d2b727ddbb 100644
--- a/drivers/mfd/ab3100-otp.c
+++ b/drivers/mfd/ab3100-otp.c
@@ -12,7 +12,7 @@
12#include <linux/slab.h> 12#include <linux/slab.h>
13#include <linux/init.h> 13#include <linux/init.h>
14#include <linux/platform_device.h> 14#include <linux/platform_device.h>
15#include <linux/mfd/ab3100.h> 15#include <linux/mfd/abx500.h>
16#include <linux/debugfs.h> 16#include <linux/debugfs.h>
17#include <linux/seq_file.h> 17#include <linux/seq_file.h>
18 18
@@ -30,7 +30,6 @@
30/** 30/**
31 * struct ab3100_otp 31 * struct ab3100_otp
32 * @dev containing device 32 * @dev containing device
33 * @ab3100 a pointer to the parent ab3100 device struct
34 * @locked whether the OTP is locked, after locking, no more bits 33 * @locked whether the OTP is locked, after locking, no more bits
35 * can be changed but before locking it is still possible 34 * can be changed but before locking it is still possible
36 * to change bits from 1->0. 35 * to change bits from 1->0.
@@ -49,7 +48,6 @@
49 */ 48 */
50struct ab3100_otp { 49struct ab3100_otp {
51 struct device *dev; 50 struct device *dev;
52 struct ab3100 *ab3100;
53 bool locked; 51 bool locked;
54 u32 freq; 52 u32 freq;
55 bool paf; 53 bool paf;
@@ -63,19 +61,19 @@ struct ab3100_otp {
63 61
64static int __init ab3100_otp_read(struct ab3100_otp *otp) 62static int __init ab3100_otp_read(struct ab3100_otp *otp)
65{ 63{
66 struct ab3100 *ab = otp->ab3100;
67 u8 otpval[8]; 64 u8 otpval[8];
68 u8 otpp; 65 u8 otpp;
69 int err; 66 int err;
70 67
71 err = ab3100_get_register_interruptible(ab, AB3100_OTPP, &otpp); 68 err = abx500_get_register_interruptible(otp->dev, 0,
69 AB3100_OTPP, &otpp);
72 if (err) { 70 if (err) {
73 dev_err(otp->dev, "unable to read OTPP register\n"); 71 dev_err(otp->dev, "unable to read OTPP register\n");
74 return err; 72 return err;
75 } 73 }
76 74
77 err = ab3100_get_register_page_interruptible(ab, AB3100_OTP0, 75 err = abx500_get_register_page_interruptible(otp->dev, 0,
78 otpval, 8); 76 AB3100_OTP0, otpval, 8);
79 if (err) { 77 if (err) {
80 dev_err(otp->dev, "unable to read OTP register page\n"); 78 dev_err(otp->dev, "unable to read OTP register page\n");
81 return err; 79 return err;
@@ -197,7 +195,6 @@ static int __init ab3100_otp_probe(struct platform_device *pdev)
197 otp->dev = &pdev->dev; 195 otp->dev = &pdev->dev;
198 196
199 /* Replace platform data coming in with a local struct */ 197 /* Replace platform data coming in with a local struct */
200 otp->ab3100 = platform_get_drvdata(pdev);
201 platform_set_drvdata(pdev, otp); 198 platform_set_drvdata(pdev, otp);
202 199
203 err = ab3100_otp_read(otp); 200 err = ab3100_otp_read(otp);
diff --git a/drivers/mfd/ab3550-core.c b/drivers/mfd/ab3550-core.c
new file mode 100644
index 000000000000..f54ab62e7bc6
--- /dev/null
+++ b/drivers/mfd/ab3550-core.c
@@ -0,0 +1,1400 @@
1/*
2 * Copyright (C) 2007-2010 ST-Ericsson
3 * License terms: GNU General Public License (GPL) version 2
4 * Low-level core for exclusive access to the AB3550 IC on the I2C bus
5 * and some basic chip-configuration.
6 * Author: Bengt Jonsson <bengt.g.jonsson@stericsson.com>
7 * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com>
8 * Author: Mattias Wallin <mattias.wallin@stericsson.com>
9 * Author: Rickard Andersson <rickard.andersson@stericsson.com>
10 */
11
12#include <linux/i2c.h>
13#include <linux/mutex.h>
14#include <linux/err.h>
15#include <linux/platform_device.h>
16#include <linux/slab.h>
17#include <linux/device.h>
18#include <linux/irq.h>
19#include <linux/interrupt.h>
20#include <linux/random.h>
21#include <linux/workqueue.h>
22#include <linux/debugfs.h>
23#include <linux/seq_file.h>
24#include <linux/uaccess.h>
25#include <linux/mfd/abx500.h>
26#include <linux/list.h>
27#include <linux/bitops.h>
28#include <linux/spinlock.h>
29#include <linux/mfd/core.h>
30
31#define AB3550_NAME_STRING "ab3550"
32#define AB3550_ID_FORMAT_STRING "AB3550 %s"
33#define AB3550_NUM_BANKS 2
34#define AB3550_NUM_EVENT_REG 5
35
36/* These are the only registers inside AB3550 used in this main file */
37
38/* Chip ID register */
39#define AB3550_CID_REG 0x20
40
41/* Interrupt event registers */
42#define AB3550_EVENT_BANK 0
43#define AB3550_EVENT_REG 0x22
44
45/* Read/write operation values. */
46#define AB3550_PERM_RD (0x01)
47#define AB3550_PERM_WR (0x02)
48
49/* Read/write permissions. */
50#define AB3550_PERM_RO (AB3550_PERM_RD)
51#define AB3550_PERM_RW (AB3550_PERM_RD | AB3550_PERM_WR)
52
53/**
54 * struct ab3550
55 * @access_mutex: lock out concurrent accesses to the AB registers
56 * @i2c_client: I2C client for this chip
57 * @chip_name: name of this chip variant
58 * @chip_id: 8 bit chip ID for this chip variant
59 * @mask_work: a worker for writing to mask registers
60 * @event_lock: a lock to protect the event_mask
61 * @event_mask: a local copy of the mask event registers
62 * @startup_events: a copy of the first reading of the event registers
63 * @startup_events_read: whether the first events have been read
64 */
65struct ab3550 {
66 struct mutex access_mutex;
67 struct i2c_client *i2c_client[AB3550_NUM_BANKS];
68 char chip_name[32];
69 u8 chip_id;
70 struct work_struct mask_work;
71 spinlock_t event_lock;
72 u8 event_mask[AB3550_NUM_EVENT_REG];
73 u8 startup_events[AB3550_NUM_EVENT_REG];
74 bool startup_events_read;
75#ifdef CONFIG_DEBUG_FS
76 unsigned int debug_bank;
77 unsigned int debug_address;
78#endif
79};
80
81/**
82 * struct ab3550_reg_range
83 * @first: the first address of the range
84 * @last: the last address of the range
85 * @perm: access permissions for the range
86 */
87struct ab3550_reg_range {
88 u8 first;
89 u8 last;
90 u8 perm;
91};
92
93/**
94 * struct ab3550_reg_ranges
95 * @count: the number of ranges in the list
96 * @range: the list of register ranges
97 */
98struct ab3550_reg_ranges {
99 u8 count;
100 const struct ab3550_reg_range *range;
101};
102
103/*
104 * Permissible register ranges for reading and writing per device and bank.
105 *
106 * The ranges must be listed in increasing address order, and no overlaps are
107 * allowed. It is assumed that write permission implies read permission
108 * (i.e. only RO and RW permissions should be used). Ranges with write
109 * permission must not be split up.
110 */
111
112#define NO_RANGE {.count = 0, .range = NULL,}
113
114static struct
115ab3550_reg_ranges ab3550_reg_ranges[AB3550_NUM_DEVICES][AB3550_NUM_BANKS] = {
116 [AB3550_DEVID_DAC] = {
117 NO_RANGE,
118 {
119 .count = 2,
120 .range = (struct ab3550_reg_range[]) {
121 {
122 .first = 0xb0,
123 .last = 0xba,
124 .perm = AB3550_PERM_RW,
125 },
126 {
127 .first = 0xbc,
128 .last = 0xc3,
129 .perm = AB3550_PERM_RW,
130 },
131 },
132 },
133 },
134 [AB3550_DEVID_LEDS] = {
135 NO_RANGE,
136 {
137 .count = 2,
138 .range = (struct ab3550_reg_range[]) {
139 {
140 .first = 0x5a,
141 .last = 0x88,
142 .perm = AB3550_PERM_RW,
143 },
144 {
145 .first = 0x8a,
146 .last = 0xad,
147 .perm = AB3550_PERM_RW,
148 },
149 }
150 },
151 },
152 [AB3550_DEVID_POWER] = {
153 {
154 .count = 1,
155 .range = (struct ab3550_reg_range[]) {
156 {
157 .first = 0x21,
158 .last = 0x21,
159 .perm = AB3550_PERM_RO,
160 },
161 }
162 },
163 NO_RANGE,
164 },
165 [AB3550_DEVID_REGULATORS] = {
166 {
167 .count = 1,
168 .range = (struct ab3550_reg_range[]) {
169 {
170 .first = 0x69,
171 .last = 0xa3,
172 .perm = AB3550_PERM_RW,
173 },
174 }
175 },
176 {
177 .count = 1,
178 .range = (struct ab3550_reg_range[]) {
179 {
180 .first = 0x14,
181 .last = 0x16,
182 .perm = AB3550_PERM_RW,
183 },
184 }
185 },
186 },
187 [AB3550_DEVID_SIM] = {
188 {
189 .count = 1,
190 .range = (struct ab3550_reg_range[]) {
191 {
192 .first = 0x21,
193 .last = 0x21,
194 .perm = AB3550_PERM_RO,
195 },
196 }
197 },
198 {
199 .count = 1,
200 .range = (struct ab3550_reg_range[]) {
201 {
202 .first = 0x14,
203 .last = 0x17,
204 .perm = AB3550_PERM_RW,
205 },
206 }
207
208 },
209 },
210 [AB3550_DEVID_UART] = {
211 NO_RANGE,
212 NO_RANGE,
213 },
214 [AB3550_DEVID_RTC] = {
215 {
216 .count = 1,
217 .range = (struct ab3550_reg_range[]) {
218 {
219 .first = 0x00,
220 .last = 0x0c,
221 .perm = AB3550_PERM_RW,
222 },
223 }
224 },
225 NO_RANGE,
226 },
227 [AB3550_DEVID_CHARGER] = {
228 {
229 .count = 2,
230 .range = (struct ab3550_reg_range[]) {
231 {
232 .first = 0x10,
233 .last = 0x1a,
234 .perm = AB3550_PERM_RW,
235 },
236 {
237 .first = 0x21,
238 .last = 0x21,
239 .perm = AB3550_PERM_RO,
240 },
241 }
242 },
243 NO_RANGE,
244 },
245 [AB3550_DEVID_ADC] = {
246 NO_RANGE,
247 {
248 .count = 1,
249 .range = (struct ab3550_reg_range[]) {
250 {
251 .first = 0x20,
252 .last = 0x56,
253 .perm = AB3550_PERM_RW,
254 },
255
256 }
257 },
258 },
259 [AB3550_DEVID_FUELGAUGE] = {
260 {
261 .count = 1,
262 .range = (struct ab3550_reg_range[]) {
263 {
264 .first = 0x21,
265 .last = 0x21,
266 .perm = AB3550_PERM_RO,
267 },
268 }
269 },
270 {
271 .count = 1,
272 .range = (struct ab3550_reg_range[]) {
273 {
274 .first = 0x00,
275 .last = 0x0e,
276 .perm = AB3550_PERM_RW,
277 },
278 }
279 },
280 },
281 [AB3550_DEVID_VIBRATOR] = {
282 NO_RANGE,
283 {
284 .count = 1,
285 .range = (struct ab3550_reg_range[]) {
286 {
287 .first = 0x10,
288 .last = 0x13,
289 .perm = AB3550_PERM_RW,
290 },
291
292 }
293 },
294 },
295 [AB3550_DEVID_CODEC] = {
296 {
297 .count = 2,
298 .range = (struct ab3550_reg_range[]) {
299 {
300 .first = 0x31,
301 .last = 0x63,
302 .perm = AB3550_PERM_RW,
303 },
304 {
305 .first = 0x65,
306 .last = 0x68,
307 .perm = AB3550_PERM_RW,
308 },
309 }
310 },
311 NO_RANGE,
312 },
313};
314
315static struct mfd_cell ab3550_devs[AB3550_NUM_DEVICES] = {
316 [AB3550_DEVID_DAC] = {
317 .name = "ab3550-dac",
318 .id = AB3550_DEVID_DAC,
319 .num_resources = 0,
320 },
321 [AB3550_DEVID_LEDS] = {
322 .name = "ab3550-leds",
323 .id = AB3550_DEVID_LEDS,
324 },
325 [AB3550_DEVID_POWER] = {
326 .name = "ab3550-power",
327 .id = AB3550_DEVID_POWER,
328 },
329 [AB3550_DEVID_REGULATORS] = {
330 .name = "ab3550-regulators",
331 .id = AB3550_DEVID_REGULATORS,
332 },
333 [AB3550_DEVID_SIM] = {
334 .name = "ab3550-sim",
335 .id = AB3550_DEVID_SIM,
336 },
337 [AB3550_DEVID_UART] = {
338 .name = "ab3550-uart",
339 .id = AB3550_DEVID_UART,
340 },
341 [AB3550_DEVID_RTC] = {
342 .name = "ab3550-rtc",
343 .id = AB3550_DEVID_RTC,
344 },
345 [AB3550_DEVID_CHARGER] = {
346 .name = "ab3550-charger",
347 .id = AB3550_DEVID_CHARGER,
348 },
349 [AB3550_DEVID_ADC] = {
350 .name = "ab3550-adc",
351 .id = AB3550_DEVID_ADC,
352 .num_resources = 10,
353 .resources = (struct resource[]) {
354 {
355 .name = "TRIGGER-0",
356 .flags = IORESOURCE_IRQ,
357 .start = 16,
358 .end = 16,
359 },
360 {
361 .name = "TRIGGER-1",
362 .flags = IORESOURCE_IRQ,
363 .start = 17,
364 .end = 17,
365 },
366 {
367 .name = "TRIGGER-2",
368 .flags = IORESOURCE_IRQ,
369 .start = 18,
370 .end = 18,
371 },
372 {
373 .name = "TRIGGER-3",
374 .flags = IORESOURCE_IRQ,
375 .start = 19,
376 .end = 19,
377 },
378 {
379 .name = "TRIGGER-4",
380 .flags = IORESOURCE_IRQ,
381 .start = 20,
382 .end = 20,
383 },
384 {
385 .name = "TRIGGER-5",
386 .flags = IORESOURCE_IRQ,
387 .start = 21,
388 .end = 21,
389 },
390 {
391 .name = "TRIGGER-6",
392 .flags = IORESOURCE_IRQ,
393 .start = 22,
394 .end = 22,
395 },
396 {
397 .name = "TRIGGER-7",
398 .flags = IORESOURCE_IRQ,
399 .start = 23,
400 .end = 23,
401 },
402 {
403 .name = "TRIGGER-VBAT-TXON",
404 .flags = IORESOURCE_IRQ,
405 .start = 13,
406 .end = 13,
407 },
408 {
409 .name = "TRIGGER-VBAT",
410 .flags = IORESOURCE_IRQ,
411 .start = 12,
412 .end = 12,
413 },
414 },
415 },
416 [AB3550_DEVID_FUELGAUGE] = {
417 .name = "ab3550-fuelgauge",
418 .id = AB3550_DEVID_FUELGAUGE,
419 },
420 [AB3550_DEVID_VIBRATOR] = {
421 .name = "ab3550-vibrator",
422 .id = AB3550_DEVID_VIBRATOR,
423 },
424 [AB3550_DEVID_CODEC] = {
425 .name = "ab3550-codec",
426 .id = AB3550_DEVID_CODEC,
427 },
428};
429
430/*
431 * I2C transactions with error messages.
432 */
433static int ab3550_i2c_master_send(struct ab3550 *ab, u8 bank, u8 *data,
434 u8 count)
435{
436 int err;
437
438 err = i2c_master_send(ab->i2c_client[bank], data, count);
439 if (err < 0) {
440 dev_err(&ab->i2c_client[0]->dev, "send error: %d\n", err);
441 return err;
442 }
443 return 0;
444}
445
446static int ab3550_i2c_master_recv(struct ab3550 *ab, u8 bank, u8 *data,
447 u8 count)
448{
449 int err;
450
451 err = i2c_master_recv(ab->i2c_client[bank], data, count);
452 if (err < 0) {
453 dev_err(&ab->i2c_client[0]->dev, "receive error: %d\n", err);
454 return err;
455 }
456 return 0;
457}
458
459/*
460 * Functionality for getting/setting register values.
461 */
462static int get_register_interruptible(struct ab3550 *ab, u8 bank, u8 reg,
463 u8 *value)
464{
465 int err;
466
467 err = mutex_lock_interruptible(&ab->access_mutex);
468 if (err)
469 return err;
470
471 err = ab3550_i2c_master_send(ab, bank, &reg, 1);
472 if (!err)
473 err = ab3550_i2c_master_recv(ab, bank, value, 1);
474
475 mutex_unlock(&ab->access_mutex);
476 return err;
477}
478
479static int get_register_page_interruptible(struct ab3550 *ab, u8 bank,
480 u8 first_reg, u8 *regvals, u8 numregs)
481{
482 int err;
483
484 err = mutex_lock_interruptible(&ab->access_mutex);
485 if (err)
486 return err;
487
488 err = ab3550_i2c_master_send(ab, bank, &first_reg, 1);
489 if (!err)
490 err = ab3550_i2c_master_recv(ab, bank, regvals, numregs);
491
492 mutex_unlock(&ab->access_mutex);
493 return err;
494}
495
496static int mask_and_set_register_interruptible(struct ab3550 *ab, u8 bank,
497 u8 reg, u8 bitmask, u8 bitvalues)
498{
499 int err = 0;
500
501 if (likely(bitmask)) {
502 u8 reg_bits[2] = {reg, 0};
503
504 err = mutex_lock_interruptible(&ab->access_mutex);
505 if (err)
506 return err;
507
508 if (bitmask == 0xFF) /* No need to read in this case. */
509 reg_bits[1] = bitvalues;
510 else { /* Read and modify the register value. */
511 u8 bits;
512
513 err = ab3550_i2c_master_send(ab, bank, &reg, 1);
514 if (err)
515 goto unlock_and_return;
516 err = ab3550_i2c_master_recv(ab, bank, &bits, 1);
517 if (err)
518 goto unlock_and_return;
519 reg_bits[1] = ((~bitmask & bits) |
520 (bitmask & bitvalues));
521 }
522 /* Write the new value. */
523 err = ab3550_i2c_master_send(ab, bank, reg_bits, 2);
524unlock_and_return:
525 mutex_unlock(&ab->access_mutex);
526 }
527 return err;
528}
529
530/*
531 * Read/write permission checking functions.
532 */
533static bool page_write_allowed(const struct ab3550_reg_ranges *ranges,
534 u8 first_reg, u8 last_reg)
535{
536 u8 i;
537
538 if (last_reg < first_reg)
539 return false;
540
541 for (i = 0; i < ranges->count; i++) {
542 if (first_reg < ranges->range[i].first)
543 break;
544 if ((last_reg <= ranges->range[i].last) &&
545 (ranges->range[i].perm & AB3550_PERM_WR))
546 return true;
547 }
548 return false;
549}
550
551static bool reg_write_allowed(const struct ab3550_reg_ranges *ranges, u8 reg)
552{
553 return page_write_allowed(ranges, reg, reg);
554}
555
556static bool page_read_allowed(const struct ab3550_reg_ranges *ranges,
557 u8 first_reg, u8 last_reg)
558{
559 u8 i;
560
561 if (last_reg < first_reg)
562 return false;
563 /* Find the range (if it exists in the list) that includes first_reg. */
564 for (i = 0; i < ranges->count; i++) {
565 if (first_reg < ranges->range[i].first)
566 return false;
567 if (first_reg <= ranges->range[i].last)
568 break;
569 }
570 /* Make sure that the entire range up to and including last_reg is
571 * readable. This may span several of the ranges in the list.
572 */
573 while ((i < ranges->count) &&
574 (ranges->range[i].perm & AB3550_PERM_RD)) {
575 if (last_reg <= ranges->range[i].last)
576 return true;
577 if ((++i >= ranges->count) ||
578 (ranges->range[i].first !=
579 (ranges->range[i - 1].last + 1))) {
580 break;
581 }
582 }
583 return false;
584}
585
586static bool reg_read_allowed(const struct ab3550_reg_ranges *ranges, u8 reg)
587{
588 return page_read_allowed(ranges, reg, reg);
589}
590
591/*
592 * The exported register access functionality.
593 */
594int ab3550_get_chip_id(struct device *dev)
595{
596 struct ab3550 *ab = dev_get_drvdata(dev->parent);
597 return (int)ab->chip_id;
598}
599
600int ab3550_mask_and_set_register_interruptible(struct device *dev, u8 bank,
601 u8 reg, u8 bitmask, u8 bitvalues)
602{
603 struct ab3550 *ab;
604 struct platform_device *pdev = to_platform_device(dev);
605
606 if ((AB3550_NUM_BANKS <= bank) ||
607 !reg_write_allowed(&ab3550_reg_ranges[pdev->id][bank], reg))
608 return -EINVAL;
609
610 ab = dev_get_drvdata(dev->parent);
611 return mask_and_set_register_interruptible(ab, bank, reg,
612 bitmask, bitvalues);
613}
614
615int ab3550_set_register_interruptible(struct device *dev, u8 bank, u8 reg,
616 u8 value)
617{
618 return ab3550_mask_and_set_register_interruptible(dev, bank, reg, 0xFF,
619 value);
620}
621
622int ab3550_get_register_interruptible(struct device *dev, u8 bank, u8 reg,
623 u8 *value)
624{
625 struct ab3550 *ab;
626 struct platform_device *pdev = to_platform_device(dev);
627
628 if ((AB3550_NUM_BANKS <= bank) ||
629 !reg_read_allowed(&ab3550_reg_ranges[pdev->id][bank], reg))
630 return -EINVAL;
631
632 ab = dev_get_drvdata(dev->parent);
633 return get_register_interruptible(ab, bank, reg, value);
634}
635
636int ab3550_get_register_page_interruptible(struct device *dev, u8 bank,
637 u8 first_reg, u8 *regvals, u8 numregs)
638{
639 struct ab3550 *ab;
640 struct platform_device *pdev = to_platform_device(dev);
641
642 if ((AB3550_NUM_BANKS <= bank) ||
643 !page_read_allowed(&ab3550_reg_ranges[pdev->id][bank],
644 first_reg, (first_reg + numregs - 1)))
645 return -EINVAL;
646
647 ab = dev_get_drvdata(dev->parent);
648 return get_register_page_interruptible(ab, bank, first_reg, regvals,
649 numregs);
650}
651
652int ab3550_event_registers_startup_state_get(struct device *dev, u8 *event)
653{
654 struct ab3550 *ab;
655
656 ab = dev_get_drvdata(dev->parent);
657 if (!ab->startup_events_read)
658 return -EAGAIN; /* Try again later */
659
660 memcpy(event, ab->startup_events, AB3550_NUM_EVENT_REG);
661 return 0;
662}
663
664int ab3550_startup_irq_enabled(struct device *dev, unsigned int irq)
665{
666 struct ab3550 *ab;
667 struct ab3550_platform_data *plf_data;
668 bool val;
669
670 ab = get_irq_chip_data(irq);
671 plf_data = ab->i2c_client[0]->dev.platform_data;
672 irq -= plf_data->irq.base;
673 val = ((ab->startup_events[irq / 8] & BIT(irq % 8)) != 0);
674
675 return val;
676}
677
678static struct abx500_ops ab3550_ops = {
679 .get_chip_id = ab3550_get_chip_id,
680 .get_register = ab3550_get_register_interruptible,
681 .set_register = ab3550_set_register_interruptible,
682 .get_register_page = ab3550_get_register_page_interruptible,
683 .set_register_page = NULL,
684 .mask_and_set_register = ab3550_mask_and_set_register_interruptible,
685 .event_registers_startup_state_get =
686 ab3550_event_registers_startup_state_get,
687 .startup_irq_enabled = ab3550_startup_irq_enabled,
688};
689
690static irqreturn_t ab3550_irq_handler(int irq, void *data)
691{
692 struct ab3550 *ab = data;
693 int err;
694 unsigned int i;
695 u8 e[AB3550_NUM_EVENT_REG];
696 u8 *events;
697 unsigned long flags;
698
699 events = (ab->startup_events_read ? e : ab->startup_events);
700
701 err = get_register_page_interruptible(ab, AB3550_EVENT_BANK,
702 AB3550_EVENT_REG, events, AB3550_NUM_EVENT_REG);
703 if (err)
704 goto err_event_rd;
705
706 if (!ab->startup_events_read) {
707 dev_info(&ab->i2c_client[0]->dev,
708 "startup events 0x%x,0x%x,0x%x,0x%x,0x%x\n",
709 ab->startup_events[0], ab->startup_events[1],
710 ab->startup_events[2], ab->startup_events[3],
711 ab->startup_events[4]);
712 ab->startup_events_read = true;
713 goto out;
714 }
715
716 /* The two highest bits in event[4] are not used. */
717 events[4] &= 0x3f;
718
719 spin_lock_irqsave(&ab->event_lock, flags);
720 for (i = 0; i < AB3550_NUM_EVENT_REG; i++)
721 events[i] &= ~ab->event_mask[i];
722 spin_unlock_irqrestore(&ab->event_lock, flags);
723
724 for (i = 0; i < AB3550_NUM_EVENT_REG; i++) {
725 u8 bit;
726 u8 event_reg;
727
728 dev_dbg(&ab->i2c_client[0]->dev, "IRQ Event[%d]: 0x%2x\n",
729 i, events[i]);
730
731 event_reg = events[i];
732 for (bit = 0; event_reg; bit++, event_reg /= 2) {
733 if (event_reg % 2) {
734 unsigned int irq;
735 struct ab3550_platform_data *plf_data;
736
737 plf_data = ab->i2c_client[0]->dev.platform_data;
738 irq = plf_data->irq.base + (i * 8) + bit;
739 handle_nested_irq(irq);
740 }
741 }
742 }
743out:
744 return IRQ_HANDLED;
745
746err_event_rd:
747 dev_dbg(&ab->i2c_client[0]->dev, "error reading event registers\n");
748 return IRQ_HANDLED;
749}
750
751#ifdef CONFIG_DEBUG_FS
752static struct ab3550_reg_ranges debug_ranges[AB3550_NUM_BANKS] = {
753 {
754 .count = 6,
755 .range = (struct ab3550_reg_range[]) {
756 {
757 .first = 0x00,
758 .last = 0x0e,
759 },
760 {
761 .first = 0x10,
762 .last = 0x1a,
763 },
764 {
765 .first = 0x1e,
766 .last = 0x4f,
767 },
768 {
769 .first = 0x51,
770 .last = 0x63,
771 },
772 {
773 .first = 0x65,
774 .last = 0xa3,
775 },
776 {
777 .first = 0xa5,
778 .last = 0xa8,
779 },
780 }
781 },
782 {
783 .count = 8,
784 .range = (struct ab3550_reg_range[]) {
785 {
786 .first = 0x00,
787 .last = 0x0e,
788 },
789 {
790 .first = 0x10,
791 .last = 0x17,
792 },
793 {
794 .first = 0x1a,
795 .last = 0x1c,
796 },
797 {
798 .first = 0x20,
799 .last = 0x56,
800 },
801 {
802 .first = 0x5a,
803 .last = 0x88,
804 },
805 {
806 .first = 0x8a,
807 .last = 0xad,
808 },
809 {
810 .first = 0xb0,
811 .last = 0xba,
812 },
813 {
814 .first = 0xbc,
815 .last = 0xc3,
816 },
817 }
818 },
819};
820
821static int ab3550_registers_print(struct seq_file *s, void *p)
822{
823 struct ab3550 *ab = s->private;
824 int bank;
825
826 seq_printf(s, AB3550_NAME_STRING " register values:\n");
827
828 for (bank = 0; bank < AB3550_NUM_BANKS; bank++) {
829 unsigned int i;
830
831 seq_printf(s, " bank %d:\n", bank);
832 for (i = 0; i < debug_ranges[bank].count; i++) {
833 u8 reg;
834
835 for (reg = debug_ranges[bank].range[i].first;
836 reg <= debug_ranges[bank].range[i].last;
837 reg++) {
838 u8 value;
839
840 get_register_interruptible(ab, bank, reg,
841 &value);
842 seq_printf(s, " [%d/0x%02X]: 0x%02X\n", bank,
843 reg, value);
844 }
845 }
846 }
847 return 0;
848}
849
850static int ab3550_registers_open(struct inode *inode, struct file *file)
851{
852 return single_open(file, ab3550_registers_print, inode->i_private);
853}
854
855static const struct file_operations ab3550_registers_fops = {
856 .open = ab3550_registers_open,
857 .read = seq_read,
858 .llseek = seq_lseek,
859 .release = single_release,
860 .owner = THIS_MODULE,
861};
862
863static int ab3550_bank_print(struct seq_file *s, void *p)
864{
865 struct ab3550 *ab = s->private;
866
867 seq_printf(s, "%d\n", ab->debug_bank);
868 return 0;
869}
870
871static int ab3550_bank_open(struct inode *inode, struct file *file)
872{
873 return single_open(file, ab3550_bank_print, inode->i_private);
874}
875
876static ssize_t ab3550_bank_write(struct file *file,
877 const char __user *user_buf,
878 size_t count, loff_t *ppos)
879{
880 struct ab3550 *ab = ((struct seq_file *)(file->private_data))->private;
881 char buf[32];
882 int buf_size;
883 unsigned long user_bank;
884 int err;
885
886 /* Get userspace string and assure termination */
887 buf_size = min(count, (sizeof(buf) - 1));
888 if (copy_from_user(buf, user_buf, buf_size))
889 return -EFAULT;
890 buf[buf_size] = 0;
891
892 err = strict_strtoul(buf, 0, &user_bank);
893 if (err)
894 return -EINVAL;
895
896 if (user_bank >= AB3550_NUM_BANKS) {
897 dev_err(&ab->i2c_client[0]->dev,
898 "debugfs error input > number of banks\n");
899 return -EINVAL;
900 }
901
902 ab->debug_bank = user_bank;
903
904 return buf_size;
905}
906
907static int ab3550_address_print(struct seq_file *s, void *p)
908{
909 struct ab3550 *ab = s->private;
910
911 seq_printf(s, "0x%02X\n", ab->debug_address);
912 return 0;
913}
914
915static int ab3550_address_open(struct inode *inode, struct file *file)
916{
917 return single_open(file, ab3550_address_print, inode->i_private);
918}
919
920static ssize_t ab3550_address_write(struct file *file,
921 const char __user *user_buf,
922 size_t count, loff_t *ppos)
923{
924 struct ab3550 *ab = ((struct seq_file *)(file->private_data))->private;
925 char buf[32];
926 int buf_size;
927 unsigned long user_address;
928 int err;
929
930 /* Get userspace string and assure termination */
931 buf_size = min(count, (sizeof(buf) - 1));
932 if (copy_from_user(buf, user_buf, buf_size))
933 return -EFAULT;
934 buf[buf_size] = 0;
935
936 err = strict_strtoul(buf, 0, &user_address);
937 if (err)
938 return -EINVAL;
939 if (user_address > 0xff) {
940 dev_err(&ab->i2c_client[0]->dev,
941 "debugfs error input > 0xff\n");
942 return -EINVAL;
943 }
944 ab->debug_address = user_address;
945 return buf_size;
946}
947
948static int ab3550_val_print(struct seq_file *s, void *p)
949{
950 struct ab3550 *ab = s->private;
951 int err;
952 u8 regvalue;
953
954 err = get_register_interruptible(ab, (u8)ab->debug_bank,
955 (u8)ab->debug_address, &regvalue);
956 if (err)
957 return -EINVAL;
958 seq_printf(s, "0x%02X\n", regvalue);
959
960 return 0;
961}
962
963static int ab3550_val_open(struct inode *inode, struct file *file)
964{
965 return single_open(file, ab3550_val_print, inode->i_private);
966}
967
968static ssize_t ab3550_val_write(struct file *file,
969 const char __user *user_buf,
970 size_t count, loff_t *ppos)
971{
972 struct ab3550 *ab = ((struct seq_file *)(file->private_data))->private;
973 char buf[32];
974 int buf_size;
975 unsigned long user_val;
976 int err;
977 u8 regvalue;
978
979 /* Get userspace string and assure termination */
980 buf_size = min(count, (sizeof(buf)-1));
981 if (copy_from_user(buf, user_buf, buf_size))
982 return -EFAULT;
983 buf[buf_size] = 0;
984
985 err = strict_strtoul(buf, 0, &user_val);
986 if (err)
987 return -EINVAL;
988 if (user_val > 0xff) {
989 dev_err(&ab->i2c_client[0]->dev,
990 "debugfs error input > 0xff\n");
991 return -EINVAL;
992 }
993 err = mask_and_set_register_interruptible(
994 ab, (u8)ab->debug_bank,
995 (u8)ab->debug_address, 0xFF, (u8)user_val);
996 if (err)
997 return -EINVAL;
998
999 get_register_interruptible(ab, (u8)ab->debug_bank,
1000 (u8)ab->debug_address, &regvalue);
1001 if (err)
1002 return -EINVAL;
1003
1004 return buf_size;
1005}
1006
1007static const struct file_operations ab3550_bank_fops = {
1008 .open = ab3550_bank_open,
1009 .write = ab3550_bank_write,
1010 .read = seq_read,
1011 .llseek = seq_lseek,
1012 .release = single_release,
1013 .owner = THIS_MODULE,
1014};
1015
1016static const struct file_operations ab3550_address_fops = {
1017 .open = ab3550_address_open,
1018 .write = ab3550_address_write,
1019 .read = seq_read,
1020 .llseek = seq_lseek,
1021 .release = single_release,
1022 .owner = THIS_MODULE,
1023};
1024
1025static const struct file_operations ab3550_val_fops = {
1026 .open = ab3550_val_open,
1027 .write = ab3550_val_write,
1028 .read = seq_read,
1029 .llseek = seq_lseek,
1030 .release = single_release,
1031 .owner = THIS_MODULE,
1032};
1033
1034static struct dentry *ab3550_dir;
1035static struct dentry *ab3550_reg_file;
1036static struct dentry *ab3550_bank_file;
1037static struct dentry *ab3550_address_file;
1038static struct dentry *ab3550_val_file;
1039
1040static inline void ab3550_setup_debugfs(struct ab3550 *ab)
1041{
1042 ab->debug_bank = 0;
1043 ab->debug_address = 0x00;
1044
1045 ab3550_dir = debugfs_create_dir(AB3550_NAME_STRING, NULL);
1046 if (!ab3550_dir)
1047 goto exit_no_debugfs;
1048
1049 ab3550_reg_file = debugfs_create_file("all-registers",
1050 S_IRUGO, ab3550_dir, ab, &ab3550_registers_fops);
1051 if (!ab3550_reg_file)
1052 goto exit_destroy_dir;
1053
1054 ab3550_bank_file = debugfs_create_file("register-bank",
1055 (S_IRUGO | S_IWUGO), ab3550_dir, ab, &ab3550_bank_fops);
1056 if (!ab3550_bank_file)
1057 goto exit_destroy_reg;
1058
1059 ab3550_address_file = debugfs_create_file("register-address",
1060 (S_IRUGO | S_IWUGO), ab3550_dir, ab, &ab3550_address_fops);
1061 if (!ab3550_address_file)
1062 goto exit_destroy_bank;
1063
1064 ab3550_val_file = debugfs_create_file("register-value",
1065 (S_IRUGO | S_IWUGO), ab3550_dir, ab, &ab3550_val_fops);
1066 if (!ab3550_val_file)
1067 goto exit_destroy_address;
1068
1069 return;
1070
1071exit_destroy_address:
1072 debugfs_remove(ab3550_address_file);
1073exit_destroy_bank:
1074 debugfs_remove(ab3550_bank_file);
1075exit_destroy_reg:
1076 debugfs_remove(ab3550_reg_file);
1077exit_destroy_dir:
1078 debugfs_remove(ab3550_dir);
1079exit_no_debugfs:
1080 dev_err(&ab->i2c_client[0]->dev, "failed to create debugfs entries.\n");
1081 return;
1082}
1083
1084static inline void ab3550_remove_debugfs(void)
1085{
1086 debugfs_remove(ab3550_val_file);
1087 debugfs_remove(ab3550_address_file);
1088 debugfs_remove(ab3550_bank_file);
1089 debugfs_remove(ab3550_reg_file);
1090 debugfs_remove(ab3550_dir);
1091}
1092
1093#else /* !CONFIG_DEBUG_FS */
1094static inline void ab3550_setup_debugfs(struct ab3550 *ab)
1095{
1096}
1097static inline void ab3550_remove_debugfs(void)
1098{
1099}
1100#endif
1101
1102/*
1103 * Basic set-up, datastructure creation/destruction and I2C interface.
1104 * This sets up a default config in the AB3550 chip so that it
1105 * will work as expected.
1106 */
1107static int __init ab3550_setup(struct ab3550 *ab)
1108{
1109 int err = 0;
1110 int i;
1111 struct ab3550_platform_data *plf_data;
1112 struct abx500_init_settings *settings;
1113
1114 plf_data = ab->i2c_client[0]->dev.platform_data;
1115 settings = plf_data->init_settings;
1116
1117 for (i = 0; i < plf_data->init_settings_sz; i++) {
1118 err = mask_and_set_register_interruptible(ab,
1119 settings[i].bank,
1120 settings[i].reg,
1121 0xFF, settings[i].setting);
1122 if (err)
1123 goto exit_no_setup;
1124
1125 /* If event mask register update the event mask in ab3550 */
1126 if ((settings[i].bank == 0) &&
1127 (AB3550_IMR1 <= settings[i].reg) &&
1128 (settings[i].reg <= AB3550_IMR5)) {
1129 ab->event_mask[settings[i].reg - AB3550_IMR1] =
1130 settings[i].setting;
1131 }
1132 }
1133exit_no_setup:
1134 return err;
1135}
1136
1137static void ab3550_mask_work(struct work_struct *work)
1138{
1139 struct ab3550 *ab = container_of(work, struct ab3550, mask_work);
1140 int i;
1141 unsigned long flags;
1142 u8 mask[AB3550_NUM_EVENT_REG];
1143
1144 spin_lock_irqsave(&ab->event_lock, flags);
1145 for (i = 0; i < AB3550_NUM_EVENT_REG; i++)
1146 mask[i] = ab->event_mask[i];
1147 spin_unlock_irqrestore(&ab->event_lock, flags);
1148
1149 for (i = 0; i < AB3550_NUM_EVENT_REG; i++) {
1150 int err;
1151
1152 err = mask_and_set_register_interruptible(ab, 0,
1153 (AB3550_IMR1 + i), ~0, mask[i]);
1154 if (err)
1155 dev_err(&ab->i2c_client[0]->dev,
1156 "ab3550_mask_work failed 0x%x,0x%x\n",
1157 (AB3550_IMR1 + i), mask[i]);
1158 }
1159}
1160
1161static void ab3550_mask(unsigned int irq)
1162{
1163 unsigned long flags;
1164 struct ab3550 *ab;
1165 struct ab3550_platform_data *plf_data;
1166
1167 ab = get_irq_chip_data(irq);
1168 plf_data = ab->i2c_client[0]->dev.platform_data;
1169 irq -= plf_data->irq.base;
1170
1171 spin_lock_irqsave(&ab->event_lock, flags);
1172 ab->event_mask[irq / 8] |= BIT(irq % 8);
1173 spin_unlock_irqrestore(&ab->event_lock, flags);
1174
1175 schedule_work(&ab->mask_work);
1176}
1177
1178static void ab3550_unmask(unsigned int irq)
1179{
1180 unsigned long flags;
1181 struct ab3550 *ab;
1182 struct ab3550_platform_data *plf_data;
1183
1184 ab = get_irq_chip_data(irq);
1185 plf_data = ab->i2c_client[0]->dev.platform_data;
1186 irq -= plf_data->irq.base;
1187
1188 spin_lock_irqsave(&ab->event_lock, flags);
1189 ab->event_mask[irq / 8] &= ~BIT(irq % 8);
1190 spin_unlock_irqrestore(&ab->event_lock, flags);
1191
1192 schedule_work(&ab->mask_work);
1193}
1194
1195static void noop(unsigned int irq)
1196{
1197}
1198
1199static struct irq_chip ab3550_irq_chip = {
1200 .name = "ab3550-core", /* Keep the same name as the request */
1201 .startup = NULL, /* defaults to enable */
1202 .shutdown = NULL, /* defaults to disable */
1203 .enable = NULL, /* defaults to unmask */
1204 .disable = ab3550_mask, /* No default to mask in chip.c */
1205 .ack = noop,
1206 .mask = ab3550_mask,
1207 .unmask = ab3550_unmask,
1208 .end = NULL,
1209};
1210
1211struct ab_family_id {
1212 u8 id;
1213 char *name;
1214};
1215
1216static const struct ab_family_id ids[] __initdata = {
1217 /* AB3550 */
1218 {
1219 .id = AB3550_P1A,
1220 .name = "P1A"
1221 },
1222 /* Terminator */
1223 {
1224 .id = 0x00,
1225 }
1226};
1227
1228static int __init ab3550_probe(struct i2c_client *client,
1229 const struct i2c_device_id *id)
1230{
1231 struct ab3550 *ab;
1232 struct ab3550_platform_data *ab3550_plf_data =
1233 client->dev.platform_data;
1234 int err;
1235 int i;
1236 int num_i2c_clients = 0;
1237
1238 ab = kzalloc(sizeof(struct ab3550), GFP_KERNEL);
1239 if (!ab) {
1240 dev_err(&client->dev,
1241 "could not allocate " AB3550_NAME_STRING " device\n");
1242 return -ENOMEM;
1243 }
1244
1245 /* Initialize data structure */
1246 mutex_init(&ab->access_mutex);
1247 spin_lock_init(&ab->event_lock);
1248 ab->i2c_client[0] = client;
1249
1250 i2c_set_clientdata(client, ab);
1251
1252 /* Read chip ID register */
1253 err = get_register_interruptible(ab, 0, AB3550_CID_REG, &ab->chip_id);
1254 if (err) {
1255 dev_err(&client->dev, "could not communicate with the analog "
1256 "baseband chip\n");
1257 goto exit_no_detect;
1258 }
1259
1260 for (i = 0; ids[i].id != 0x0; i++) {
1261 if (ids[i].id == ab->chip_id) {
1262 snprintf(&ab->chip_name[0], sizeof(ab->chip_name) - 1,
1263 AB3550_ID_FORMAT_STRING, ids[i].name);
1264 break;
1265 }
1266 }
1267
1268 if (ids[i].id == 0x0) {
1269 dev_err(&client->dev, "unknown analog baseband chip id: 0x%x\n",
1270 ab->chip_id);
1271 dev_err(&client->dev, "driver not started!\n");
1272 goto exit_no_detect;
1273 }
1274
1275 dev_info(&client->dev, "detected AB chip: %s\n", &ab->chip_name[0]);
1276
1277 /* Attach other dummy I2C clients. */
1278 while (++num_i2c_clients < AB3550_NUM_BANKS) {
1279 ab->i2c_client[num_i2c_clients] =
1280 i2c_new_dummy(client->adapter,
1281 (client->addr + num_i2c_clients));
1282 if (!ab->i2c_client[num_i2c_clients]) {
1283 err = -ENOMEM;
1284 goto exit_no_dummy_client;
1285 }
1286 strlcpy(ab->i2c_client[num_i2c_clients]->name, id->name,
1287 sizeof(ab->i2c_client[num_i2c_clients]->name));
1288 }
1289
1290 err = ab3550_setup(ab);
1291 if (err)
1292 goto exit_no_setup;
1293
1294 INIT_WORK(&ab->mask_work, ab3550_mask_work);
1295
1296 for (i = 0; i < ab3550_plf_data->irq.count; i++) {
1297 unsigned int irq;
1298
1299 irq = ab3550_plf_data->irq.base + i;
1300 set_irq_chip_data(irq, ab);
1301 set_irq_chip_and_handler(irq, &ab3550_irq_chip,
1302 handle_simple_irq);
1303 set_irq_nested_thread(irq, 1);
1304#ifdef CONFIG_ARM
1305 set_irq_flags(irq, IRQF_VALID);
1306#else
1307 set_irq_noprobe(irq);
1308#endif
1309 }
1310
1311 err = request_threaded_irq(client->irq, NULL, ab3550_irq_handler,
1312 IRQF_ONESHOT, "ab3550-core", ab);
1313 /* This real unpredictable IRQ is of course sampled for entropy */
1314 rand_initialize_irq(client->irq);
1315
1316 if (err)
1317 goto exit_no_irq;
1318
1319 err = abx500_register_ops(&client->dev, &ab3550_ops);
1320 if (err)
1321 goto exit_no_ops;
1322
1323 /* Set up and register the platform devices. */
1324 for (i = 0; i < AB3550_NUM_DEVICES; i++) {
1325 ab3550_devs[i].platform_data = ab3550_plf_data->dev_data[i];
1326 ab3550_devs[i].data_size = ab3550_plf_data->dev_data_sz[i];
1327 }
1328
1329 err = mfd_add_devices(&client->dev, 0, ab3550_devs,
1330 ARRAY_SIZE(ab3550_devs), NULL,
1331 ab3550_plf_data->irq.base);
1332
1333 ab3550_setup_debugfs(ab);
1334
1335 return 0;
1336
1337exit_no_ops:
1338exit_no_irq:
1339exit_no_setup:
1340exit_no_dummy_client:
1341 /* Unregister the dummy i2c clients. */
1342 while (--num_i2c_clients)
1343 i2c_unregister_device(ab->i2c_client[num_i2c_clients]);
1344exit_no_detect:
1345 kfree(ab);
1346 return err;
1347}
1348
1349static int __exit ab3550_remove(struct i2c_client *client)
1350{
1351 struct ab3550 *ab = i2c_get_clientdata(client);
1352 int num_i2c_clients = AB3550_NUM_BANKS;
1353
1354 mfd_remove_devices(&client->dev);
1355 ab3550_remove_debugfs();
1356
1357 while (--num_i2c_clients)
1358 i2c_unregister_device(ab->i2c_client[num_i2c_clients]);
1359
1360 /*
1361 * At this point, all subscribers should have unregistered
1362 * their notifiers so deactivate IRQ
1363 */
1364 free_irq(client->irq, ab);
1365 kfree(ab);
1366 return 0;
1367}
1368
1369static const struct i2c_device_id ab3550_id[] = {
1370 {AB3550_NAME_STRING, 0},
1371 {}
1372};
1373MODULE_DEVICE_TABLE(i2c, ab3550_id);
1374
1375static struct i2c_driver ab3550_driver = {
1376 .driver = {
1377 .name = AB3550_NAME_STRING,
1378 .owner = THIS_MODULE,
1379 },
1380 .id_table = ab3550_id,
1381 .probe = ab3550_probe,
1382 .remove = __exit_p(ab3550_remove),
1383};
1384
1385static int __init ab3550_i2c_init(void)
1386{
1387 return i2c_add_driver(&ab3550_driver);
1388}
1389
1390static void __exit ab3550_i2c_exit(void)
1391{
1392 i2c_del_driver(&ab3550_driver);
1393}
1394
1395subsys_initcall(ab3550_i2c_init);
1396module_exit(ab3550_i2c_exit);
1397
1398MODULE_AUTHOR("Mattias Wallin <mattias.wallin@stericsson.com>");
1399MODULE_DESCRIPTION("AB3550 core driver");
1400MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/ab4500-core.c b/drivers/mfd/ab4500-core.c
deleted file mode 100644
index c275daa3ab1a..000000000000
--- a/drivers/mfd/ab4500-core.c
+++ /dev/null
@@ -1,209 +0,0 @@
1/*
2 * Copyright (C) 2009 ST-Ericsson
3 *
4 * Author: Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com>
5 *
6 * This program is free software; you can redistribute it
7 * and/or modify it under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation.
9 *
10 * AB4500 is a companion power management chip used with U8500.
11 * On this platform, this is interfaced with SSP0 controller
12 * which is a ARM primecell pl022.
13 *
14 * At the moment the module just exports read/write features.
15 * Interrupt management to be added - TODO.
16 */
17#include <linux/kernel.h>
18#include <linux/slab.h>
19#include <linux/init.h>
20#include <linux/module.h>
21#include <linux/platform_device.h>
22#include <linux/spi/spi.h>
23#include <linux/mfd/ab4500.h>
24
25/* just required if probe fails, we need to
26 * unregister the device
27 */
28static struct spi_driver ab4500_driver;
29
30/*
31 * This funtion writes to any AB4500 registers using
32 * SPI protocol & before it writes it packs the data
33 * in the below 24 bit frame format
34 *
35 * *|------------------------------------|
36 * *| 23|22...18|17.......10|9|8|7......0|
37 * *| r/w bank adr data |
38 * * ------------------------------------
39 *
40 * This function shouldn't be called from interrupt
41 * context
42 */
43int ab4500_write(struct ab4500 *ab4500, unsigned char block,
44 unsigned long addr, unsigned char data)
45{
46 struct spi_transfer xfer;
47 struct spi_message msg;
48 int err;
49 unsigned long spi_data =
50 block << 18 | addr << 10 | data;
51
52 mutex_lock(&ab4500->lock);
53 ab4500->tx_buf[0] = spi_data;
54 ab4500->rx_buf[0] = 0;
55
56 xfer.tx_buf = ab4500->tx_buf;
57 xfer.rx_buf = NULL;
58 xfer.len = sizeof(unsigned long);
59
60 spi_message_init(&msg);
61 spi_message_add_tail(&xfer, &msg);
62
63 err = spi_sync(ab4500->spi, &msg);
64 mutex_unlock(&ab4500->lock);
65
66 return err;
67}
68EXPORT_SYMBOL(ab4500_write);
69
70int ab4500_read(struct ab4500 *ab4500, unsigned char block,
71 unsigned long addr)
72{
73 struct spi_transfer xfer;
74 struct spi_message msg;
75 unsigned long spi_data =
76 1 << 23 | block << 18 | addr << 10;
77
78 mutex_lock(&ab4500->lock);
79 ab4500->tx_buf[0] = spi_data;
80 ab4500->rx_buf[0] = 0;
81
82 xfer.tx_buf = ab4500->tx_buf;
83 xfer.rx_buf = ab4500->rx_buf;
84 xfer.len = sizeof(unsigned long);
85
86 spi_message_init(&msg);
87 spi_message_add_tail(&xfer, &msg);
88
89 spi_sync(ab4500->spi, &msg);
90 mutex_unlock(&ab4500->lock);
91
92 return ab4500->rx_buf[0];
93}
94EXPORT_SYMBOL(ab4500_read);
95
96/* ref: ab3100 core */
97#define AB4500_DEVICE(devname, devid) \
98static struct platform_device ab4500_##devname##_device = { \
99 .name = devid, \
100 .id = -1, \
101}
102
103/* list of childern devices of ab4500 - all are
104 * not populated here - TODO
105 */
106AB4500_DEVICE(charger, "ab4500-charger");
107AB4500_DEVICE(audio, "ab4500-audio");
108AB4500_DEVICE(usb, "ab4500-usb");
109AB4500_DEVICE(tvout, "ab4500-tvout");
110AB4500_DEVICE(sim, "ab4500-sim");
111AB4500_DEVICE(gpadc, "ab4500-gpadc");
112AB4500_DEVICE(clkmgt, "ab4500-clkmgt");
113AB4500_DEVICE(misc, "ab4500-misc");
114
115static struct platform_device *ab4500_platform_devs[] = {
116 &ab4500_charger_device,
117 &ab4500_audio_device,
118 &ab4500_usb_device,
119 &ab4500_tvout_device,
120 &ab4500_sim_device,
121 &ab4500_gpadc_device,
122 &ab4500_clkmgt_device,
123 &ab4500_misc_device,
124};
125
126static int __init ab4500_probe(struct spi_device *spi)
127{
128 struct ab4500 *ab4500;
129 unsigned char revision;
130 int err = 0;
131 int i;
132
133 ab4500 = kzalloc(sizeof *ab4500, GFP_KERNEL);
134 if (!ab4500) {
135 dev_err(&spi->dev, "could not allocate AB4500\n");
136 err = -ENOMEM;
137 goto not_detect;
138 }
139
140 ab4500->spi = spi;
141 spi_set_drvdata(spi, ab4500);
142
143 mutex_init(&ab4500->lock);
144
145 /* read the revision register */
146 revision = ab4500_read(ab4500, AB4500_MISC, AB4500_REV_REG);
147
148 /* revision id 0x0 is for early drop, 0x10 is for cut1.0 */
149 if (revision == 0x0 || revision == 0x10)
150 dev_info(&spi->dev, "Detected chip: %s, revision = %x\n",
151 ab4500_driver.driver.name, revision);
152 else {
153 dev_err(&spi->dev, "unknown chip: 0x%x\n", revision);
154 goto not_detect;
155 }
156
157 for (i = 0; i < ARRAY_SIZE(ab4500_platform_devs); i++) {
158 ab4500_platform_devs[i]->dev.parent =
159 &spi->dev;
160 platform_set_drvdata(ab4500_platform_devs[i], ab4500);
161 }
162
163 /* register the ab4500 platform devices */
164 platform_add_devices(ab4500_platform_devs,
165 ARRAY_SIZE(ab4500_platform_devs));
166
167 return err;
168
169 not_detect:
170 spi_unregister_driver(&ab4500_driver);
171 kfree(ab4500);
172 return err;
173}
174
175static int __devexit ab4500_remove(struct spi_device *spi)
176{
177 struct ab4500 *ab4500 =
178 spi_get_drvdata(spi);
179
180 kfree(ab4500);
181
182 return 0;
183}
184
185static struct spi_driver ab4500_driver = {
186 .driver = {
187 .name = "ab4500",
188 .owner = THIS_MODULE,
189 },
190 .probe = ab4500_probe,
191 .remove = __devexit_p(ab4500_remove)
192};
193
194static int __devinit ab4500_init(void)
195{
196 return spi_register_driver(&ab4500_driver);
197}
198
199static void __exit ab4500_exit(void)
200{
201 spi_unregister_driver(&ab4500_driver);
202}
203
204subsys_initcall(ab4500_init);
205module_exit(ab4500_exit);
206
207MODULE_AUTHOR("Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com");
208MODULE_DESCRIPTION("AB4500 core driver");
209MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
new file mode 100644
index 000000000000..f3d26fa9c34d
--- /dev/null
+++ b/drivers/mfd/ab8500-core.c
@@ -0,0 +1,444 @@
1/*
2 * Copyright (C) ST-Ericsson SA 2010
3 *
4 * License Terms: GNU General Public License v2
5 * Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
6 * Author: Rabin Vincent <rabin.vincent@stericsson.com>
7 */
8
9#include <linux/kernel.h>
10#include <linux/slab.h>
11#include <linux/init.h>
12#include <linux/irq.h>
13#include <linux/delay.h>
14#include <linux/interrupt.h>
15#include <linux/module.h>
16#include <linux/platform_device.h>
17#include <linux/mfd/core.h>
18#include <linux/mfd/ab8500.h>
19
20/*
21 * Interrupt register offsets
22 * Bank : 0x0E
23 */
24#define AB8500_IT_SOURCE1_REG 0x0E00
25#define AB8500_IT_SOURCE2_REG 0x0E01
26#define AB8500_IT_SOURCE3_REG 0x0E02
27#define AB8500_IT_SOURCE4_REG 0x0E03
28#define AB8500_IT_SOURCE5_REG 0x0E04
29#define AB8500_IT_SOURCE6_REG 0x0E05
30#define AB8500_IT_SOURCE7_REG 0x0E06
31#define AB8500_IT_SOURCE8_REG 0x0E07
32#define AB8500_IT_SOURCE19_REG 0x0E12
33#define AB8500_IT_SOURCE20_REG 0x0E13
34#define AB8500_IT_SOURCE21_REG 0x0E14
35#define AB8500_IT_SOURCE22_REG 0x0E15
36#define AB8500_IT_SOURCE23_REG 0x0E16
37#define AB8500_IT_SOURCE24_REG 0x0E17
38
39/*
40 * latch registers
41 */
42#define AB8500_IT_LATCH1_REG 0x0E20
43#define AB8500_IT_LATCH2_REG 0x0E21
44#define AB8500_IT_LATCH3_REG 0x0E22
45#define AB8500_IT_LATCH4_REG 0x0E23
46#define AB8500_IT_LATCH5_REG 0x0E24
47#define AB8500_IT_LATCH6_REG 0x0E25
48#define AB8500_IT_LATCH7_REG 0x0E26
49#define AB8500_IT_LATCH8_REG 0x0E27
50#define AB8500_IT_LATCH9_REG 0x0E28
51#define AB8500_IT_LATCH10_REG 0x0E29
52#define AB8500_IT_LATCH19_REG 0x0E32
53#define AB8500_IT_LATCH20_REG 0x0E33
54#define AB8500_IT_LATCH21_REG 0x0E34
55#define AB8500_IT_LATCH22_REG 0x0E35
56#define AB8500_IT_LATCH23_REG 0x0E36
57#define AB8500_IT_LATCH24_REG 0x0E37
58
59/*
60 * mask registers
61 */
62
63#define AB8500_IT_MASK1_REG 0x0E40
64#define AB8500_IT_MASK2_REG 0x0E41
65#define AB8500_IT_MASK3_REG 0x0E42
66#define AB8500_IT_MASK4_REG 0x0E43
67#define AB8500_IT_MASK5_REG 0x0E44
68#define AB8500_IT_MASK6_REG 0x0E45
69#define AB8500_IT_MASK7_REG 0x0E46
70#define AB8500_IT_MASK8_REG 0x0E47
71#define AB8500_IT_MASK9_REG 0x0E48
72#define AB8500_IT_MASK10_REG 0x0E49
73#define AB8500_IT_MASK11_REG 0x0E4A
74#define AB8500_IT_MASK12_REG 0x0E4B
75#define AB8500_IT_MASK13_REG 0x0E4C
76#define AB8500_IT_MASK14_REG 0x0E4D
77#define AB8500_IT_MASK15_REG 0x0E4E
78#define AB8500_IT_MASK16_REG 0x0E4F
79#define AB8500_IT_MASK17_REG 0x0E50
80#define AB8500_IT_MASK18_REG 0x0E51
81#define AB8500_IT_MASK19_REG 0x0E52
82#define AB8500_IT_MASK20_REG 0x0E53
83#define AB8500_IT_MASK21_REG 0x0E54
84#define AB8500_IT_MASK22_REG 0x0E55
85#define AB8500_IT_MASK23_REG 0x0E56
86#define AB8500_IT_MASK24_REG 0x0E57
87
88#define AB8500_REV_REG 0x1080
89
90/*
91 * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt
92 * numbers are indexed into this array with (num / 8).
93 *
94 * This is one off from the register names, i.e. AB8500_IT_MASK1_REG is at
95 * offset 0.
96 */
97static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = {
98 0, 1, 2, 3, 4, 6, 7, 8, 9, 18, 19, 20, 21,
99};
100
101static int __ab8500_write(struct ab8500 *ab8500, u16 addr, u8 data)
102{
103 int ret;
104
105 dev_vdbg(ab8500->dev, "wr: addr %#x <= %#x\n", addr, data);
106
107 ret = ab8500->write(ab8500, addr, data);
108 if (ret < 0)
109 dev_err(ab8500->dev, "failed to write reg %#x: %d\n",
110 addr, ret);
111
112 return ret;
113}
114
115/**
116 * ab8500_write() - write an AB8500 register
117 * @ab8500: device to write to
118 * @addr: address of the register
119 * @data: value to write
120 */
121int ab8500_write(struct ab8500 *ab8500, u16 addr, u8 data)
122{
123 int ret;
124
125 mutex_lock(&ab8500->lock);
126 ret = __ab8500_write(ab8500, addr, data);
127 mutex_unlock(&ab8500->lock);
128
129 return ret;
130}
131EXPORT_SYMBOL_GPL(ab8500_write);
132
133static int __ab8500_read(struct ab8500 *ab8500, u16 addr)
134{
135 int ret;
136
137 ret = ab8500->read(ab8500, addr);
138 if (ret < 0)
139 dev_err(ab8500->dev, "failed to read reg %#x: %d\n",
140 addr, ret);
141
142 dev_vdbg(ab8500->dev, "rd: addr %#x => data %#x\n", addr, ret);
143
144 return ret;
145}
146
147/**
148 * ab8500_read() - read an AB8500 register
149 * @ab8500: device to read from
150 * @addr: address of the register
151 */
152int ab8500_read(struct ab8500 *ab8500, u16 addr)
153{
154 int ret;
155
156 mutex_lock(&ab8500->lock);
157 ret = __ab8500_read(ab8500, addr);
158 mutex_unlock(&ab8500->lock);
159
160 return ret;
161}
162EXPORT_SYMBOL_GPL(ab8500_read);
163
164/**
165 * ab8500_set_bits() - set a bitfield in an AB8500 register
166 * @ab8500: device to read from
167 * @addr: address of the register
168 * @mask: mask of the bitfield to modify
169 * @data: value to set to the bitfield
170 */
171int ab8500_set_bits(struct ab8500 *ab8500, u16 addr, u8 mask, u8 data)
172{
173 int ret;
174
175 mutex_lock(&ab8500->lock);
176
177 ret = __ab8500_read(ab8500, addr);
178 if (ret < 0)
179 goto out;
180
181 ret &= ~mask;
182 ret |= data;
183
184 ret = __ab8500_write(ab8500, addr, ret);
185
186out:
187 mutex_unlock(&ab8500->lock);
188 return ret;
189}
190EXPORT_SYMBOL_GPL(ab8500_set_bits);
191
192static void ab8500_irq_lock(unsigned int irq)
193{
194 struct ab8500 *ab8500 = get_irq_chip_data(irq);
195
196 mutex_lock(&ab8500->irq_lock);
197}
198
199static void ab8500_irq_sync_unlock(unsigned int irq)
200{
201 struct ab8500 *ab8500 = get_irq_chip_data(irq);
202 int i;
203
204 for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) {
205 u8 old = ab8500->oldmask[i];
206 u8 new = ab8500->mask[i];
207 int reg;
208
209 if (new == old)
210 continue;
211
212 ab8500->oldmask[i] = new;
213
214 reg = AB8500_IT_MASK1_REG + ab8500_irq_regoffset[i];
215 ab8500_write(ab8500, reg, new);
216 }
217
218 mutex_unlock(&ab8500->irq_lock);
219}
220
221static void ab8500_irq_mask(unsigned int irq)
222{
223 struct ab8500 *ab8500 = get_irq_chip_data(irq);
224 int offset = irq - ab8500->irq_base;
225 int index = offset / 8;
226 int mask = 1 << (offset % 8);
227
228 ab8500->mask[index] |= mask;
229}
230
231static void ab8500_irq_unmask(unsigned int irq)
232{
233 struct ab8500 *ab8500 = get_irq_chip_data(irq);
234 int offset = irq - ab8500->irq_base;
235 int index = offset / 8;
236 int mask = 1 << (offset % 8);
237
238 ab8500->mask[index] &= ~mask;
239}
240
241static struct irq_chip ab8500_irq_chip = {
242 .name = "ab8500",
243 .bus_lock = ab8500_irq_lock,
244 .bus_sync_unlock = ab8500_irq_sync_unlock,
245 .mask = ab8500_irq_mask,
246 .unmask = ab8500_irq_unmask,
247};
248
249static irqreturn_t ab8500_irq(int irq, void *dev)
250{
251 struct ab8500 *ab8500 = dev;
252 int i;
253
254 dev_vdbg(ab8500->dev, "interrupt\n");
255
256 for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) {
257 int regoffset = ab8500_irq_regoffset[i];
258 int status;
259
260 status = ab8500_read(ab8500, AB8500_IT_LATCH1_REG + regoffset);
261 if (status <= 0)
262 continue;
263
264 do {
265 int bit = __ffs(status);
266 int line = i * 8 + bit;
267
268 handle_nested_irq(ab8500->irq_base + line);
269 status &= ~(1 << bit);
270 } while (status);
271 }
272
273 return IRQ_HANDLED;
274}
275
276static int ab8500_irq_init(struct ab8500 *ab8500)
277{
278 int base = ab8500->irq_base;
279 int irq;
280
281 for (irq = base; irq < base + AB8500_NR_IRQS; irq++) {
282 set_irq_chip_data(irq, ab8500);
283 set_irq_chip_and_handler(irq, &ab8500_irq_chip,
284 handle_simple_irq);
285 set_irq_nested_thread(irq, 1);
286#ifdef CONFIG_ARM
287 set_irq_flags(irq, IRQF_VALID);
288#else
289 set_irq_noprobe(irq);
290#endif
291 }
292
293 return 0;
294}
295
296static void ab8500_irq_remove(struct ab8500 *ab8500)
297{
298 int base = ab8500->irq_base;
299 int irq;
300
301 for (irq = base; irq < base + AB8500_NR_IRQS; irq++) {
302#ifdef CONFIG_ARM
303 set_irq_flags(irq, 0);
304#endif
305 set_irq_chip_and_handler(irq, NULL, NULL);
306 set_irq_chip_data(irq, NULL);
307 }
308}
309
310static struct resource ab8500_gpadc_resources[] = {
311 {
312 .name = "HW_CONV_END",
313 .start = AB8500_INT_GP_HW_ADC_CONV_END,
314 .end = AB8500_INT_GP_HW_ADC_CONV_END,
315 .flags = IORESOURCE_IRQ,
316 },
317 {
318 .name = "SW_CONV_END",
319 .start = AB8500_INT_GP_SW_ADC_CONV_END,
320 .end = AB8500_INT_GP_SW_ADC_CONV_END,
321 .flags = IORESOURCE_IRQ,
322 },
323};
324
325static struct resource ab8500_rtc_resources[] = {
326 {
327 .name = "60S",
328 .start = AB8500_INT_RTC_60S,
329 .end = AB8500_INT_RTC_60S,
330 .flags = IORESOURCE_IRQ,
331 },
332 {
333 .name = "ALARM",
334 .start = AB8500_INT_RTC_ALARM,
335 .end = AB8500_INT_RTC_ALARM,
336 .flags = IORESOURCE_IRQ,
337 },
338};
339
340static struct mfd_cell ab8500_devs[] = {
341 {
342 .name = "ab8500-gpadc",
343 .num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
344 .resources = ab8500_gpadc_resources,
345 },
346 {
347 .name = "ab8500-rtc",
348 .num_resources = ARRAY_SIZE(ab8500_rtc_resources),
349 .resources = ab8500_rtc_resources,
350 },
351 { .name = "ab8500-charger", },
352 { .name = "ab8500-audio", },
353 { .name = "ab8500-usb", },
354 { .name = "ab8500-pwm", },
355};
356
357int __devinit ab8500_init(struct ab8500 *ab8500)
358{
359 struct ab8500_platform_data *plat = dev_get_platdata(ab8500->dev);
360 int ret;
361 int i;
362
363 if (plat)
364 ab8500->irq_base = plat->irq_base;
365
366 mutex_init(&ab8500->lock);
367 mutex_init(&ab8500->irq_lock);
368
369 ret = ab8500_read(ab8500, AB8500_REV_REG);
370 if (ret < 0)
371 return ret;
372
373 /*
374 * 0x0 - Early Drop
375 * 0x10 - Cut 1.0
376 * 0x11 - Cut 1.1
377 */
378 if (ret == 0x0 || ret == 0x10 || ret == 0x11) {
379 ab8500->revision = ret;
380 dev_info(ab8500->dev, "detected chip, revision: %#x\n", ret);
381 } else {
382 dev_err(ab8500->dev, "unknown chip, revision: %#x\n", ret);
383 return -EINVAL;
384 }
385
386 if (plat && plat->init)
387 plat->init(ab8500);
388
389 /* Clear and mask all interrupts */
390 for (i = 0; i < 10; i++) {
391 ab8500_read(ab8500, AB8500_IT_LATCH1_REG + i);
392 ab8500_write(ab8500, AB8500_IT_MASK1_REG + i, 0xff);
393 }
394
395 for (i = 18; i < 24; i++) {
396 ab8500_read(ab8500, AB8500_IT_LATCH1_REG + i);
397 ab8500_write(ab8500, AB8500_IT_MASK1_REG + i, 0xff);
398 }
399
400 for (i = 0; i < AB8500_NUM_IRQ_REGS; i++)
401 ab8500->mask[i] = ab8500->oldmask[i] = 0xff;
402
403 if (ab8500->irq_base) {
404 ret = ab8500_irq_init(ab8500);
405 if (ret)
406 return ret;
407
408 ret = request_threaded_irq(ab8500->irq, NULL, ab8500_irq,
409 IRQF_ONESHOT, "ab8500", ab8500);
410 if (ret)
411 goto out_removeirq;
412 }
413
414 ret = mfd_add_devices(ab8500->dev, -1, ab8500_devs,
415 ARRAY_SIZE(ab8500_devs), NULL,
416 ab8500->irq_base);
417 if (ret)
418 goto out_freeirq;
419
420 return ret;
421
422out_freeirq:
423 if (ab8500->irq_base) {
424 free_irq(ab8500->irq, ab8500);
425out_removeirq:
426 ab8500_irq_remove(ab8500);
427 }
428 return ret;
429}
430
431int __devexit ab8500_exit(struct ab8500 *ab8500)
432{
433 mfd_remove_devices(ab8500->dev);
434 if (ab8500->irq_base) {
435 free_irq(ab8500->irq, ab8500);
436 ab8500_irq_remove(ab8500);
437 }
438
439 return 0;
440}
441
442MODULE_AUTHOR("Srinidhi Kasagar, Rabin Vincent");
443MODULE_DESCRIPTION("AB8500 MFD core");
444MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/ab8500-spi.c b/drivers/mfd/ab8500-spi.c
new file mode 100644
index 000000000000..b81d4f768ef6
--- /dev/null
+++ b/drivers/mfd/ab8500-spi.c
@@ -0,0 +1,133 @@
1/*
2 * Copyright (C) ST-Ericsson SA 2010
3 *
4 * License Terms: GNU General Public License v2
5 * Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
6 */
7
8#include <linux/kernel.h>
9#include <linux/slab.h>
10#include <linux/init.h>
11#include <linux/module.h>
12#include <linux/platform_device.h>
13#include <linux/spi/spi.h>
14#include <linux/mfd/ab8500.h>
15
16/*
17 * This funtion writes to any AB8500 registers using
18 * SPI protocol & before it writes it packs the data
19 * in the below 24 bit frame format
20 *
21 * *|------------------------------------|
22 * *| 23|22...18|17.......10|9|8|7......0|
23 * *| r/w bank adr data |
24 * * ------------------------------------
25 *
26 * This function shouldn't be called from interrupt
27 * context
28 */
29static int ab8500_spi_write(struct ab8500 *ab8500, u16 addr, u8 data)
30{
31 struct spi_device *spi = container_of(ab8500->dev, struct spi_device,
32 dev);
33 unsigned long spi_data = addr << 10 | data;
34 struct spi_transfer xfer;
35 struct spi_message msg;
36
37 ab8500->tx_buf[0] = spi_data;
38 ab8500->rx_buf[0] = 0;
39
40 xfer.tx_buf = ab8500->tx_buf;
41 xfer.rx_buf = NULL;
42 xfer.len = sizeof(unsigned long);
43
44 spi_message_init(&msg);
45 spi_message_add_tail(&xfer, &msg);
46
47 return spi_sync(spi, &msg);
48}
49
50static int ab8500_spi_read(struct ab8500 *ab8500, u16 addr)
51{
52 struct spi_device *spi = container_of(ab8500->dev, struct spi_device,
53 dev);
54 unsigned long spi_data = 1 << 23 | addr << 10;
55 struct spi_transfer xfer;
56 struct spi_message msg;
57 int ret;
58
59 ab8500->tx_buf[0] = spi_data;
60 ab8500->rx_buf[0] = 0;
61
62 xfer.tx_buf = ab8500->tx_buf;
63 xfer.rx_buf = ab8500->rx_buf;
64 xfer.len = sizeof(unsigned long);
65
66 spi_message_init(&msg);
67 spi_message_add_tail(&xfer, &msg);
68
69 ret = spi_sync(spi, &msg);
70 if (!ret)
71 ret = ab8500->rx_buf[0];
72
73 return ret;
74}
75
76static int __devinit ab8500_spi_probe(struct spi_device *spi)
77{
78 struct ab8500 *ab8500;
79 int ret;
80
81 ab8500 = kzalloc(sizeof *ab8500, GFP_KERNEL);
82 if (!ab8500)
83 return -ENOMEM;
84
85 ab8500->dev = &spi->dev;
86 ab8500->irq = spi->irq;
87
88 ab8500->read = ab8500_spi_read;
89 ab8500->write = ab8500_spi_write;
90
91 spi_set_drvdata(spi, ab8500);
92
93 ret = ab8500_init(ab8500);
94 if (ret)
95 kfree(ab8500);
96
97 return ret;
98}
99
100static int __devexit ab8500_spi_remove(struct spi_device *spi)
101{
102 struct ab8500 *ab8500 = spi_get_drvdata(spi);
103
104 ab8500_exit(ab8500);
105 kfree(ab8500);
106
107 return 0;
108}
109
110static struct spi_driver ab8500_spi_driver = {
111 .driver = {
112 .name = "ab8500",
113 .owner = THIS_MODULE,
114 },
115 .probe = ab8500_spi_probe,
116 .remove = __devexit_p(ab8500_spi_remove)
117};
118
119static int __init ab8500_spi_init(void)
120{
121 return spi_register_driver(&ab8500_spi_driver);
122}
123subsys_initcall(ab8500_spi_init);
124
125static void __exit ab8500_spi_exit(void)
126{
127 spi_unregister_driver(&ab8500_spi_driver);
128}
129module_exit(ab8500_spi_exit);
130
131MODULE_AUTHOR("Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com");
132MODULE_DESCRIPTION("AB8500 SPI");
133MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/abx500-core.c b/drivers/mfd/abx500-core.c
new file mode 100644
index 000000000000..3b3b97ec32a7
--- /dev/null
+++ b/drivers/mfd/abx500-core.c
@@ -0,0 +1,157 @@
1/*
2 * Copyright (C) 2007-2010 ST-Ericsson
3 * License terms: GNU General Public License (GPL) version 2
4 * Register access functions for the ABX500 Mixed Signal IC family.
5 * Author: Mattias Wallin <mattias.wallin@stericsson.com>
6 */
7
8#include <linux/list.h>
9#include <linux/slab.h>
10#include <linux/err.h>
11#include <linux/mfd/abx500.h>
12
13static LIST_HEAD(abx500_list);
14
15struct abx500_device_entry {
16 struct list_head list;
17 struct abx500_ops ops;
18 struct device *dev;
19};
20
21static void lookup_ops(struct device *dev, struct abx500_ops **ops)
22{
23 struct abx500_device_entry *dev_entry;
24
25 *ops = NULL;
26 list_for_each_entry(dev_entry, &abx500_list, list) {
27 if (dev_entry->dev == dev) {
28 *ops = &dev_entry->ops;
29 return;
30 }
31 }
32}
33
34int abx500_register_ops(struct device *dev, struct abx500_ops *ops)
35{
36 struct abx500_device_entry *dev_entry;
37
38 dev_entry = kzalloc(sizeof(struct abx500_device_entry), GFP_KERNEL);
39 if (IS_ERR(dev_entry)) {
40 dev_err(dev, "register_ops kzalloc failed");
41 return -ENOMEM;
42 }
43 dev_entry->dev = dev;
44 memcpy(&dev_entry->ops, ops, sizeof(struct abx500_ops));
45
46 list_add_tail(&dev_entry->list, &abx500_list);
47 return 0;
48}
49EXPORT_SYMBOL(abx500_register_ops);
50
51void abx500_remove_ops(struct device *dev)
52{
53 struct abx500_device_entry *dev_entry, *tmp;
54
55 list_for_each_entry_safe(dev_entry, tmp, &abx500_list, list)
56 {
57 if (dev_entry->dev == dev) {
58 list_del(&dev_entry->list);
59 kfree(dev_entry);
60 }
61 }
62}
63EXPORT_SYMBOL(abx500_remove_ops);
64
65int abx500_set_register_interruptible(struct device *dev, u8 bank, u8 reg,
66 u8 value)
67{
68 struct abx500_ops *ops;
69
70 lookup_ops(dev->parent, &ops);
71 if ((ops != NULL) && (ops->set_register != NULL))
72 return ops->set_register(dev, bank, reg, value);
73 else
74 return -ENOTSUPP;
75}
76EXPORT_SYMBOL(abx500_set_register_interruptible);
77
78int abx500_get_register_interruptible(struct device *dev, u8 bank, u8 reg,
79 u8 *value)
80{
81 struct abx500_ops *ops;
82
83 lookup_ops(dev->parent, &ops);
84 if ((ops != NULL) && (ops->get_register != NULL))
85 return ops->get_register(dev, bank, reg, value);
86 else
87 return -ENOTSUPP;
88}
89EXPORT_SYMBOL(abx500_get_register_interruptible);
90
91int abx500_get_register_page_interruptible(struct device *dev, u8 bank,
92 u8 first_reg, u8 *regvals, u8 numregs)
93{
94 struct abx500_ops *ops;
95
96 lookup_ops(dev->parent, &ops);
97 if ((ops != NULL) && (ops->get_register_page != NULL))
98 return ops->get_register_page(dev, bank,
99 first_reg, regvals, numregs);
100 else
101 return -ENOTSUPP;
102}
103EXPORT_SYMBOL(abx500_get_register_page_interruptible);
104
105int abx500_mask_and_set_register_interruptible(struct device *dev, u8 bank,
106 u8 reg, u8 bitmask, u8 bitvalues)
107{
108 struct abx500_ops *ops;
109
110 lookup_ops(dev->parent, &ops);
111 if ((ops != NULL) && (ops->mask_and_set_register != NULL))
112 return ops->mask_and_set_register(dev, bank,
113 reg, bitmask, bitvalues);
114 else
115 return -ENOTSUPP;
116}
117EXPORT_SYMBOL(abx500_mask_and_set_register_interruptible);
118
119int abx500_get_chip_id(struct device *dev)
120{
121 struct abx500_ops *ops;
122
123 lookup_ops(dev->parent, &ops);
124 if ((ops != NULL) && (ops->get_chip_id != NULL))
125 return ops->get_chip_id(dev);
126 else
127 return -ENOTSUPP;
128}
129EXPORT_SYMBOL(abx500_get_chip_id);
130
131int abx500_event_registers_startup_state_get(struct device *dev, u8 *event)
132{
133 struct abx500_ops *ops;
134
135 lookup_ops(dev->parent, &ops);
136 if ((ops != NULL) && (ops->event_registers_startup_state_get != NULL))
137 return ops->event_registers_startup_state_get(dev, event);
138 else
139 return -ENOTSUPP;
140}
141EXPORT_SYMBOL(abx500_event_registers_startup_state_get);
142
143int abx500_startup_irq_enabled(struct device *dev, unsigned int irq)
144{
145 struct abx500_ops *ops;
146
147 lookup_ops(dev->parent, &ops);
148 if ((ops != NULL) && (ops->startup_irq_enabled != NULL))
149 return ops->startup_irq_enabled(dev, irq);
150 else
151 return -ENOTSUPP;
152}
153EXPORT_SYMBOL(abx500_startup_irq_enabled);
154
155MODULE_AUTHOR("Mattias Wallin <mattias.wallin@stericsson.com>");
156MODULE_DESCRIPTION("ABX500 core driver");
157MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/adp5520.c b/drivers/mfd/adp5520.c
index 005532865654..3122139b4300 100644
--- a/drivers/mfd/adp5520.c
+++ b/drivers/mfd/adp5520.c
@@ -302,7 +302,6 @@ out_free_irq:
302 free_irq(chip->irq, chip); 302 free_irq(chip->irq, chip);
303 303
304out_free_chip: 304out_free_chip:
305 i2c_set_clientdata(client, NULL);
306 kfree(chip); 305 kfree(chip);
307 306
308 return ret; 307 return ret;
@@ -317,7 +316,6 @@ static int __devexit adp5520_remove(struct i2c_client *client)
317 316
318 adp5520_remove_subdevs(chip); 317 adp5520_remove_subdevs(chip);
319 adp5520_write(chip->dev, ADP5520_MODE_STATUS, 0); 318 adp5520_write(chip->dev, ADP5520_MODE_STATUS, 0);
320 i2c_set_clientdata(client, NULL);
321 kfree(chip); 319 kfree(chip);
322 return 0; 320 return 0;
323} 321}
diff --git a/drivers/mfd/da903x.c b/drivers/mfd/da903x.c
index 67181b147ab3..c07aece900fb 100644
--- a/drivers/mfd/da903x.c
+++ b/drivers/mfd/da903x.c
@@ -534,7 +534,6 @@ static int __devinit da903x_probe(struct i2c_client *client,
534out_free_irq: 534out_free_irq:
535 free_irq(client->irq, chip); 535 free_irq(client->irq, chip);
536out_free_chip: 536out_free_chip:
537 i2c_set_clientdata(client, NULL);
538 kfree(chip); 537 kfree(chip);
539 return ret; 538 return ret;
540} 539}
diff --git a/drivers/mfd/janz-cmodio.c b/drivers/mfd/janz-cmodio.c
new file mode 100644
index 000000000000..9ed630799acc
--- /dev/null
+++ b/drivers/mfd/janz-cmodio.c
@@ -0,0 +1,304 @@
1/*
2 * Janz CMOD-IO MODULbus Carrier Board PCI Driver
3 *
4 * Copyright (c) 2010 Ira W. Snyder <iws@ovro.caltech.edu>
5 *
6 * Lots of inspiration and code was copied from drivers/mfd/sm501.c
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 */
13
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/init.h>
17#include <linux/pci.h>
18#include <linux/interrupt.h>
19#include <linux/delay.h>
20#include <linux/platform_device.h>
21#include <linux/mfd/core.h>
22
23#include <linux/mfd/janz.h>
24
25#define DRV_NAME "janz-cmodio"
26
27/* Size of each MODULbus module in PCI BAR4 */
28#define CMODIO_MODULBUS_SIZE 0x200
29
30/* Maximum number of MODULbus modules on a CMOD-IO carrier board */
31#define CMODIO_MAX_MODULES 4
32
33/* Module Parameters */
34static unsigned int num_modules = CMODIO_MAX_MODULES;
35static unsigned char *modules[CMODIO_MAX_MODULES] = {
36 "empty", "empty", "empty", "empty",
37};
38
39module_param_array(modules, charp, &num_modules, S_IRUGO);
40MODULE_PARM_DESC(modules, "MODULbus modules attached to the carrier board");
41
42/* Unique Device Id */
43static unsigned int cmodio_id;
44
45struct cmodio_device {
46 /* Parent PCI device */
47 struct pci_dev *pdev;
48
49 /* PLX control registers */
50 struct janz_cmodio_onboard_regs __iomem *ctrl;
51
52 /* hex switch position */
53 u8 hex;
54
55 /* mfd-core API */
56 struct mfd_cell cells[CMODIO_MAX_MODULES];
57 struct resource resources[3 * CMODIO_MAX_MODULES];
58 struct janz_platform_data pdata[CMODIO_MAX_MODULES];
59};
60
61/*
62 * Subdevices using the mfd-core API
63 */
64
65static int __devinit cmodio_setup_subdevice(struct cmodio_device *priv,
66 char *name, unsigned int devno,
67 unsigned int modno)
68{
69 struct janz_platform_data *pdata;
70 struct mfd_cell *cell;
71 struct resource *res;
72 struct pci_dev *pci;
73
74 pci = priv->pdev;
75 cell = &priv->cells[devno];
76 res = &priv->resources[devno * 3];
77 pdata = &priv->pdata[devno];
78
79 cell->name = name;
80 cell->resources = res;
81 cell->num_resources = 3;
82
83 /* Setup the subdevice ID -- must be unique */
84 cell->id = cmodio_id++;
85
86 /* Add platform data */
87 pdata->modno = modno;
88 cell->platform_data = pdata;
89 cell->data_size = sizeof(*pdata);
90
91 /* MODULbus registers -- PCI BAR3 is big-endian MODULbus access */
92 res->flags = IORESOURCE_MEM;
93 res->parent = &pci->resource[3];
94 res->start = pci->resource[3].start + (CMODIO_MODULBUS_SIZE * modno);
95 res->end = res->start + CMODIO_MODULBUS_SIZE - 1;
96 res++;
97
98 /* PLX Control Registers -- PCI BAR4 is interrupt and other registers */
99 res->flags = IORESOURCE_MEM;
100 res->parent = &pci->resource[4];
101 res->start = pci->resource[4].start;
102 res->end = pci->resource[4].end;
103 res++;
104
105 /*
106 * IRQ
107 *
108 * The start and end fields are used as an offset to the irq_base
109 * parameter passed into the mfd_add_devices() function call. All
110 * devices share the same IRQ.
111 */
112 res->flags = IORESOURCE_IRQ;
113 res->parent = NULL;
114 res->start = 0;
115 res->end = 0;
116 res++;
117
118 return 0;
119}
120
121/* Probe each submodule using kernel parameters */
122static int __devinit cmodio_probe_submodules(struct cmodio_device *priv)
123{
124 struct pci_dev *pdev = priv->pdev;
125 unsigned int num_probed = 0;
126 char *name;
127 int i;
128
129 for (i = 0; i < num_modules; i++) {
130 name = modules[i];
131 if (!strcmp(name, "") || !strcmp(name, "empty"))
132 continue;
133
134 dev_dbg(&priv->pdev->dev, "MODULbus %d: name %s\n", i, name);
135 cmodio_setup_subdevice(priv, name, num_probed, i);
136 num_probed++;
137 }
138
139 /* print an error message if no modules were probed */
140 if (num_probed == 0) {
141 dev_err(&priv->pdev->dev, "no MODULbus modules specified, "
142 "please set the ``modules'' kernel "
143 "parameter according to your "
144 "hardware configuration\n");
145 return -ENODEV;
146 }
147
148 return mfd_add_devices(&pdev->dev, 0, priv->cells,
149 num_probed, NULL, pdev->irq);
150}
151
152/*
153 * SYSFS Attributes
154 */
155
156static ssize_t mbus_show(struct device *dev, struct device_attribute *attr,
157 char *buf)
158{
159 struct cmodio_device *priv = dev_get_drvdata(dev);
160
161 return snprintf(buf, PAGE_SIZE, "%x\n", priv->hex);
162}
163
164static DEVICE_ATTR(modulbus_number, S_IRUGO, mbus_show, NULL);
165
166static struct attribute *cmodio_sysfs_attrs[] = {
167 &dev_attr_modulbus_number.attr,
168 NULL,
169};
170
171static const struct attribute_group cmodio_sysfs_attr_group = {
172 .attrs = cmodio_sysfs_attrs,
173};
174
175/*
176 * PCI Driver
177 */
178
179static int __devinit cmodio_pci_probe(struct pci_dev *dev,
180 const struct pci_device_id *id)
181{
182 struct cmodio_device *priv;
183 int ret;
184
185 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
186 if (!priv) {
187 dev_err(&dev->dev, "unable to allocate private data\n");
188 ret = -ENOMEM;
189 goto out_return;
190 }
191
192 pci_set_drvdata(dev, priv);
193 priv->pdev = dev;
194
195 /* Hardware Initialization */
196 ret = pci_enable_device(dev);
197 if (ret) {
198 dev_err(&dev->dev, "unable to enable device\n");
199 goto out_free_priv;
200 }
201
202 pci_set_master(dev);
203 ret = pci_request_regions(dev, DRV_NAME);
204 if (ret) {
205 dev_err(&dev->dev, "unable to request regions\n");
206 goto out_pci_disable_device;
207 }
208
209 /* Onboard configuration registers */
210 priv->ctrl = pci_ioremap_bar(dev, 4);
211 if (!priv->ctrl) {
212 dev_err(&dev->dev, "unable to remap onboard regs\n");
213 ret = -ENOMEM;
214 goto out_pci_release_regions;
215 }
216
217 /* Read the hex switch on the carrier board */
218 priv->hex = ioread8(&priv->ctrl->int_enable);
219
220 /* Add the MODULbus number (hex switch value) to the device's sysfs */
221 ret = sysfs_create_group(&dev->dev.kobj, &cmodio_sysfs_attr_group);
222 if (ret) {
223 dev_err(&dev->dev, "unable to create sysfs attributes\n");
224 goto out_unmap_ctrl;
225 }
226
227 /*
228 * Disable all interrupt lines, each submodule will enable its
229 * own interrupt line if needed
230 */
231 iowrite8(0xf, &priv->ctrl->int_disable);
232
233 /* Register drivers for all submodules */
234 ret = cmodio_probe_submodules(priv);
235 if (ret) {
236 dev_err(&dev->dev, "unable to probe submodules\n");
237 goto out_sysfs_remove_group;
238 }
239
240 return 0;
241
242out_sysfs_remove_group:
243 sysfs_remove_group(&dev->dev.kobj, &cmodio_sysfs_attr_group);
244out_unmap_ctrl:
245 iounmap(priv->ctrl);
246out_pci_release_regions:
247 pci_release_regions(dev);
248out_pci_disable_device:
249 pci_disable_device(dev);
250out_free_priv:
251 kfree(priv);
252out_return:
253 return ret;
254}
255
256static void __devexit cmodio_pci_remove(struct pci_dev *dev)
257{
258 struct cmodio_device *priv = pci_get_drvdata(dev);
259
260 mfd_remove_devices(&dev->dev);
261 sysfs_remove_group(&dev->dev.kobj, &cmodio_sysfs_attr_group);
262 iounmap(priv->ctrl);
263 pci_release_regions(dev);
264 pci_disable_device(dev);
265 kfree(priv);
266}
267
268#define PCI_VENDOR_ID_JANZ 0x13c3
269
270/* The list of devices that this module will support */
271static DEFINE_PCI_DEVICE_TABLE(cmodio_pci_ids) = {
272 { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030, PCI_VENDOR_ID_JANZ, 0x0101 },
273 { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_JANZ, 0x0100 },
274 { 0, }
275};
276MODULE_DEVICE_TABLE(pci, cmodio_pci_ids);
277
278static struct pci_driver cmodio_pci_driver = {
279 .name = DRV_NAME,
280 .id_table = cmodio_pci_ids,
281 .probe = cmodio_pci_probe,
282 .remove = __devexit_p(cmodio_pci_remove),
283};
284
285/*
286 * Module Init / Exit
287 */
288
289static int __init cmodio_init(void)
290{
291 return pci_register_driver(&cmodio_pci_driver);
292}
293
294static void __exit cmodio_exit(void)
295{
296 pci_unregister_driver(&cmodio_pci_driver);
297}
298
299MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>");
300MODULE_DESCRIPTION("Janz CMOD-IO PCI MODULbus Carrier Board Driver");
301MODULE_LICENSE("GPL");
302
303module_init(cmodio_init);
304module_exit(cmodio_exit);
diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c
index 85d63c04749b..f621bcea3d02 100644
--- a/drivers/mfd/max8925-core.c
+++ b/drivers/mfd/max8925-core.c
@@ -508,7 +508,7 @@ static int max8925_irq_init(struct max8925_chip *chip, int irq,
508 max8925_reg_read(chip->i2c, MAX8925_ON_OFF_IRQ2); 508 max8925_reg_read(chip->i2c, MAX8925_ON_OFF_IRQ2);
509 max8925_reg_read(chip->rtc, MAX8925_RTC_IRQ); 509 max8925_reg_read(chip->rtc, MAX8925_RTC_IRQ);
510 max8925_reg_read(chip->adc, MAX8925_TSC_IRQ); 510 max8925_reg_read(chip->adc, MAX8925_TSC_IRQ);
511 /* mask all interrupts */ 511 /* mask all interrupts except for TSC */
512 max8925_reg_write(chip->rtc, MAX8925_ALARM0_CNTL, 0); 512 max8925_reg_write(chip->rtc, MAX8925_ALARM0_CNTL, 0);
513 max8925_reg_write(chip->rtc, MAX8925_ALARM1_CNTL, 0); 513 max8925_reg_write(chip->rtc, MAX8925_ALARM1_CNTL, 0);
514 max8925_reg_write(chip->i2c, MAX8925_CHG_IRQ1_MASK, 0xff); 514 max8925_reg_write(chip->i2c, MAX8925_CHG_IRQ1_MASK, 0xff);
@@ -516,7 +516,6 @@ static int max8925_irq_init(struct max8925_chip *chip, int irq,
516 max8925_reg_write(chip->i2c, MAX8925_ON_OFF_IRQ1_MASK, 0xff); 516 max8925_reg_write(chip->i2c, MAX8925_ON_OFF_IRQ1_MASK, 0xff);
517 max8925_reg_write(chip->i2c, MAX8925_ON_OFF_IRQ2_MASK, 0xff); 517 max8925_reg_write(chip->i2c, MAX8925_ON_OFF_IRQ2_MASK, 0xff);
518 max8925_reg_write(chip->rtc, MAX8925_RTC_IRQ_MASK, 0xff); 518 max8925_reg_write(chip->rtc, MAX8925_RTC_IRQ_MASK, 0xff);
519 max8925_reg_write(chip->adc, MAX8925_TSC_IRQ_MASK, 0xff);
520 519
521 mutex_init(&chip->irq_lock); 520 mutex_init(&chip->irq_lock);
522 chip->core_irq = irq; 521 chip->core_irq = irq;
@@ -547,7 +546,11 @@ static int max8925_irq_init(struct max8925_chip *chip, int irq,
547 dev_err(chip->dev, "Failed to request core IRQ: %d\n", ret); 546 dev_err(chip->dev, "Failed to request core IRQ: %d\n", ret);
548 chip->core_irq = 0; 547 chip->core_irq = 0;
549 } 548 }
549
550tsc_irq: 550tsc_irq:
551 /* mask TSC interrupt */
552 max8925_reg_write(chip->adc, MAX8925_TSC_IRQ_MASK, 0x0f);
553
551 if (!pdata->tsc_irq) { 554 if (!pdata->tsc_irq) {
552 dev_warn(chip->dev, "No interrupt support on TSC IRQ\n"); 555 dev_warn(chip->dev, "No interrupt support on TSC IRQ\n");
553 return 0; 556 return 0;
diff --git a/drivers/mfd/max8925-i2c.c b/drivers/mfd/max8925-i2c.c
index d9fd8785da4d..0219115e00c7 100644
--- a/drivers/mfd/max8925-i2c.c
+++ b/drivers/mfd/max8925-i2c.c
@@ -173,9 +173,6 @@ static int __devexit max8925_remove(struct i2c_client *client)
173 max8925_device_exit(chip); 173 max8925_device_exit(chip);
174 i2c_unregister_device(chip->adc); 174 i2c_unregister_device(chip->adc);
175 i2c_unregister_device(chip->rtc); 175 i2c_unregister_device(chip->rtc);
176 i2c_set_clientdata(chip->adc, NULL);
177 i2c_set_clientdata(chip->rtc, NULL);
178 i2c_set_clientdata(chip->i2c, NULL);
179 kfree(chip); 176 kfree(chip);
180 return 0; 177 return 0;
181} 178}
diff --git a/drivers/mfd/mc13783-core.c b/drivers/mfd/mc13783-core.c
index 1f68ecadddc2..fecf38a4f025 100644
--- a/drivers/mfd/mc13783-core.c
+++ b/drivers/mfd/mc13783-core.c
@@ -679,6 +679,10 @@ err_revision:
679 if (pdata->flags & MC13783_USE_TOUCHSCREEN) 679 if (pdata->flags & MC13783_USE_TOUCHSCREEN)
680 mc13783_add_subdevice(mc13783, "mc13783-ts"); 680 mc13783_add_subdevice(mc13783, "mc13783-ts");
681 681
682 if (pdata->flags & MC13783_USE_LED)
683 mc13783_add_subdevice_pdata(mc13783, "mc13783-led",
684 pdata->leds, sizeof(*pdata->leds));
685
682 return 0; 686 return 0;
683} 687}
684 688
diff --git a/drivers/mfd/menelaus.c b/drivers/mfd/menelaus.c
index a94b131a18ef..a3fb4bcb9889 100644
--- a/drivers/mfd/menelaus.c
+++ b/drivers/mfd/menelaus.c
@@ -1238,7 +1238,6 @@ static int __exit menelaus_remove(struct i2c_client *client)
1238 1238
1239 free_irq(client->irq, menelaus); 1239 free_irq(client->irq, menelaus);
1240 kfree(menelaus); 1240 kfree(menelaus);
1241 i2c_set_clientdata(client, NULL);
1242 the_menelaus = NULL; 1241 the_menelaus = NULL;
1243 return 0; 1242 return 0;
1244} 1243}
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index 8ffbb7a85a7e..7dd76bceaae8 100644
--- a/drivers/mfd/mfd-core.c
+++ b/drivers/mfd/mfd-core.c
@@ -48,7 +48,7 @@ static int mfd_add_device(struct device *parent, int id,
48 res[r].flags = cell->resources[r].flags; 48 res[r].flags = cell->resources[r].flags;
49 49
50 /* Find out base to use */ 50 /* Find out base to use */
51 if (cell->resources[r].flags & IORESOURCE_MEM) { 51 if ((cell->resources[r].flags & IORESOURCE_MEM) && mem_base) {
52 res[r].parent = mem_base; 52 res[r].parent = mem_base;
53 res[r].start = mem_base->start + 53 res[r].start = mem_base->start +
54 cell->resources[r].start; 54 cell->resources[r].start;
diff --git a/drivers/mfd/pcf50633-adc.c b/drivers/mfd/pcf50633-adc.c
index fe8f922f6654..aed0d2a9b032 100644
--- a/drivers/mfd/pcf50633-adc.c
+++ b/drivers/mfd/pcf50633-adc.c
@@ -30,13 +30,13 @@
30struct pcf50633_adc_request { 30struct pcf50633_adc_request {
31 int mux; 31 int mux;
32 int avg; 32 int avg;
33 int result;
34 void (*callback)(struct pcf50633 *, void *, int); 33 void (*callback)(struct pcf50633 *, void *, int);
35 void *callback_param; 34 void *callback_param;
35};
36 36
37 /* Used in case of sync requests */ 37struct pcf50633_adc_sync_request {
38 int result;
38 struct completion completion; 39 struct completion completion;
39
40}; 40};
41 41
42#define PCF50633_MAX_ADC_FIFO_DEPTH 8 42#define PCF50633_MAX_ADC_FIFO_DEPTH 8
@@ -109,10 +109,10 @@ adc_enqueue_request(struct pcf50633 *pcf, struct pcf50633_adc_request *req)
109 return 0; 109 return 0;
110} 110}
111 111
112static void 112static void pcf50633_adc_sync_read_callback(struct pcf50633 *pcf, void *param,
113pcf50633_adc_sync_read_callback(struct pcf50633 *pcf, void *param, int result) 113 int result)
114{ 114{
115 struct pcf50633_adc_request *req = param; 115 struct pcf50633_adc_sync_request *req = param;
116 116
117 req->result = result; 117 req->result = result;
118 complete(&req->completion); 118 complete(&req->completion);
@@ -120,28 +120,19 @@ pcf50633_adc_sync_read_callback(struct pcf50633 *pcf, void *param, int result)
120 120
121int pcf50633_adc_sync_read(struct pcf50633 *pcf, int mux, int avg) 121int pcf50633_adc_sync_read(struct pcf50633 *pcf, int mux, int avg)
122{ 122{
123 struct pcf50633_adc_request *req; 123 struct pcf50633_adc_sync_request req;
124 int err; 124 int ret;
125 125
126 /* req is freed when the result is ready, in interrupt handler */ 126 init_completion(&req.completion);
127 req = kzalloc(sizeof(*req), GFP_KERNEL);
128 if (!req)
129 return -ENOMEM;
130
131 req->mux = mux;
132 req->avg = avg;
133 req->callback = pcf50633_adc_sync_read_callback;
134 req->callback_param = req;
135 127
136 init_completion(&req->completion); 128 ret = pcf50633_adc_async_read(pcf, mux, avg,
137 err = adc_enqueue_request(pcf, req); 129 pcf50633_adc_sync_read_callback, &req);
138 if (err) 130 if (ret)
139 return err; 131 return ret;
140 132
141 wait_for_completion(&req->completion); 133 wait_for_completion(&req.completion);
142 134
143 /* FIXME by this time req might be already freed */ 135 return req.result;
144 return req->result;
145} 136}
146EXPORT_SYMBOL_GPL(pcf50633_adc_sync_read); 137EXPORT_SYMBOL_GPL(pcf50633_adc_sync_read);
147 138
diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c
index 63a614d696c1..23e585527285 100644
--- a/drivers/mfd/pcf50633-core.c
+++ b/drivers/mfd/pcf50633-core.c
@@ -21,16 +21,16 @@
21#include <linux/workqueue.h> 21#include <linux/workqueue.h>
22#include <linux/platform_device.h> 22#include <linux/platform_device.h>
23#include <linux/i2c.h> 23#include <linux/i2c.h>
24#include <linux/irq.h>
25#include <linux/slab.h> 24#include <linux/slab.h>
26 25
27#include <linux/mfd/pcf50633/core.h> 26#include <linux/mfd/pcf50633/core.h>
28 27
29/* Two MBCS registers used during cold start */ 28int pcf50633_irq_init(struct pcf50633 *pcf, int irq);
30#define PCF50633_REG_MBCS1 0x4b 29void pcf50633_irq_free(struct pcf50633 *pcf);
31#define PCF50633_REG_MBCS2 0x4c 30#ifdef CONFIG_PM
32#define PCF50633_MBCS1_USBPRES 0x01 31int pcf50633_irq_suspend(struct pcf50633 *pcf);
33#define PCF50633_MBCS1_ADAPTPRES 0x01 32int pcf50633_irq_resume(struct pcf50633 *pcf);
33#endif
34 34
35static int __pcf50633_read(struct pcf50633 *pcf, u8 reg, int num, u8 *data) 35static int __pcf50633_read(struct pcf50633 *pcf, u8 reg, int num, u8 *data)
36{ 36{
@@ -215,244 +215,6 @@ static struct attribute_group pcf_attr_group = {
215 .attrs = pcf_sysfs_entries, 215 .attrs = pcf_sysfs_entries,
216}; 216};
217 217
218int pcf50633_register_irq(struct pcf50633 *pcf, int irq,
219 void (*handler) (int, void *), void *data)
220{
221 if (irq < 0 || irq > PCF50633_NUM_IRQ || !handler)
222 return -EINVAL;
223
224 if (WARN_ON(pcf->irq_handler[irq].handler))
225 return -EBUSY;
226
227 mutex_lock(&pcf->lock);
228 pcf->irq_handler[irq].handler = handler;
229 pcf->irq_handler[irq].data = data;
230 mutex_unlock(&pcf->lock);
231
232 return 0;
233}
234EXPORT_SYMBOL_GPL(pcf50633_register_irq);
235
236int pcf50633_free_irq(struct pcf50633 *pcf, int irq)
237{
238 if (irq < 0 || irq > PCF50633_NUM_IRQ)
239 return -EINVAL;
240
241 mutex_lock(&pcf->lock);
242 pcf->irq_handler[irq].handler = NULL;
243 mutex_unlock(&pcf->lock);
244
245 return 0;
246}
247EXPORT_SYMBOL_GPL(pcf50633_free_irq);
248
249static int __pcf50633_irq_mask_set(struct pcf50633 *pcf, int irq, u8 mask)
250{
251 u8 reg, bits, tmp;
252 int ret = 0, idx;
253
254 idx = irq >> 3;
255 reg = PCF50633_REG_INT1M + idx;
256 bits = 1 << (irq & 0x07);
257
258 mutex_lock(&pcf->lock);
259
260 if (mask) {
261 ret = __pcf50633_read(pcf, reg, 1, &tmp);
262 if (ret < 0)
263 goto out;
264
265 tmp |= bits;
266
267 ret = __pcf50633_write(pcf, reg, 1, &tmp);
268 if (ret < 0)
269 goto out;
270
271 pcf->mask_regs[idx] &= ~bits;
272 pcf->mask_regs[idx] |= bits;
273 } else {
274 ret = __pcf50633_read(pcf, reg, 1, &tmp);
275 if (ret < 0)
276 goto out;
277
278 tmp &= ~bits;
279
280 ret = __pcf50633_write(pcf, reg, 1, &tmp);
281 if (ret < 0)
282 goto out;
283
284 pcf->mask_regs[idx] &= ~bits;
285 }
286out:
287 mutex_unlock(&pcf->lock);
288
289 return ret;
290}
291
292int pcf50633_irq_mask(struct pcf50633 *pcf, int irq)
293{
294 dev_dbg(pcf->dev, "Masking IRQ %d\n", irq);
295
296 return __pcf50633_irq_mask_set(pcf, irq, 1);
297}
298EXPORT_SYMBOL_GPL(pcf50633_irq_mask);
299
300int pcf50633_irq_unmask(struct pcf50633 *pcf, int irq)
301{
302 dev_dbg(pcf->dev, "Unmasking IRQ %d\n", irq);
303
304 return __pcf50633_irq_mask_set(pcf, irq, 0);
305}
306EXPORT_SYMBOL_GPL(pcf50633_irq_unmask);
307
308int pcf50633_irq_mask_get(struct pcf50633 *pcf, int irq)
309{
310 u8 reg, bits;
311
312 reg = irq >> 3;
313 bits = 1 << (irq & 0x07);
314
315 return pcf->mask_regs[reg] & bits;
316}
317EXPORT_SYMBOL_GPL(pcf50633_irq_mask_get);
318
319static void pcf50633_irq_call_handler(struct pcf50633 *pcf, int irq)
320{
321 if (pcf->irq_handler[irq].handler)
322 pcf->irq_handler[irq].handler(irq, pcf->irq_handler[irq].data);
323}
324
325/* Maximum amount of time ONKEY is held before emergency action is taken */
326#define PCF50633_ONKEY1S_TIMEOUT 8
327
328static void pcf50633_irq_worker(struct work_struct *work)
329{
330 struct pcf50633 *pcf;
331 int ret, i, j;
332 u8 pcf_int[5], chgstat;
333
334 pcf = container_of(work, struct pcf50633, irq_work);
335
336 /* Read the 5 INT regs in one transaction */
337 ret = pcf50633_read_block(pcf, PCF50633_REG_INT1,
338 ARRAY_SIZE(pcf_int), pcf_int);
339 if (ret != ARRAY_SIZE(pcf_int)) {
340 dev_err(pcf->dev, "Error reading INT registers\n");
341
342 /*
343 * If this doesn't ACK the interrupt to the chip, we'll be
344 * called once again as we're level triggered.
345 */
346 goto out;
347 }
348
349 /* defeat 8s death from lowsys on A5 */
350 pcf50633_reg_write(pcf, PCF50633_REG_OOCSHDWN, 0x04);
351
352 /* We immediately read the usb and adapter status. We thus make sure
353 * only of USBINS/USBREM IRQ handlers are called */
354 if (pcf_int[0] & (PCF50633_INT1_USBINS | PCF50633_INT1_USBREM)) {
355 chgstat = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2);
356 if (chgstat & (0x3 << 4))
357 pcf_int[0] &= ~(1 << PCF50633_INT1_USBREM);
358 else
359 pcf_int[0] &= ~(1 << PCF50633_INT1_USBINS);
360 }
361
362 /* Make sure only one of ADPINS or ADPREM is set */
363 if (pcf_int[0] & (PCF50633_INT1_ADPINS | PCF50633_INT1_ADPREM)) {
364 chgstat = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2);
365 if (chgstat & (0x3 << 4))
366 pcf_int[0] &= ~(1 << PCF50633_INT1_ADPREM);
367 else
368 pcf_int[0] &= ~(1 << PCF50633_INT1_ADPINS);
369 }
370
371 dev_dbg(pcf->dev, "INT1=0x%02x INT2=0x%02x INT3=0x%02x "
372 "INT4=0x%02x INT5=0x%02x\n", pcf_int[0],
373 pcf_int[1], pcf_int[2], pcf_int[3], pcf_int[4]);
374
375 /* Some revisions of the chip don't have a 8s standby mode on
376 * ONKEY1S press. We try to manually do it in such cases. */
377 if ((pcf_int[0] & PCF50633_INT1_SECOND) && pcf->onkey1s_held) {
378 dev_info(pcf->dev, "ONKEY1S held for %d secs\n",
379 pcf->onkey1s_held);
380 if (pcf->onkey1s_held++ == PCF50633_ONKEY1S_TIMEOUT)
381 if (pcf->pdata->force_shutdown)
382 pcf->pdata->force_shutdown(pcf);
383 }
384
385 if (pcf_int[2] & PCF50633_INT3_ONKEY1S) {
386 dev_info(pcf->dev, "ONKEY1S held\n");
387 pcf->onkey1s_held = 1 ;
388
389 /* Unmask IRQ_SECOND */
390 pcf50633_reg_clear_bits(pcf, PCF50633_REG_INT1M,
391 PCF50633_INT1_SECOND);
392
393 /* Unmask IRQ_ONKEYR */
394 pcf50633_reg_clear_bits(pcf, PCF50633_REG_INT2M,
395 PCF50633_INT2_ONKEYR);
396 }
397
398 if ((pcf_int[1] & PCF50633_INT2_ONKEYR) && pcf->onkey1s_held) {
399 pcf->onkey1s_held = 0;
400
401 /* Mask SECOND and ONKEYR interrupts */
402 if (pcf->mask_regs[0] & PCF50633_INT1_SECOND)
403 pcf50633_reg_set_bit_mask(pcf,
404 PCF50633_REG_INT1M,
405 PCF50633_INT1_SECOND,
406 PCF50633_INT1_SECOND);
407
408 if (pcf->mask_regs[1] & PCF50633_INT2_ONKEYR)
409 pcf50633_reg_set_bit_mask(pcf,
410 PCF50633_REG_INT2M,
411 PCF50633_INT2_ONKEYR,
412 PCF50633_INT2_ONKEYR);
413 }
414
415 /* Have we just resumed ? */
416 if (pcf->is_suspended) {
417 pcf->is_suspended = 0;
418
419 /* Set the resume reason filtering out non resumers */
420 for (i = 0; i < ARRAY_SIZE(pcf_int); i++)
421 pcf->resume_reason[i] = pcf_int[i] &
422 pcf->pdata->resumers[i];
423
424 /* Make sure we don't pass on any ONKEY events to
425 * userspace now */
426 pcf_int[1] &= ~(PCF50633_INT2_ONKEYR | PCF50633_INT2_ONKEYF);
427 }
428
429 for (i = 0; i < ARRAY_SIZE(pcf_int); i++) {
430 /* Unset masked interrupts */
431 pcf_int[i] &= ~pcf->mask_regs[i];
432
433 for (j = 0; j < 8 ; j++)
434 if (pcf_int[i] & (1 << j))
435 pcf50633_irq_call_handler(pcf, (i * 8) + j);
436 }
437
438out:
439 put_device(pcf->dev);
440 enable_irq(pcf->irq);
441}
442
443static irqreturn_t pcf50633_irq(int irq, void *data)
444{
445 struct pcf50633 *pcf = data;
446
447 dev_dbg(pcf->dev, "pcf50633_irq\n");
448
449 get_device(pcf->dev);
450 disable_irq_nosync(pcf->irq);
451 queue_work(pcf->work_queue, &pcf->irq_work);
452
453 return IRQ_HANDLED;
454}
455
456static void 218static void
457pcf50633_client_dev_register(struct pcf50633 *pcf, const char *name, 219pcf50633_client_dev_register(struct pcf50633 *pcf, const char *name,
458 struct platform_device **pdev) 220 struct platform_device **pdev)
@@ -479,70 +241,17 @@ pcf50633_client_dev_register(struct pcf50633 *pcf, const char *name,
479static int pcf50633_suspend(struct i2c_client *client, pm_message_t state) 241static int pcf50633_suspend(struct i2c_client *client, pm_message_t state)
480{ 242{
481 struct pcf50633 *pcf; 243 struct pcf50633 *pcf;
482 int ret = 0, i;
483 u8 res[5];
484
485 pcf = i2c_get_clientdata(client); 244 pcf = i2c_get_clientdata(client);
486 245
487 /* Make sure our interrupt handlers are not called 246 return pcf50633_irq_suspend(pcf);
488 * henceforth */
489 disable_irq(pcf->irq);
490
491 /* Make sure that any running IRQ worker has quit */
492 cancel_work_sync(&pcf->irq_work);
493
494 /* Save the masks */
495 ret = pcf50633_read_block(pcf, PCF50633_REG_INT1M,
496 ARRAY_SIZE(pcf->suspend_irq_masks),
497 pcf->suspend_irq_masks);
498 if (ret < 0) {
499 dev_err(pcf->dev, "error saving irq masks\n");
500 goto out;
501 }
502
503 /* Write wakeup irq masks */
504 for (i = 0; i < ARRAY_SIZE(res); i++)
505 res[i] = ~pcf->pdata->resumers[i];
506
507 ret = pcf50633_write_block(pcf, PCF50633_REG_INT1M,
508 ARRAY_SIZE(res), &res[0]);
509 if (ret < 0) {
510 dev_err(pcf->dev, "error writing wakeup irq masks\n");
511 goto out;
512 }
513
514 pcf->is_suspended = 1;
515
516out:
517 return ret;
518} 247}
519 248
520static int pcf50633_resume(struct i2c_client *client) 249static int pcf50633_resume(struct i2c_client *client)
521{ 250{
522 struct pcf50633 *pcf; 251 struct pcf50633 *pcf;
523 int ret;
524
525 pcf = i2c_get_clientdata(client); 252 pcf = i2c_get_clientdata(client);
526 253
527 /* Write the saved mask registers */ 254 return pcf50633_irq_resume(pcf);
528 ret = pcf50633_write_block(pcf, PCF50633_REG_INT1M,
529 ARRAY_SIZE(pcf->suspend_irq_masks),
530 pcf->suspend_irq_masks);
531 if (ret < 0)
532 dev_err(pcf->dev, "Error restoring saved suspend masks\n");
533
534 /* Restore regulators' state */
535
536
537 get_device(pcf->dev);
538
539 /*
540 * Clear any pending interrupts and set resume reason if any.
541 * This will leave with enable_irq()
542 */
543 pcf50633_irq_worker(&pcf->irq_work);
544
545 return 0;
546} 255}
547#else 256#else
548#define pcf50633_suspend NULL 257#define pcf50633_suspend NULL
@@ -573,43 +282,19 @@ static int __devinit pcf50633_probe(struct i2c_client *client,
573 i2c_set_clientdata(client, pcf); 282 i2c_set_clientdata(client, pcf);
574 pcf->dev = &client->dev; 283 pcf->dev = &client->dev;
575 pcf->i2c_client = client; 284 pcf->i2c_client = client;
576 pcf->irq = client->irq;
577 pcf->work_queue = create_singlethread_workqueue("pcf50633");
578
579 if (!pcf->work_queue) {
580 dev_err(&client->dev, "Failed to alloc workqueue\n");
581 ret = -ENOMEM;
582 goto err_free;
583 }
584
585 INIT_WORK(&pcf->irq_work, pcf50633_irq_worker);
586 285
587 version = pcf50633_reg_read(pcf, 0); 286 version = pcf50633_reg_read(pcf, 0);
588 variant = pcf50633_reg_read(pcf, 1); 287 variant = pcf50633_reg_read(pcf, 1);
589 if (version < 0 || variant < 0) { 288 if (version < 0 || variant < 0) {
590 dev_err(pcf->dev, "Unable to probe pcf50633\n"); 289 dev_err(pcf->dev, "Unable to probe pcf50633\n");
591 ret = -ENODEV; 290 ret = -ENODEV;
592 goto err_destroy_workqueue; 291 goto err_free;
593 } 292 }
594 293
595 dev_info(pcf->dev, "Probed device version %d variant %d\n", 294 dev_info(pcf->dev, "Probed device version %d variant %d\n",
596 version, variant); 295 version, variant);
597 296
598 /* Enable all interrupts except RTC SECOND */ 297 pcf50633_irq_init(pcf, client->irq);
599 pcf->mask_regs[0] = 0x80;
600 pcf50633_reg_write(pcf, PCF50633_REG_INT1M, pcf->mask_regs[0]);
601 pcf50633_reg_write(pcf, PCF50633_REG_INT2M, 0x00);
602 pcf50633_reg_write(pcf, PCF50633_REG_INT3M, 0x00);
603 pcf50633_reg_write(pcf, PCF50633_REG_INT4M, 0x00);
604 pcf50633_reg_write(pcf, PCF50633_REG_INT5M, 0x00);
605
606 ret = request_irq(client->irq, pcf50633_irq,
607 IRQF_TRIGGER_LOW, "pcf50633", pcf);
608
609 if (ret) {
610 dev_err(pcf->dev, "Failed to request IRQ %d\n", ret);
611 goto err_destroy_workqueue;
612 }
613 298
614 /* Create sub devices */ 299 /* Create sub devices */
615 pcf50633_client_dev_register(pcf, "pcf50633-input", 300 pcf50633_client_dev_register(pcf, "pcf50633-input",
@@ -620,6 +305,9 @@ static int __devinit pcf50633_probe(struct i2c_client *client,
620 &pcf->mbc_pdev); 305 &pcf->mbc_pdev);
621 pcf50633_client_dev_register(pcf, "pcf50633-adc", 306 pcf50633_client_dev_register(pcf, "pcf50633-adc",
622 &pcf->adc_pdev); 307 &pcf->adc_pdev);
308 pcf50633_client_dev_register(pcf, "pcf50633-backlight",
309 &pcf->bl_pdev);
310
623 311
624 for (i = 0; i < PCF50633_NUM_REGULATORS; i++) { 312 for (i = 0; i < PCF50633_NUM_REGULATORS; i++) {
625 struct platform_device *pdev; 313 struct platform_device *pdev;
@@ -638,10 +326,6 @@ static int __devinit pcf50633_probe(struct i2c_client *client,
638 platform_device_add(pdev); 326 platform_device_add(pdev);
639 } 327 }
640 328
641 if (enable_irq_wake(client->irq) < 0)
642 dev_err(pcf->dev, "IRQ %u cannot be enabled as wake-up source"
643 "in this hardware revision", client->irq);
644
645 ret = sysfs_create_group(&client->dev.kobj, &pcf_attr_group); 329 ret = sysfs_create_group(&client->dev.kobj, &pcf_attr_group);
646 if (ret) 330 if (ret)
647 dev_err(pcf->dev, "error creating sysfs entries\n"); 331 dev_err(pcf->dev, "error creating sysfs entries\n");
@@ -651,10 +335,7 @@ static int __devinit pcf50633_probe(struct i2c_client *client,
651 335
652 return 0; 336 return 0;
653 337
654err_destroy_workqueue:
655 destroy_workqueue(pcf->work_queue);
656err_free: 338err_free:
657 i2c_set_clientdata(client, NULL);
658 kfree(pcf); 339 kfree(pcf);
659 340
660 return ret; 341 return ret;
@@ -665,8 +346,7 @@ static int __devexit pcf50633_remove(struct i2c_client *client)
665 struct pcf50633 *pcf = i2c_get_clientdata(client); 346 struct pcf50633 *pcf = i2c_get_clientdata(client);
666 int i; 347 int i;
667 348
668 free_irq(pcf->irq, pcf); 349 pcf50633_irq_free(pcf);
669 destroy_workqueue(pcf->work_queue);
670 350
671 platform_device_unregister(pcf->input_pdev); 351 platform_device_unregister(pcf->input_pdev);
672 platform_device_unregister(pcf->rtc_pdev); 352 platform_device_unregister(pcf->rtc_pdev);
diff --git a/drivers/mfd/pcf50633-irq.c b/drivers/mfd/pcf50633-irq.c
new file mode 100644
index 000000000000..1b0192f1efff
--- /dev/null
+++ b/drivers/mfd/pcf50633-irq.c
@@ -0,0 +1,318 @@
1/* NXP PCF50633 Power Management Unit (PMU) driver
2 *
3 * (C) 2006-2008 by Openmoko, Inc.
4 * Author: Harald Welte <laforge@openmoko.org>
5 * Balaji Rao <balajirrao@openmoko.org>
6 * All rights reserved.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 */
14
15#include <linux/interrupt.h>
16#include <linux/kernel.h>
17#include <linux/mutex.h>
18#include <linux/slab.h>
19
20#include <linux/mfd/pcf50633/core.h>
21
22/* Two MBCS registers used during cold start */
23#define PCF50633_REG_MBCS1 0x4b
24#define PCF50633_REG_MBCS2 0x4c
25#define PCF50633_MBCS1_USBPRES 0x01
26#define PCF50633_MBCS1_ADAPTPRES 0x01
27
28int pcf50633_register_irq(struct pcf50633 *pcf, int irq,
29 void (*handler) (int, void *), void *data)
30{
31 if (irq < 0 || irq >= PCF50633_NUM_IRQ || !handler)
32 return -EINVAL;
33
34 if (WARN_ON(pcf->irq_handler[irq].handler))
35 return -EBUSY;
36
37 mutex_lock(&pcf->lock);
38 pcf->irq_handler[irq].handler = handler;
39 pcf->irq_handler[irq].data = data;
40 mutex_unlock(&pcf->lock);
41
42 return 0;
43}
44EXPORT_SYMBOL_GPL(pcf50633_register_irq);
45
46int pcf50633_free_irq(struct pcf50633 *pcf, int irq)
47{
48 if (irq < 0 || irq >= PCF50633_NUM_IRQ)
49 return -EINVAL;
50
51 mutex_lock(&pcf->lock);
52 pcf->irq_handler[irq].handler = NULL;
53 mutex_unlock(&pcf->lock);
54
55 return 0;
56}
57EXPORT_SYMBOL_GPL(pcf50633_free_irq);
58
59static int __pcf50633_irq_mask_set(struct pcf50633 *pcf, int irq, u8 mask)
60{
61 u8 reg, bit;
62 int ret = 0, idx;
63
64 idx = irq >> 3;
65 reg = PCF50633_REG_INT1M + idx;
66 bit = 1 << (irq & 0x07);
67
68 pcf50633_reg_set_bit_mask(pcf, reg, bit, mask ? bit : 0);
69
70 mutex_lock(&pcf->lock);
71
72 if (mask)
73 pcf->mask_regs[idx] |= bit;
74 else
75 pcf->mask_regs[idx] &= ~bit;
76
77 mutex_unlock(&pcf->lock);
78
79 return ret;
80}
81
82int pcf50633_irq_mask(struct pcf50633 *pcf, int irq)
83{
84 dev_dbg(pcf->dev, "Masking IRQ %d\n", irq);
85
86 return __pcf50633_irq_mask_set(pcf, irq, 1);
87}
88EXPORT_SYMBOL_GPL(pcf50633_irq_mask);
89
90int pcf50633_irq_unmask(struct pcf50633 *pcf, int irq)
91{
92 dev_dbg(pcf->dev, "Unmasking IRQ %d\n", irq);
93
94 return __pcf50633_irq_mask_set(pcf, irq, 0);
95}
96EXPORT_SYMBOL_GPL(pcf50633_irq_unmask);
97
98int pcf50633_irq_mask_get(struct pcf50633 *pcf, int irq)
99{
100 u8 reg, bits;
101
102 reg = irq >> 3;
103 bits = 1 << (irq & 0x07);
104
105 return pcf->mask_regs[reg] & bits;
106}
107EXPORT_SYMBOL_GPL(pcf50633_irq_mask_get);
108
109static void pcf50633_irq_call_handler(struct pcf50633 *pcf, int irq)
110{
111 if (pcf->irq_handler[irq].handler)
112 pcf->irq_handler[irq].handler(irq, pcf->irq_handler[irq].data);
113}
114
115/* Maximum amount of time ONKEY is held before emergency action is taken */
116#define PCF50633_ONKEY1S_TIMEOUT 8
117
118static irqreturn_t pcf50633_irq(int irq, void *data)
119{
120 struct pcf50633 *pcf = data;
121 int ret, i, j;
122 u8 pcf_int[5], chgstat;
123
124 /* Read the 5 INT regs in one transaction */
125 ret = pcf50633_read_block(pcf, PCF50633_REG_INT1,
126 ARRAY_SIZE(pcf_int), pcf_int);
127 if (ret != ARRAY_SIZE(pcf_int)) {
128 dev_err(pcf->dev, "Error reading INT registers\n");
129
130 /*
131 * If this doesn't ACK the interrupt to the chip, we'll be
132 * called once again as we're level triggered.
133 */
134 goto out;
135 }
136
137 /* defeat 8s death from lowsys on A5 */
138 pcf50633_reg_write(pcf, PCF50633_REG_OOCSHDWN, 0x04);
139
140 /* We immediately read the usb and adapter status. We thus make sure
141 * only of USBINS/USBREM IRQ handlers are called */
142 if (pcf_int[0] & (PCF50633_INT1_USBINS | PCF50633_INT1_USBREM)) {
143 chgstat = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2);
144 if (chgstat & (0x3 << 4))
145 pcf_int[0] &= ~PCF50633_INT1_USBREM;
146 else
147 pcf_int[0] &= ~PCF50633_INT1_USBINS;
148 }
149
150 /* Make sure only one of ADPINS or ADPREM is set */
151 if (pcf_int[0] & (PCF50633_INT1_ADPINS | PCF50633_INT1_ADPREM)) {
152 chgstat = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2);
153 if (chgstat & (0x3 << 4))
154 pcf_int[0] &= ~PCF50633_INT1_ADPREM;
155 else
156 pcf_int[0] &= ~PCF50633_INT1_ADPINS;
157 }
158
159 dev_dbg(pcf->dev, "INT1=0x%02x INT2=0x%02x INT3=0x%02x "
160 "INT4=0x%02x INT5=0x%02x\n", pcf_int[0],
161 pcf_int[1], pcf_int[2], pcf_int[3], pcf_int[4]);
162
163 /* Some revisions of the chip don't have a 8s standby mode on
164 * ONKEY1S press. We try to manually do it in such cases. */
165 if ((pcf_int[0] & PCF50633_INT1_SECOND) && pcf->onkey1s_held) {
166 dev_info(pcf->dev, "ONKEY1S held for %d secs\n",
167 pcf->onkey1s_held);
168 if (pcf->onkey1s_held++ == PCF50633_ONKEY1S_TIMEOUT)
169 if (pcf->pdata->force_shutdown)
170 pcf->pdata->force_shutdown(pcf);
171 }
172
173 if (pcf_int[2] & PCF50633_INT3_ONKEY1S) {
174 dev_info(pcf->dev, "ONKEY1S held\n");
175 pcf->onkey1s_held = 1 ;
176
177 /* Unmask IRQ_SECOND */
178 pcf50633_reg_clear_bits(pcf, PCF50633_REG_INT1M,
179 PCF50633_INT1_SECOND);
180
181 /* Unmask IRQ_ONKEYR */
182 pcf50633_reg_clear_bits(pcf, PCF50633_REG_INT2M,
183 PCF50633_INT2_ONKEYR);
184 }
185
186 if ((pcf_int[1] & PCF50633_INT2_ONKEYR) && pcf->onkey1s_held) {
187 pcf->onkey1s_held = 0;
188
189 /* Mask SECOND and ONKEYR interrupts */
190 if (pcf->mask_regs[0] & PCF50633_INT1_SECOND)
191 pcf50633_reg_set_bit_mask(pcf,
192 PCF50633_REG_INT1M,
193 PCF50633_INT1_SECOND,
194 PCF50633_INT1_SECOND);
195
196 if (pcf->mask_regs[1] & PCF50633_INT2_ONKEYR)
197 pcf50633_reg_set_bit_mask(pcf,
198 PCF50633_REG_INT2M,
199 PCF50633_INT2_ONKEYR,
200 PCF50633_INT2_ONKEYR);
201 }
202
203 /* Have we just resumed ? */
204 if (pcf->is_suspended) {
205 pcf->is_suspended = 0;
206
207 /* Set the resume reason filtering out non resumers */
208 for (i = 0; i < ARRAY_SIZE(pcf_int); i++)
209 pcf->resume_reason[i] = pcf_int[i] &
210 pcf->pdata->resumers[i];
211
212 /* Make sure we don't pass on any ONKEY events to
213 * userspace now */
214 pcf_int[1] &= ~(PCF50633_INT2_ONKEYR | PCF50633_INT2_ONKEYF);
215 }
216
217 for (i = 0; i < ARRAY_SIZE(pcf_int); i++) {
218 /* Unset masked interrupts */
219 pcf_int[i] &= ~pcf->mask_regs[i];
220
221 for (j = 0; j < 8 ; j++)
222 if (pcf_int[i] & (1 << j))
223 pcf50633_irq_call_handler(pcf, (i * 8) + j);
224 }
225
226out:
227 return IRQ_HANDLED;
228}
229
230#ifdef CONFIG_PM
231
232int pcf50633_irq_suspend(struct pcf50633 *pcf)
233{
234 int ret;
235 int i;
236 u8 res[5];
237
238
239 /* Make sure our interrupt handlers are not called
240 * henceforth */
241 disable_irq(pcf->irq);
242
243 /* Save the masks */
244 ret = pcf50633_read_block(pcf, PCF50633_REG_INT1M,
245 ARRAY_SIZE(pcf->suspend_irq_masks),
246 pcf->suspend_irq_masks);
247 if (ret < 0) {
248 dev_err(pcf->dev, "error saving irq masks\n");
249 goto out;
250 }
251
252 /* Write wakeup irq masks */
253 for (i = 0; i < ARRAY_SIZE(res); i++)
254 res[i] = ~pcf->pdata->resumers[i];
255
256 ret = pcf50633_write_block(pcf, PCF50633_REG_INT1M,
257 ARRAY_SIZE(res), &res[0]);
258 if (ret < 0) {
259 dev_err(pcf->dev, "error writing wakeup irq masks\n");
260 goto out;
261 }
262
263 pcf->is_suspended = 1;
264
265out:
266 return ret;
267}
268
269int pcf50633_irq_resume(struct pcf50633 *pcf)
270{
271 int ret;
272
273 /* Write the saved mask registers */
274 ret = pcf50633_write_block(pcf, PCF50633_REG_INT1M,
275 ARRAY_SIZE(pcf->suspend_irq_masks),
276 pcf->suspend_irq_masks);
277 if (ret < 0)
278 dev_err(pcf->dev, "Error restoring saved suspend masks\n");
279
280 enable_irq(pcf->irq);
281
282 return ret;
283}
284
285#endif
286
287int pcf50633_irq_init(struct pcf50633 *pcf, int irq)
288{
289 int ret;
290
291 pcf->irq = irq;
292
293 /* Enable all interrupts except RTC SECOND */
294 pcf->mask_regs[0] = 0x80;
295 pcf50633_reg_write(pcf, PCF50633_REG_INT1M, pcf->mask_regs[0]);
296 pcf50633_reg_write(pcf, PCF50633_REG_INT2M, 0x00);
297 pcf50633_reg_write(pcf, PCF50633_REG_INT3M, 0x00);
298 pcf50633_reg_write(pcf, PCF50633_REG_INT4M, 0x00);
299 pcf50633_reg_write(pcf, PCF50633_REG_INT5M, 0x00);
300
301 ret = request_threaded_irq(irq, NULL, pcf50633_irq,
302 IRQF_TRIGGER_LOW | IRQF_ONESHOT,
303 "pcf50633", pcf);
304
305 if (ret)
306 dev_err(pcf->dev, "Failed to request IRQ %d\n", ret);
307
308 if (enable_irq_wake(irq) < 0)
309 dev_err(pcf->dev, "IRQ %u cannot be enabled as wake-up source"
310 "in this hardware revision", irq);
311
312 return ret;
313}
314
315void pcf50633_irq_free(struct pcf50633 *pcf)
316{
317 free_irq(pcf->irq, pcf);
318}
diff --git a/drivers/mfd/rdc321x-southbridge.c b/drivers/mfd/rdc321x-southbridge.c
new file mode 100644
index 000000000000..50922975bda3
--- /dev/null
+++ b/drivers/mfd/rdc321x-southbridge.c
@@ -0,0 +1,123 @@
1/*
2 * RDC321x MFD southbrige driver
3 *
4 * Copyright (C) 2007-2010 Florian Fainelli <florian@openwrt.org>
5 * Copyright (C) 2010 Bernhard Loos <bernhardloos@googlemail.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 */
22#include <linux/init.h>
23#include <linux/module.h>
24#include <linux/kernel.h>
25#include <linux/platform_device.h>
26#include <linux/pci.h>
27#include <linux/mfd/core.h>
28#include <linux/mfd/rdc321x.h>
29
30static struct rdc321x_wdt_pdata rdc321x_wdt_pdata;
31
32static struct resource rdc321x_wdt_resource[] = {
33 {
34 .name = "wdt-reg",
35 .start = RDC321X_WDT_CTRL,
36 .end = RDC321X_WDT_CTRL + 0x3,
37 .flags = IORESOURCE_IO,
38 }
39};
40
41static struct rdc321x_gpio_pdata rdc321x_gpio_pdata = {
42 .max_gpios = RDC321X_MAX_GPIO,
43};
44
45static struct resource rdc321x_gpio_resources[] = {
46 {
47 .name = "gpio-reg1",
48 .start = RDC321X_GPIO_CTRL_REG1,
49 .end = RDC321X_GPIO_CTRL_REG1 + 0x7,
50 .flags = IORESOURCE_IO,
51 }, {
52 .name = "gpio-reg2",
53 .start = RDC321X_GPIO_CTRL_REG2,
54 .end = RDC321X_GPIO_CTRL_REG2 + 0x7,
55 .flags = IORESOURCE_IO,
56 }
57};
58
59static struct mfd_cell rdc321x_sb_cells[] = {
60 {
61 .name = "rdc321x-wdt",
62 .resources = rdc321x_wdt_resource,
63 .num_resources = ARRAY_SIZE(rdc321x_wdt_resource),
64 .driver_data = &rdc321x_wdt_pdata,
65 }, {
66 .name = "rdc321x-gpio",
67 .resources = rdc321x_gpio_resources,
68 .num_resources = ARRAY_SIZE(rdc321x_gpio_resources),
69 .driver_data = &rdc321x_gpio_pdata,
70 },
71};
72
73static int __devinit rdc321x_sb_probe(struct pci_dev *pdev,
74 const struct pci_device_id *ent)
75{
76 int err;
77
78 err = pci_enable_device(pdev);
79 if (err) {
80 dev_err(&pdev->dev, "failed to enable device\n");
81 return err;
82 }
83
84 rdc321x_gpio_pdata.sb_pdev = pdev;
85 rdc321x_wdt_pdata.sb_pdev = pdev;
86
87 return mfd_add_devices(&pdev->dev, -1,
88 rdc321x_sb_cells, ARRAY_SIZE(rdc321x_sb_cells), NULL, 0);
89}
90
91static void __devexit rdc321x_sb_remove(struct pci_dev *pdev)
92{
93 mfd_remove_devices(&pdev->dev);
94}
95
96static DEFINE_PCI_DEVICE_TABLE(rdc321x_sb_table) = {
97 { PCI_DEVICE(PCI_VENDOR_ID_RDC, PCI_DEVICE_ID_RDC_R6030) },
98 {}
99};
100
101static struct pci_driver rdc321x_sb_driver = {
102 .name = "RDC321x Southbridge",
103 .id_table = rdc321x_sb_table,
104 .probe = rdc321x_sb_probe,
105 .remove = __devexit_p(rdc321x_sb_remove),
106};
107
108static int __init rdc321x_sb_init(void)
109{
110 return pci_register_driver(&rdc321x_sb_driver);
111}
112
113static void __exit rdc321x_sb_exit(void)
114{
115 pci_unregister_driver(&rdc321x_sb_driver);
116}
117
118module_init(rdc321x_sb_init);
119module_exit(rdc321x_sb_exit);
120
121MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
122MODULE_LICENSE("GPL");
123MODULE_DESCRIPTION("RDC R-321x MFD southbridge driver");
diff --git a/drivers/mfd/t7l66xb.c b/drivers/mfd/t7l66xb.c
index da6383a934ac..5041d33adf0b 100644
--- a/drivers/mfd/t7l66xb.c
+++ b/drivers/mfd/t7l66xb.c
@@ -318,6 +318,9 @@ static int t7l66xb_probe(struct platform_device *dev)
318 struct resource *iomem, *rscr; 318 struct resource *iomem, *rscr;
319 int ret; 319 int ret;
320 320
321 if (pdata == NULL)
322 return -EINVAL;
323
321 iomem = platform_get_resource(dev, IORESOURCE_MEM, 0); 324 iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
322 if (!iomem) 325 if (!iomem)
323 return -EINVAL; 326 return -EINVAL;
diff --git a/drivers/mfd/tc35892.c b/drivers/mfd/tc35892.c
new file mode 100644
index 000000000000..e619e2a55997
--- /dev/null
+++ b/drivers/mfd/tc35892.c
@@ -0,0 +1,345 @@
1/*
2 * Copyright (C) ST-Ericsson SA 2010
3 *
4 * License Terms: GNU General Public License, version 2
5 * Author: Hanumath Prasad <hanumath.prasad@stericsson.com> for ST-Ericsson
6 * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
7 */
8
9#include <linux/module.h>
10#include <linux/interrupt.h>
11#include <linux/irq.h>
12#include <linux/slab.h>
13#include <linux/i2c.h>
14#include <linux/mfd/core.h>
15#include <linux/mfd/tc35892.h>
16
17/**
18 * tc35892_reg_read() - read a single TC35892 register
19 * @tc35892: Device to read from
20 * @reg: Register to read
21 */
22int tc35892_reg_read(struct tc35892 *tc35892, u8 reg)
23{
24 int ret;
25
26 ret = i2c_smbus_read_byte_data(tc35892->i2c, reg);
27 if (ret < 0)
28 dev_err(tc35892->dev, "failed to read reg %#x: %d\n",
29 reg, ret);
30
31 return ret;
32}
33EXPORT_SYMBOL_GPL(tc35892_reg_read);
34
35/**
36 * tc35892_reg_read() - write a single TC35892 register
37 * @tc35892: Device to write to
38 * @reg: Register to read
39 * @data: Value to write
40 */
41int tc35892_reg_write(struct tc35892 *tc35892, u8 reg, u8 data)
42{
43 int ret;
44
45 ret = i2c_smbus_write_byte_data(tc35892->i2c, reg, data);
46 if (ret < 0)
47 dev_err(tc35892->dev, "failed to write reg %#x: %d\n",
48 reg, ret);
49
50 return ret;
51}
52EXPORT_SYMBOL_GPL(tc35892_reg_write);
53
54/**
55 * tc35892_block_read() - read multiple TC35892 registers
56 * @tc35892: Device to read from
57 * @reg: First register
58 * @length: Number of registers
59 * @values: Buffer to write to
60 */
61int tc35892_block_read(struct tc35892 *tc35892, u8 reg, u8 length, u8 *values)
62{
63 int ret;
64
65 ret = i2c_smbus_read_i2c_block_data(tc35892->i2c, reg, length, values);
66 if (ret < 0)
67 dev_err(tc35892->dev, "failed to read regs %#x: %d\n",
68 reg, ret);
69
70 return ret;
71}
72EXPORT_SYMBOL_GPL(tc35892_block_read);
73
74/**
75 * tc35892_block_write() - write multiple TC35892 registers
76 * @tc35892: Device to write to
77 * @reg: First register
78 * @length: Number of registers
79 * @values: Values to write
80 */
81int tc35892_block_write(struct tc35892 *tc35892, u8 reg, u8 length,
82 const u8 *values)
83{
84 int ret;
85
86 ret = i2c_smbus_write_i2c_block_data(tc35892->i2c, reg, length,
87 values);
88 if (ret < 0)
89 dev_err(tc35892->dev, "failed to write regs %#x: %d\n",
90 reg, ret);
91
92 return ret;
93}
94EXPORT_SYMBOL_GPL(tc35892_block_write);
95
96/**
97 * tc35892_set_bits() - set the value of a bitfield in a TC35892 register
98 * @tc35892: Device to write to
99 * @reg: Register to write
100 * @mask: Mask of bits to set
101 * @values: Value to set
102 */
103int tc35892_set_bits(struct tc35892 *tc35892, u8 reg, u8 mask, u8 val)
104{
105 int ret;
106
107 mutex_lock(&tc35892->lock);
108
109 ret = tc35892_reg_read(tc35892, reg);
110 if (ret < 0)
111 goto out;
112
113 ret &= ~mask;
114 ret |= val;
115
116 ret = tc35892_reg_write(tc35892, reg, ret);
117
118out:
119 mutex_unlock(&tc35892->lock);
120 return ret;
121}
122EXPORT_SYMBOL_GPL(tc35892_set_bits);
123
124static struct resource gpio_resources[] = {
125 {
126 .start = TC35892_INT_GPIIRQ,
127 .end = TC35892_INT_GPIIRQ,
128 .flags = IORESOURCE_IRQ,
129 },
130};
131
132static struct mfd_cell tc35892_devs[] = {
133 {
134 .name = "tc35892-gpio",
135 .num_resources = ARRAY_SIZE(gpio_resources),
136 .resources = &gpio_resources[0],
137 },
138};
139
140static irqreturn_t tc35892_irq(int irq, void *data)
141{
142 struct tc35892 *tc35892 = data;
143 int status;
144
145 status = tc35892_reg_read(tc35892, TC35892_IRQST);
146 if (status < 0)
147 return IRQ_NONE;
148
149 while (status) {
150 int bit = __ffs(status);
151
152 handle_nested_irq(tc35892->irq_base + bit);
153 status &= ~(1 << bit);
154 }
155
156 /*
157 * A dummy read or write (to any register) appears to be necessary to
158 * have the last interrupt clear (for example, GPIO IC write) take
159 * effect.
160 */
161 tc35892_reg_read(tc35892, TC35892_IRQST);
162
163 return IRQ_HANDLED;
164}
165
166static void tc35892_irq_dummy(unsigned int irq)
167{
168 /* No mask/unmask at this level */
169}
170
171static struct irq_chip tc35892_irq_chip = {
172 .name = "tc35892",
173 .mask = tc35892_irq_dummy,
174 .unmask = tc35892_irq_dummy,
175};
176
177static int tc35892_irq_init(struct tc35892 *tc35892)
178{
179 int base = tc35892->irq_base;
180 int irq;
181
182 for (irq = base; irq < base + TC35892_NR_INTERNAL_IRQS; irq++) {
183 set_irq_chip_data(irq, tc35892);
184 set_irq_chip_and_handler(irq, &tc35892_irq_chip,
185 handle_edge_irq);
186 set_irq_nested_thread(irq, 1);
187#ifdef CONFIG_ARM
188 set_irq_flags(irq, IRQF_VALID);
189#else
190 set_irq_noprobe(irq);
191#endif
192 }
193
194 return 0;
195}
196
197static void tc35892_irq_remove(struct tc35892 *tc35892)
198{
199 int base = tc35892->irq_base;
200 int irq;
201
202 for (irq = base; irq < base + TC35892_NR_INTERNAL_IRQS; irq++) {
203#ifdef CONFIG_ARM
204 set_irq_flags(irq, 0);
205#endif
206 set_irq_chip_and_handler(irq, NULL, NULL);
207 set_irq_chip_data(irq, NULL);
208 }
209}
210
211static int tc35892_chip_init(struct tc35892 *tc35892)
212{
213 int manf, ver, ret;
214
215 manf = tc35892_reg_read(tc35892, TC35892_MANFCODE);
216 if (manf < 0)
217 return manf;
218
219 ver = tc35892_reg_read(tc35892, TC35892_VERSION);
220 if (ver < 0)
221 return ver;
222
223 if (manf != TC35892_MANFCODE_MAGIC) {
224 dev_err(tc35892->dev, "unknown manufacturer: %#x\n", manf);
225 return -EINVAL;
226 }
227
228 dev_info(tc35892->dev, "manufacturer: %#x, version: %#x\n", manf, ver);
229
230 /* Put everything except the IRQ module into reset */
231 ret = tc35892_reg_write(tc35892, TC35892_RSTCTRL,
232 TC35892_RSTCTRL_TIMRST
233 | TC35892_RSTCTRL_ROTRST
234 | TC35892_RSTCTRL_KBDRST
235 | TC35892_RSTCTRL_GPIRST);
236 if (ret < 0)
237 return ret;
238
239 /* Clear the reset interrupt. */
240 return tc35892_reg_write(tc35892, TC35892_RSTINTCLR, 0x1);
241}
242
243static int __devinit tc35892_probe(struct i2c_client *i2c,
244 const struct i2c_device_id *id)
245{
246 struct tc35892_platform_data *pdata = i2c->dev.platform_data;
247 struct tc35892 *tc35892;
248 int ret;
249
250 if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA
251 | I2C_FUNC_SMBUS_I2C_BLOCK))
252 return -EIO;
253
254 tc35892 = kzalloc(sizeof(struct tc35892), GFP_KERNEL);
255 if (!tc35892)
256 return -ENOMEM;
257
258 mutex_init(&tc35892->lock);
259
260 tc35892->dev = &i2c->dev;
261 tc35892->i2c = i2c;
262 tc35892->pdata = pdata;
263 tc35892->irq_base = pdata->irq_base;
264 tc35892->num_gpio = id->driver_data;
265
266 i2c_set_clientdata(i2c, tc35892);
267
268 ret = tc35892_chip_init(tc35892);
269 if (ret)
270 goto out_free;
271
272 ret = tc35892_irq_init(tc35892);
273 if (ret)
274 goto out_free;
275
276 ret = request_threaded_irq(tc35892->i2c->irq, NULL, tc35892_irq,
277 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
278 "tc35892", tc35892);
279 if (ret) {
280 dev_err(tc35892->dev, "failed to request IRQ: %d\n", ret);
281 goto out_removeirq;
282 }
283
284 ret = mfd_add_devices(tc35892->dev, -1, tc35892_devs,
285 ARRAY_SIZE(tc35892_devs), NULL,
286 tc35892->irq_base);
287 if (ret) {
288 dev_err(tc35892->dev, "failed to add children\n");
289 goto out_freeirq;
290 }
291
292 return 0;
293
294out_freeirq:
295 free_irq(tc35892->i2c->irq, tc35892);
296out_removeirq:
297 tc35892_irq_remove(tc35892);
298out_free:
299 kfree(tc35892);
300 return ret;
301}
302
303static int __devexit tc35892_remove(struct i2c_client *client)
304{
305 struct tc35892 *tc35892 = i2c_get_clientdata(client);
306
307 mfd_remove_devices(tc35892->dev);
308
309 free_irq(tc35892->i2c->irq, tc35892);
310 tc35892_irq_remove(tc35892);
311
312 kfree(tc35892);
313
314 return 0;
315}
316
317static const struct i2c_device_id tc35892_id[] = {
318 { "tc35892", 24 },
319 { }
320};
321MODULE_DEVICE_TABLE(i2c, tc35892_id);
322
323static struct i2c_driver tc35892_driver = {
324 .driver.name = "tc35892",
325 .driver.owner = THIS_MODULE,
326 .probe = tc35892_probe,
327 .remove = __devexit_p(tc35892_remove),
328 .id_table = tc35892_id,
329};
330
331static int __init tc35892_init(void)
332{
333 return i2c_add_driver(&tc35892_driver);
334}
335subsys_initcall(tc35892_init);
336
337static void __exit tc35892_exit(void)
338{
339 i2c_del_driver(&tc35892_driver);
340}
341module_exit(tc35892_exit);
342
343MODULE_LICENSE("GPL v2");
344MODULE_DESCRIPTION("TC35892 MFD core driver");
345MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent");
diff --git a/drivers/mfd/timberdale.c b/drivers/mfd/timberdale.c
index 7f478ec4184b..ac5995026c88 100644
--- a/drivers/mfd/timberdale.c
+++ b/drivers/mfd/timberdale.c
@@ -31,6 +31,7 @@
31 31
32#include <linux/i2c.h> 32#include <linux/i2c.h>
33#include <linux/i2c-ocores.h> 33#include <linux/i2c-ocores.h>
34#include <linux/i2c-xiic.h>
34#include <linux/i2c/tsc2007.h> 35#include <linux/i2c/tsc2007.h>
35 36
36#include <linux/spi/spi.h> 37#include <linux/spi/spi.h>
@@ -40,6 +41,8 @@
40 41
41#include <media/timb_radio.h> 42#include <media/timb_radio.h>
42 43
44#include <linux/timb_dma.h>
45
43#include "timberdale.h" 46#include "timberdale.h"
44 47
45#define DRIVER_NAME "timberdale" 48#define DRIVER_NAME "timberdale"
@@ -69,6 +72,12 @@ static struct i2c_board_info timberdale_i2c_board_info[] = {
69 }, 72 },
70}; 73};
71 74
75static __devinitdata struct xiic_i2c_platform_data
76timberdale_xiic_platform_data = {
77 .devices = timberdale_i2c_board_info,
78 .num_devices = ARRAY_SIZE(timberdale_i2c_board_info)
79};
80
72static __devinitdata struct ocores_i2c_platform_data 81static __devinitdata struct ocores_i2c_platform_data
73timberdale_ocores_platform_data = { 82timberdale_ocores_platform_data = {
74 .regstep = 4, 83 .regstep = 4,
@@ -77,7 +86,20 @@ timberdale_ocores_platform_data = {
77 .num_devices = ARRAY_SIZE(timberdale_i2c_board_info) 86 .num_devices = ARRAY_SIZE(timberdale_i2c_board_info)
78}; 87};
79 88
80const static __devinitconst struct resource timberdale_ocores_resources[] = { 89static const __devinitconst struct resource timberdale_xiic_resources[] = {
90 {
91 .start = XIICOFFSET,
92 .end = XIICEND,
93 .flags = IORESOURCE_MEM,
94 },
95 {
96 .start = IRQ_TIMBERDALE_I2C,
97 .end = IRQ_TIMBERDALE_I2C,
98 .flags = IORESOURCE_IRQ,
99 },
100};
101
102static const __devinitconst struct resource timberdale_ocores_resources[] = {
81 { 103 {
82 .start = OCORESOFFSET, 104 .start = OCORESOFFSET,
83 .end = OCORESEND, 105 .end = OCORESEND,
@@ -126,7 +148,7 @@ static __devinitdata struct xspi_platform_data timberdale_xspi_platform_data = {
126 */ 148 */
127}; 149};
128 150
129const static __devinitconst struct resource timberdale_spi_resources[] = { 151static const __devinitconst struct resource timberdale_spi_resources[] = {
130 { 152 {
131 .start = SPIOFFSET, 153 .start = SPIOFFSET,
132 .end = SPIEND, 154 .end = SPIEND,
@@ -139,7 +161,7 @@ const static __devinitconst struct resource timberdale_spi_resources[] = {
139 }, 161 },
140}; 162};
141 163
142const static __devinitconst struct resource timberdale_eth_resources[] = { 164static const __devinitconst struct resource timberdale_eth_resources[] = {
143 { 165 {
144 .start = ETHOFFSET, 166 .start = ETHOFFSET,
145 .end = ETHEND, 167 .end = ETHEND,
@@ -159,7 +181,7 @@ static __devinitdata struct timbgpio_platform_data
159 .irq_base = 200, 181 .irq_base = 200,
160}; 182};
161 183
162const static __devinitconst struct resource timberdale_gpio_resources[] = { 184static const __devinitconst struct resource timberdale_gpio_resources[] = {
163 { 185 {
164 .start = GPIOOFFSET, 186 .start = GPIOOFFSET,
165 .end = GPIOEND, 187 .end = GPIOEND,
@@ -172,7 +194,7 @@ const static __devinitconst struct resource timberdale_gpio_resources[] = {
172 }, 194 },
173}; 195};
174 196
175const static __devinitconst struct resource timberdale_mlogicore_resources[] = { 197static const __devinitconst struct resource timberdale_mlogicore_resources[] = {
176 { 198 {
177 .start = MLCOREOFFSET, 199 .start = MLCOREOFFSET,
178 .end = MLCOREEND, 200 .end = MLCOREEND,
@@ -190,7 +212,7 @@ const static __devinitconst struct resource timberdale_mlogicore_resources[] = {
190 }, 212 },
191}; 213};
192 214
193const static __devinitconst struct resource timberdale_uart_resources[] = { 215static const __devinitconst struct resource timberdale_uart_resources[] = {
194 { 216 {
195 .start = UARTOFFSET, 217 .start = UARTOFFSET,
196 .end = UARTEND, 218 .end = UARTEND,
@@ -203,7 +225,7 @@ const static __devinitconst struct resource timberdale_uart_resources[] = {
203 }, 225 },
204}; 226};
205 227
206const static __devinitconst struct resource timberdale_uartlite_resources[] = { 228static const __devinitconst struct resource timberdale_uartlite_resources[] = {
207 { 229 {
208 .start = UARTLITEOFFSET, 230 .start = UARTLITEOFFSET,
209 .end = UARTLITEEND, 231 .end = UARTLITEEND,
@@ -216,7 +238,7 @@ const static __devinitconst struct resource timberdale_uartlite_resources[] = {
216 }, 238 },
217}; 239};
218 240
219const static __devinitconst struct resource timberdale_radio_resources[] = { 241static const __devinitconst struct resource timberdale_radio_resources[] = {
220 { 242 {
221 .start = RDSOFFSET, 243 .start = RDSOFFSET,
222 .end = RDSEND, 244 .end = RDSEND,
@@ -250,7 +272,66 @@ static __devinitdata struct timb_radio_platform_data
250 } 272 }
251}; 273};
252 274
253const static __devinitconst struct resource timberdale_dma_resources[] = { 275static __devinitdata struct timb_dma_platform_data timb_dma_platform_data = {
276 .nr_channels = 10,
277 .channels = {
278 {
279 /* UART RX */
280 .rx = true,
281 .descriptors = 2,
282 .descriptor_elements = 1
283 },
284 {
285 /* UART TX */
286 .rx = false,
287 .descriptors = 2,
288 .descriptor_elements = 1
289 },
290 {
291 /* MLB RX */
292 .rx = true,
293 .descriptors = 2,
294 .descriptor_elements = 1
295 },
296 {
297 /* MLB TX */
298 .rx = false,
299 .descriptors = 2,
300 .descriptor_elements = 1
301 },
302 {
303 /* Video RX */
304 .rx = true,
305 .bytes_per_line = 1440,
306 .descriptors = 2,
307 .descriptor_elements = 16
308 },
309 {
310 /* Video framedrop */
311 },
312 {
313 /* SDHCI RX */
314 .rx = true,
315 },
316 {
317 /* SDHCI TX */
318 },
319 {
320 /* ETH RX */
321 .rx = true,
322 .descriptors = 2,
323 .descriptor_elements = 1
324 },
325 {
326 /* ETH TX */
327 .rx = false,
328 .descriptors = 2,
329 .descriptor_elements = 1
330 },
331 }
332};
333
334static const __devinitconst struct resource timberdale_dma_resources[] = {
254 { 335 {
255 .start = DMAOFFSET, 336 .start = DMAOFFSET,
256 .end = DMAEND, 337 .end = DMAEND,
@@ -265,11 +346,25 @@ const static __devinitconst struct resource timberdale_dma_resources[] = {
265 346
266static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg0[] = { 347static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg0[] = {
267 { 348 {
349 .name = "timb-dma",
350 .num_resources = ARRAY_SIZE(timberdale_dma_resources),
351 .resources = timberdale_dma_resources,
352 .platform_data = &timb_dma_platform_data,
353 .data_size = sizeof(timb_dma_platform_data),
354 },
355 {
268 .name = "timb-uart", 356 .name = "timb-uart",
269 .num_resources = ARRAY_SIZE(timberdale_uart_resources), 357 .num_resources = ARRAY_SIZE(timberdale_uart_resources),
270 .resources = timberdale_uart_resources, 358 .resources = timberdale_uart_resources,
271 }, 359 },
272 { 360 {
361 .name = "xiic-i2c",
362 .num_resources = ARRAY_SIZE(timberdale_xiic_resources),
363 .resources = timberdale_xiic_resources,
364 .platform_data = &timberdale_xiic_platform_data,
365 .data_size = sizeof(timberdale_xiic_platform_data),
366 },
367 {
273 .name = "timb-gpio", 368 .name = "timb-gpio",
274 .num_resources = ARRAY_SIZE(timberdale_gpio_resources), 369 .num_resources = ARRAY_SIZE(timberdale_gpio_resources),
275 .resources = timberdale_gpio_resources, 370 .resources = timberdale_gpio_resources,
@@ -295,14 +390,16 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg0[] = {
295 .num_resources = ARRAY_SIZE(timberdale_eth_resources), 390 .num_resources = ARRAY_SIZE(timberdale_eth_resources),
296 .resources = timberdale_eth_resources, 391 .resources = timberdale_eth_resources,
297 }, 392 },
393};
394
395static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = {
298 { 396 {
299 .name = "timb-dma", 397 .name = "timb-dma",
300 .num_resources = ARRAY_SIZE(timberdale_dma_resources), 398 .num_resources = ARRAY_SIZE(timberdale_dma_resources),
301 .resources = timberdale_dma_resources, 399 .resources = timberdale_dma_resources,
400 .platform_data = &timb_dma_platform_data,
401 .data_size = sizeof(timb_dma_platform_data),
302 }, 402 },
303};
304
305static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = {
306 { 403 {
307 .name = "timb-uart", 404 .name = "timb-uart",
308 .num_resources = ARRAY_SIZE(timberdale_uart_resources), 405 .num_resources = ARRAY_SIZE(timberdale_uart_resources),
@@ -314,6 +411,13 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = {
314 .resources = timberdale_uartlite_resources, 411 .resources = timberdale_uartlite_resources,
315 }, 412 },
316 { 413 {
414 .name = "xiic-i2c",
415 .num_resources = ARRAY_SIZE(timberdale_xiic_resources),
416 .resources = timberdale_xiic_resources,
417 .platform_data = &timberdale_xiic_platform_data,
418 .data_size = sizeof(timberdale_xiic_platform_data),
419 },
420 {
317 .name = "timb-gpio", 421 .name = "timb-gpio",
318 .num_resources = ARRAY_SIZE(timberdale_gpio_resources), 422 .num_resources = ARRAY_SIZE(timberdale_gpio_resources),
319 .resources = timberdale_gpio_resources, 423 .resources = timberdale_gpio_resources,
@@ -344,20 +448,29 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = {
344 .num_resources = ARRAY_SIZE(timberdale_eth_resources), 448 .num_resources = ARRAY_SIZE(timberdale_eth_resources),
345 .resources = timberdale_eth_resources, 449 .resources = timberdale_eth_resources,
346 }, 450 },
451};
452
453static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg2[] = {
347 { 454 {
348 .name = "timb-dma", 455 .name = "timb-dma",
349 .num_resources = ARRAY_SIZE(timberdale_dma_resources), 456 .num_resources = ARRAY_SIZE(timberdale_dma_resources),
350 .resources = timberdale_dma_resources, 457 .resources = timberdale_dma_resources,
458 .platform_data = &timb_dma_platform_data,
459 .data_size = sizeof(timb_dma_platform_data),
351 }, 460 },
352};
353
354static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg2[] = {
355 { 461 {
356 .name = "timb-uart", 462 .name = "timb-uart",
357 .num_resources = ARRAY_SIZE(timberdale_uart_resources), 463 .num_resources = ARRAY_SIZE(timberdale_uart_resources),
358 .resources = timberdale_uart_resources, 464 .resources = timberdale_uart_resources,
359 }, 465 },
360 { 466 {
467 .name = "xiic-i2c",
468 .num_resources = ARRAY_SIZE(timberdale_xiic_resources),
469 .resources = timberdale_xiic_resources,
470 .platform_data = &timberdale_xiic_platform_data,
471 .data_size = sizeof(timberdale_xiic_platform_data),
472 },
473 {
361 .name = "timb-gpio", 474 .name = "timb-gpio",
362 .num_resources = ARRAY_SIZE(timberdale_gpio_resources), 475 .num_resources = ARRAY_SIZE(timberdale_gpio_resources),
363 .resources = timberdale_gpio_resources, 476 .resources = timberdale_gpio_resources,
@@ -378,14 +491,16 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg2[] = {
378 .platform_data = &timberdale_xspi_platform_data, 491 .platform_data = &timberdale_xspi_platform_data,
379 .data_size = sizeof(timberdale_xspi_platform_data), 492 .data_size = sizeof(timberdale_xspi_platform_data),
380 }, 493 },
494};
495
496static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg3[] = {
381 { 497 {
382 .name = "timb-dma", 498 .name = "timb-dma",
383 .num_resources = ARRAY_SIZE(timberdale_dma_resources), 499 .num_resources = ARRAY_SIZE(timberdale_dma_resources),
384 .resources = timberdale_dma_resources, 500 .resources = timberdale_dma_resources,
501 .platform_data = &timb_dma_platform_data,
502 .data_size = sizeof(timb_dma_platform_data),
385 }, 503 },
386};
387
388static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg3[] = {
389 { 504 {
390 .name = "timb-uart", 505 .name = "timb-uart",
391 .num_resources = ARRAY_SIZE(timberdale_uart_resources), 506 .num_resources = ARRAY_SIZE(timberdale_uart_resources),
@@ -424,11 +539,6 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg3[] = {
424 .num_resources = ARRAY_SIZE(timberdale_eth_resources), 539 .num_resources = ARRAY_SIZE(timberdale_eth_resources),
425 .resources = timberdale_eth_resources, 540 .resources = timberdale_eth_resources,
426 }, 541 },
427 {
428 .name = "timb-dma",
429 .num_resources = ARRAY_SIZE(timberdale_dma_resources),
430 .resources = timberdale_dma_resources,
431 },
432}; 542};
433 543
434static const __devinitconst struct resource timberdale_sdhc_resources[] = { 544static const __devinitconst struct resource timberdale_sdhc_resources[] = {
diff --git a/drivers/mfd/timberdale.h b/drivers/mfd/timberdale.h
index 8d27ffabc25d..c11bf6ebfe00 100644
--- a/drivers/mfd/timberdale.h
+++ b/drivers/mfd/timberdale.h
@@ -23,7 +23,7 @@
23#ifndef MFD_TIMBERDALE_H 23#ifndef MFD_TIMBERDALE_H
24#define MFD_TIMBERDALE_H 24#define MFD_TIMBERDALE_H
25 25
26#define DRV_VERSION "0.1" 26#define DRV_VERSION "0.2"
27 27
28/* This driver only support versions >= 3.8 and < 4.0 */ 28/* This driver only support versions >= 3.8 and < 4.0 */
29#define TIMB_SUPPORTED_MAJOR 3 29#define TIMB_SUPPORTED_MAJOR 3
@@ -66,7 +66,7 @@
66 66
67#define CHIPCTLOFFSET 0x800 67#define CHIPCTLOFFSET 0x800
68#define CHIPCTLEND 0x8ff 68#define CHIPCTLEND 0x8ff
69#define CHIPCTLSIZE (CHIPCTLEND - CHIPCTLOFFSET) 69#define CHIPCTLSIZE (CHIPCTLEND - CHIPCTLOFFSET + 1)
70 70
71#define INTCOFFSET 0xc00 71#define INTCOFFSET 0xc00
72#define INTCEND 0xfff 72#define INTCEND 0xfff
@@ -127,4 +127,16 @@
127#define GPIO_PIN_BT_RST 15 127#define GPIO_PIN_BT_RST 15
128#define GPIO_NR_PINS 16 128#define GPIO_NR_PINS 16
129 129
130/* DMA Channels */
131#define DMA_UART_RX 0
132#define DMA_UART_TX 1
133#define DMA_MLB_RX 2
134#define DMA_MLB_TX 3
135#define DMA_VIDEO_RX 4
136#define DMA_VIDEO_DROP 5
137#define DMA_SDHCI_RX 6
138#define DMA_SDHCI_TX 7
139#define DMA_ETH_RX 8
140#define DMA_ETH_TX 9
141
130#endif 142#endif
diff --git a/drivers/mfd/tps65010.c b/drivers/mfd/tps65010.c
index e5955306c2fa..d0016b67d125 100644
--- a/drivers/mfd/tps65010.c
+++ b/drivers/mfd/tps65010.c
@@ -531,7 +531,6 @@ static int __exit tps65010_remove(struct i2c_client *client)
531 flush_scheduled_work(); 531 flush_scheduled_work();
532 debugfs_remove(tps->file); 532 debugfs_remove(tps->file);
533 kfree(tps); 533 kfree(tps);
534 i2c_set_clientdata(client, NULL);
535 the_tps = NULL; 534 the_tps = NULL;
536 return 0; 535 return 0;
537} 536}
diff --git a/drivers/mfd/tps6507x.c b/drivers/mfd/tps6507x.c
new file mode 100644
index 000000000000..d859dffed39f
--- /dev/null
+++ b/drivers/mfd/tps6507x.c
@@ -0,0 +1,159 @@
1/*
2 * tps6507x.c -- TPS6507x chip family multi-function driver
3 *
4 * Copyright (c) 2010 RidgeRun (todd.fischer@ridgerun.com)
5 *
6 * Author: Todd Fischer
7 * todd.fischer@ridgerun.com
8 *
9 * Credits:
10 *
11 * Using code from wm831x-*.c, wm8400-core, Wolfson Microelectronics PLC.
12 *
13 * For licencing details see kernel-base/COPYING
14 *
15 */
16
17#include <linux/module.h>
18#include <linux/moduleparam.h>
19#include <linux/init.h>
20#include <linux/slab.h>
21#include <linux/i2c.h>
22#include <linux/mfd/core.h>
23#include <linux/mfd/tps6507x.h>
24
25static struct mfd_cell tps6507x_devs[] = {
26 {
27 .name = "tps6507x-pmic",
28 },
29 {
30 .name = "tps6507x-ts",
31 },
32};
33
34
35static int tps6507x_i2c_read_device(struct tps6507x_dev *tps6507x, char reg,
36 int bytes, void *dest)
37{
38 struct i2c_client *i2c = tps6507x->i2c_client;
39 struct i2c_msg xfer[2];
40 int ret;
41
42 /* Write register */
43 xfer[0].addr = i2c->addr;
44 xfer[0].flags = 0;
45 xfer[0].len = 1;
46 xfer[0].buf = &reg;
47
48 /* Read data */
49 xfer[1].addr = i2c->addr;
50 xfer[1].flags = I2C_M_RD;
51 xfer[1].len = bytes;
52 xfer[1].buf = dest;
53
54 ret = i2c_transfer(i2c->adapter, xfer, 2);
55 if (ret == 2)
56 ret = 0;
57 else if (ret >= 0)
58 ret = -EIO;
59
60 return ret;
61}
62
63static int tps6507x_i2c_write_device(struct tps6507x_dev *tps6507x, char reg,
64 int bytes, void *src)
65{
66 struct i2c_client *i2c = tps6507x->i2c_client;
67 /* we add 1 byte for device register */
68 u8 msg[TPS6507X_MAX_REGISTER + 1];
69 int ret;
70
71 if (bytes > (TPS6507X_MAX_REGISTER + 1))
72 return -EINVAL;
73
74 msg[0] = reg;
75 memcpy(&msg[1], src, bytes);
76
77 ret = i2c_master_send(i2c, msg, bytes + 1);
78 if (ret < 0)
79 return ret;
80 if (ret != bytes + 1)
81 return -EIO;
82 return 0;
83}
84
85static int tps6507x_i2c_probe(struct i2c_client *i2c,
86 const struct i2c_device_id *id)
87{
88 struct tps6507x_dev *tps6507x;
89 int ret = 0;
90
91 tps6507x = kzalloc(sizeof(struct tps6507x_dev), GFP_KERNEL);
92 if (tps6507x == NULL) {
93 kfree(i2c);
94 return -ENOMEM;
95 }
96
97 i2c_set_clientdata(i2c, tps6507x);
98 tps6507x->dev = &i2c->dev;
99 tps6507x->i2c_client = i2c;
100 tps6507x->read_dev = tps6507x_i2c_read_device;
101 tps6507x->write_dev = tps6507x_i2c_write_device;
102
103 ret = mfd_add_devices(tps6507x->dev, -1,
104 tps6507x_devs, ARRAY_SIZE(tps6507x_devs),
105 NULL, 0);
106
107 if (ret < 0)
108 goto err;
109
110 return ret;
111
112err:
113 mfd_remove_devices(tps6507x->dev);
114 kfree(tps6507x);
115 return ret;
116}
117
118static int tps6507x_i2c_remove(struct i2c_client *i2c)
119{
120 struct tps6507x_dev *tps6507x = i2c_get_clientdata(i2c);
121
122 mfd_remove_devices(tps6507x->dev);
123 kfree(tps6507x);
124
125 return 0;
126}
127
128static const struct i2c_device_id tps6507x_i2c_id[] = {
129 { "tps6507x", 0 },
130 { }
131};
132MODULE_DEVICE_TABLE(i2c, tps6507x_i2c_id);
133
134
135static struct i2c_driver tps6507x_i2c_driver = {
136 .driver = {
137 .name = "tps6507x",
138 .owner = THIS_MODULE,
139 },
140 .probe = tps6507x_i2c_probe,
141 .remove = tps6507x_i2c_remove,
142 .id_table = tps6507x_i2c_id,
143};
144
145static int __init tps6507x_i2c_init(void)
146{
147 return i2c_add_driver(&tps6507x_i2c_driver);
148}
149/* init early so consumer devices can complete system boot */
150subsys_initcall(tps6507x_i2c_init);
151
152static void __exit tps6507x_i2c_exit(void)
153{
154 i2c_del_driver(&tps6507x_i2c_driver);
155}
156module_exit(tps6507x_i2c_exit);
157
158MODULE_DESCRIPTION("TPS6507x chip family multi-function driver");
159MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c
index 202bdd59632d..097f24d8bceb 100644
--- a/drivers/mfd/twl4030-irq.c
+++ b/drivers/mfd/twl4030-irq.c
@@ -232,10 +232,11 @@ static const struct sih sih_modules_twl5031[8] = {
232 }, 232 },
233 [6] = { 233 [6] = {
234 /* 234 /*
235 * ACI doesn't use the same SIH organization. 235 * ECI/DBI doesn't use the same SIH organization.
236 * For example, it supports only one interrupt line 236 * For example, it supports only one interrupt output line.
237 * That is, the interrupts are seen on both INT1 and INT2 lines.
237 */ 238 */
238 .name = "aci", 239 .name = "eci_dbi",
239 .module = TWL5031_MODULE_ACCESSORY, 240 .module = TWL5031_MODULE_ACCESSORY,
240 .bits = 9, 241 .bits = 9,
241 .bytes_ixr = 2, 242 .bytes_ixr = 2,
@@ -247,8 +248,8 @@ static const struct sih sih_modules_twl5031[8] = {
247 248
248 }, 249 },
249 [7] = { 250 [7] = {
250 /* Accessory */ 251 /* Audio accessory */
251 .name = "acc", 252 .name = "audio",
252 .module = TWL5031_MODULE_ACCESSORY, 253 .module = TWL5031_MODULE_ACCESSORY,
253 .control_offset = TWL5031_ACCSIHCTRL, 254 .control_offset = TWL5031_ACCSIHCTRL,
254 .bits = 2, 255 .bits = 2,
diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c
index f2ab025ad97a..1a968f34d679 100644
--- a/drivers/mfd/wm831x-core.c
+++ b/drivers/mfd/wm831x-core.c
@@ -322,7 +322,11 @@ EXPORT_SYMBOL_GPL(wm831x_set_bits);
322 */ 322 */
323int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input) 323int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input)
324{ 324{
325 int ret, src; 325 int ret, src, irq_masked, timeout;
326
327 /* Are we using the interrupt? */
328 irq_masked = wm831x_reg_read(wm831x, WM831X_INTERRUPT_STATUS_1_MASK);
329 irq_masked &= WM831X_AUXADC_DATA_EINT;
326 330
327 mutex_lock(&wm831x->auxadc_lock); 331 mutex_lock(&wm831x->auxadc_lock);
328 332
@@ -342,6 +346,9 @@ int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input)
342 goto out; 346 goto out;
343 } 347 }
344 348
349 /* Clear any notification from a very late arriving interrupt */
350 try_wait_for_completion(&wm831x->auxadc_done);
351
345 ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL, 352 ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL,
346 WM831X_AUX_CVT_ENA, WM831X_AUX_CVT_ENA); 353 WM831X_AUX_CVT_ENA, WM831X_AUX_CVT_ENA);
347 if (ret < 0) { 354 if (ret < 0) {
@@ -349,22 +356,46 @@ int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input)
349 goto disable; 356 goto disable;
350 } 357 }
351 358
352 /* If an interrupt arrived late clean up after it */ 359 if (irq_masked) {
353 try_wait_for_completion(&wm831x->auxadc_done); 360 /* If we're not using interrupts then poll the
354 361 * interrupt status register */
355 /* Ignore the result to allow us to soldier on without IRQ hookup */ 362 timeout = 5;
356 wait_for_completion_timeout(&wm831x->auxadc_done, msecs_to_jiffies(5)); 363 while (timeout) {
357 364 msleep(1);
358 ret = wm831x_reg_read(wm831x, WM831X_AUXADC_CONTROL); 365
359 if (ret < 0) { 366 ret = wm831x_reg_read(wm831x,
360 dev_err(wm831x->dev, "AUXADC status read failed: %d\n", ret); 367 WM831X_INTERRUPT_STATUS_1);
361 goto disable; 368 if (ret < 0) {
362 } 369 dev_err(wm831x->dev,
363 370 "ISR 1 read failed: %d\n", ret);
364 if (ret & WM831X_AUX_CVT_ENA) { 371 goto disable;
365 dev_err(wm831x->dev, "Timed out reading AUXADC\n"); 372 }
366 ret = -EBUSY; 373
367 goto disable; 374 /* Did it complete? */
375 if (ret & WM831X_AUXADC_DATA_EINT) {
376 wm831x_reg_write(wm831x,
377 WM831X_INTERRUPT_STATUS_1,
378 WM831X_AUXADC_DATA_EINT);
379 break;
380 } else {
381 dev_err(wm831x->dev,
382 "AUXADC conversion timeout\n");
383 ret = -EBUSY;
384 goto disable;
385 }
386 }
387 } else {
388 /* If we are using interrupts then wait for the
389 * interrupt to complete. Use an extremely long
390 * timeout to handle situations with heavy load where
391 * the notification of the interrupt may be delayed by
392 * threaded IRQ handling. */
393 if (!wait_for_completion_timeout(&wm831x->auxadc_done,
394 msecs_to_jiffies(500))) {
395 dev_err(wm831x->dev, "Timed out waiting for AUXADC\n");
396 ret = -EBUSY;
397 goto disable;
398 }
368 } 399 }
369 400
370 ret = wm831x_reg_read(wm831x, WM831X_AUXADC_DATA); 401 ret = wm831x_reg_read(wm831x, WM831X_AUXADC_DATA);
@@ -1463,6 +1494,7 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
1463 case WM8310: 1494 case WM8310:
1464 parent = WM8310; 1495 parent = WM8310;
1465 wm831x->num_gpio = 16; 1496 wm831x->num_gpio = 16;
1497 wm831x->charger_irq_wake = 1;
1466 if (rev > 0) { 1498 if (rev > 0) {
1467 wm831x->has_gpio_ena = 1; 1499 wm831x->has_gpio_ena = 1;
1468 wm831x->has_cs_sts = 1; 1500 wm831x->has_cs_sts = 1;
@@ -1474,6 +1506,7 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
1474 case WM8311: 1506 case WM8311:
1475 parent = WM8311; 1507 parent = WM8311;
1476 wm831x->num_gpio = 16; 1508 wm831x->num_gpio = 16;
1509 wm831x->charger_irq_wake = 1;
1477 if (rev > 0) { 1510 if (rev > 0) {
1478 wm831x->has_gpio_ena = 1; 1511 wm831x->has_gpio_ena = 1;
1479 wm831x->has_cs_sts = 1; 1512 wm831x->has_cs_sts = 1;
@@ -1485,6 +1518,7 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
1485 case WM8312: 1518 case WM8312:
1486 parent = WM8312; 1519 parent = WM8312;
1487 wm831x->num_gpio = 16; 1520 wm831x->num_gpio = 16;
1521 wm831x->charger_irq_wake = 1;
1488 if (rev > 0) { 1522 if (rev > 0) {
1489 wm831x->has_gpio_ena = 1; 1523 wm831x->has_gpio_ena = 1;
1490 wm831x->has_cs_sts = 1; 1524 wm831x->has_cs_sts = 1;
@@ -1623,6 +1657,42 @@ static void wm831x_device_exit(struct wm831x *wm831x)
1623 kfree(wm831x); 1657 kfree(wm831x);
1624} 1658}
1625 1659
1660static int wm831x_device_suspend(struct wm831x *wm831x)
1661{
1662 int reg, mask;
1663
1664 /* If the charger IRQs are a wake source then make sure we ack
1665 * them even if they're not actively being used (eg, no power
1666 * driver or no IRQ line wired up) then acknowledge the
1667 * interrupts otherwise suspend won't last very long.
1668 */
1669 if (wm831x->charger_irq_wake) {
1670 reg = wm831x_reg_read(wm831x, WM831X_INTERRUPT_STATUS_2_MASK);
1671
1672 mask = WM831X_CHG_BATT_HOT_EINT |
1673 WM831X_CHG_BATT_COLD_EINT |
1674 WM831X_CHG_BATT_FAIL_EINT |
1675 WM831X_CHG_OV_EINT | WM831X_CHG_END_EINT |
1676 WM831X_CHG_TO_EINT | WM831X_CHG_MODE_EINT |
1677 WM831X_CHG_START_EINT;
1678
1679 /* If any of the interrupts are masked read the statuses */
1680 if (reg & mask)
1681 reg = wm831x_reg_read(wm831x,
1682 WM831X_INTERRUPT_STATUS_2);
1683
1684 if (reg & mask) {
1685 dev_info(wm831x->dev,
1686 "Acknowledging masked charger IRQs: %x\n",
1687 reg & mask);
1688 wm831x_reg_write(wm831x, WM831X_INTERRUPT_STATUS_2,
1689 reg & mask);
1690 }
1691 }
1692
1693 return 0;
1694}
1695
1626static int wm831x_i2c_read_device(struct wm831x *wm831x, unsigned short reg, 1696static int wm831x_i2c_read_device(struct wm831x *wm831x, unsigned short reg,
1627 int bytes, void *dest) 1697 int bytes, void *dest)
1628{ 1698{
@@ -1697,6 +1767,13 @@ static int wm831x_i2c_remove(struct i2c_client *i2c)
1697 return 0; 1767 return 0;
1698} 1768}
1699 1769
1770static int wm831x_i2c_suspend(struct i2c_client *i2c, pm_message_t mesg)
1771{
1772 struct wm831x *wm831x = i2c_get_clientdata(i2c);
1773
1774 return wm831x_device_suspend(wm831x);
1775}
1776
1700static const struct i2c_device_id wm831x_i2c_id[] = { 1777static const struct i2c_device_id wm831x_i2c_id[] = {
1701 { "wm8310", WM8310 }, 1778 { "wm8310", WM8310 },
1702 { "wm8311", WM8311 }, 1779 { "wm8311", WM8311 },
@@ -1714,6 +1791,7 @@ static struct i2c_driver wm831x_i2c_driver = {
1714 }, 1791 },
1715 .probe = wm831x_i2c_probe, 1792 .probe = wm831x_i2c_probe,
1716 .remove = wm831x_i2c_remove, 1793 .remove = wm831x_i2c_remove,
1794 .suspend = wm831x_i2c_suspend,
1717 .id_table = wm831x_i2c_id, 1795 .id_table = wm831x_i2c_id,
1718}; 1796};
1719 1797
diff --git a/drivers/mfd/wm831x-irq.c b/drivers/mfd/wm831x-irq.c
index 4c1122ceb443..7dabe4dbd373 100644
--- a/drivers/mfd/wm831x-irq.c
+++ b/drivers/mfd/wm831x-irq.c
@@ -39,8 +39,6 @@ struct wm831x_irq_data {
39 int primary; 39 int primary;
40 int reg; 40 int reg;
41 int mask; 41 int mask;
42 irq_handler_t handler;
43 void *handler_data;
44}; 42};
45 43
46static struct wm831x_irq_data wm831x_irqs[] = { 44static struct wm831x_irq_data wm831x_irqs[] = {
@@ -492,6 +490,14 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq)
492 490
493 mutex_init(&wm831x->irq_lock); 491 mutex_init(&wm831x->irq_lock);
494 492
493 /* Mask the individual interrupt sources */
494 for (i = 0; i < ARRAY_SIZE(wm831x->irq_masks_cur); i++) {
495 wm831x->irq_masks_cur[i] = 0xffff;
496 wm831x->irq_masks_cache[i] = 0xffff;
497 wm831x_reg_write(wm831x, WM831X_INTERRUPT_STATUS_1_MASK + i,
498 0xffff);
499 }
500
495 if (!irq) { 501 if (!irq) {
496 dev_warn(wm831x->dev, 502 dev_warn(wm831x->dev,
497 "No interrupt specified - functionality limited\n"); 503 "No interrupt specified - functionality limited\n");
@@ -507,14 +513,6 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq)
507 wm831x->irq = irq; 513 wm831x->irq = irq;
508 wm831x->irq_base = pdata->irq_base; 514 wm831x->irq_base = pdata->irq_base;
509 515
510 /* Mask the individual interrupt sources */
511 for (i = 0; i < ARRAY_SIZE(wm831x->irq_masks_cur); i++) {
512 wm831x->irq_masks_cur[i] = 0xffff;
513 wm831x->irq_masks_cache[i] = 0xffff;
514 wm831x_reg_write(wm831x, WM831X_INTERRUPT_STATUS_1_MASK + i,
515 0xffff);
516 }
517
518 /* Register them with genirq */ 516 /* Register them with genirq */
519 for (cur_irq = wm831x->irq_base; 517 for (cur_irq = wm831x->irq_base;
520 cur_irq < ARRAY_SIZE(wm831x_irqs) + wm831x->irq_base; 518 cur_irq < ARRAY_SIZE(wm831x_irqs) + wm831x->irq_base;
diff --git a/drivers/mfd/wm8350-i2c.c b/drivers/mfd/wm8350-i2c.c
index 65830f57c093..5fe5de166adb 100644
--- a/drivers/mfd/wm8350-i2c.c
+++ b/drivers/mfd/wm8350-i2c.c
@@ -64,10 +64,8 @@ static int wm8350_i2c_probe(struct i2c_client *i2c,
64 int ret = 0; 64 int ret = 0;
65 65
66 wm8350 = kzalloc(sizeof(struct wm8350), GFP_KERNEL); 66 wm8350 = kzalloc(sizeof(struct wm8350), GFP_KERNEL);
67 if (wm8350 == NULL) { 67 if (wm8350 == NULL)
68 kfree(i2c);
69 return -ENOMEM; 68 return -ENOMEM;
70 }
71 69
72 i2c_set_clientdata(i2c, wm8350); 70 i2c_set_clientdata(i2c, wm8350);
73 wm8350->dev = &i2c->dev; 71 wm8350->dev = &i2c->dev;
diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c
index 865ce013a821..1bfef4846b07 100644
--- a/drivers/mfd/wm8400-core.c
+++ b/drivers/mfd/wm8400-core.c
@@ -118,7 +118,7 @@ static int wm8400_read(struct wm8400 *wm8400, u8 reg, int num_regs, u16 *dest)
118{ 118{
119 int i, ret = 0; 119 int i, ret = 0;
120 120
121 BUG_ON(reg + num_regs - 1 > ARRAY_SIZE(wm8400->reg_cache)); 121 BUG_ON(reg + num_regs > ARRAY_SIZE(wm8400->reg_cache));
122 122
123 /* If there are any volatile reads then read back the entire block */ 123 /* If there are any volatile reads then read back the entire block */
124 for (i = reg; i < reg + num_regs; i++) 124 for (i = reg; i < reg + num_regs; i++)
@@ -144,7 +144,7 @@ static int wm8400_write(struct wm8400 *wm8400, u8 reg, int num_regs,
144{ 144{
145 int ret, i; 145 int ret, i;
146 146
147 BUG_ON(reg + num_regs - 1 > ARRAY_SIZE(wm8400->reg_cache)); 147 BUG_ON(reg + num_regs > ARRAY_SIZE(wm8400->reg_cache));
148 148
149 for (i = 0; i < num_regs; i++) { 149 for (i = 0; i < num_regs; i++) {
150 BUG_ON(!reg_data[reg + i].writable); 150 BUG_ON(!reg_data[reg + i].writable);
@@ -415,7 +415,6 @@ static int wm8400_i2c_probe(struct i2c_client *i2c,
415 return 0; 415 return 0;
416 416
417struct_err: 417struct_err:
418 i2c_set_clientdata(i2c, NULL);
419 kfree(wm8400); 418 kfree(wm8400);
420err: 419err:
421 return ret; 420 return ret;
@@ -426,7 +425,6 @@ static int wm8400_i2c_remove(struct i2c_client *i2c)
426 struct wm8400 *wm8400 = i2c_get_clientdata(i2c); 425 struct wm8400 *wm8400 = i2c_get_clientdata(i2c);
427 426
428 wm8400_release(wm8400); 427 wm8400_release(wm8400);
429 i2c_set_clientdata(i2c, NULL);
430 kfree(wm8400); 428 kfree(wm8400);
431 429
432 return 0; 430 return 0;
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index f7ca3a42b490..559b0b3c16c3 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -643,7 +643,6 @@ static int __devexit at24_remove(struct i2c_client *client)
643 643
644 kfree(at24->writebuf); 644 kfree(at24->writebuf);
645 kfree(at24); 645 kfree(at24);
646 i2c_set_clientdata(client, NULL);
647 return 0; 646 return 0;
648} 647}
649 648
diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c
index 31a991161f0a..5bfb2a2041b8 100644
--- a/drivers/misc/lkdtm.c
+++ b/drivers/misc/lkdtm.c
@@ -75,6 +75,9 @@ enum ctype {
75 UNALIGNED_LOAD_STORE_WRITE, 75 UNALIGNED_LOAD_STORE_WRITE,
76 OVERWRITE_ALLOCATION, 76 OVERWRITE_ALLOCATION,
77 WRITE_AFTER_FREE, 77 WRITE_AFTER_FREE,
78 SOFTLOCKUP,
79 HARDLOCKUP,
80 HUNG_TASK,
78}; 81};
79 82
80static char* cp_name[] = { 83static char* cp_name[] = {
@@ -99,6 +102,9 @@ static char* cp_type[] = {
99 "UNALIGNED_LOAD_STORE_WRITE", 102 "UNALIGNED_LOAD_STORE_WRITE",
100 "OVERWRITE_ALLOCATION", 103 "OVERWRITE_ALLOCATION",
101 "WRITE_AFTER_FREE", 104 "WRITE_AFTER_FREE",
105 "SOFTLOCKUP",
106 "HARDLOCKUP",
107 "HUNG_TASK",
102}; 108};
103 109
104static struct jprobe lkdtm; 110static struct jprobe lkdtm;
@@ -320,6 +326,20 @@ static void lkdtm_do_action(enum ctype which)
320 memset(data, 0x78, len); 326 memset(data, 0x78, len);
321 break; 327 break;
322 } 328 }
329 case SOFTLOCKUP:
330 preempt_disable();
331 for (;;)
332 cpu_relax();
333 break;
334 case HARDLOCKUP:
335 local_irq_disable();
336 for (;;)
337 cpu_relax();
338 break;
339 case HUNG_TASK:
340 set_current_state(TASK_UNINTERRUPTIBLE);
341 schedule();
342 break;
323 case NONE: 343 case NONE:
324 default: 344 default:
325 break; 345 break;
diff --git a/drivers/misc/vmware_balloon.c b/drivers/misc/vmware_balloon.c
index db9cd0240c6f..2a1e804a71aa 100644
--- a/drivers/misc/vmware_balloon.c
+++ b/drivers/misc/vmware_balloon.c
@@ -45,7 +45,7 @@
45 45
46MODULE_AUTHOR("VMware, Inc."); 46MODULE_AUTHOR("VMware, Inc.");
47MODULE_DESCRIPTION("VMware Memory Control (Balloon) Driver"); 47MODULE_DESCRIPTION("VMware Memory Control (Balloon) Driver");
48MODULE_VERSION("1.2.1.0-K"); 48MODULE_VERSION("1.2.1.1-k");
49MODULE_ALIAS("dmi:*:svnVMware*:*"); 49MODULE_ALIAS("dmi:*:svnVMware*:*");
50MODULE_ALIAS("vmware_vmmemctl"); 50MODULE_ALIAS("vmware_vmmemctl");
51MODULE_LICENSE("GPL"); 51MODULE_LICENSE("GPL");
@@ -101,6 +101,8 @@ MODULE_LICENSE("GPL");
101/* Maximum number of page allocations without yielding processor */ 101/* Maximum number of page allocations without yielding processor */
102#define VMW_BALLOON_YIELD_THRESHOLD 1024 102#define VMW_BALLOON_YIELD_THRESHOLD 1024
103 103
104/* Maximum number of refused pages we accumulate during inflation cycle */
105#define VMW_BALLOON_MAX_REFUSED 16
104 106
105/* 107/*
106 * Hypervisor communication port definitions. 108 * Hypervisor communication port definitions.
@@ -183,6 +185,7 @@ struct vmballoon {
183 185
184 /* transient list of non-balloonable pages */ 186 /* transient list of non-balloonable pages */
185 struct list_head refused_pages; 187 struct list_head refused_pages;
188 unsigned int n_refused_pages;
186 189
187 /* balloon size in pages */ 190 /* balloon size in pages */
188 unsigned int size; 191 unsigned int size;
@@ -428,14 +431,21 @@ static int vmballoon_reserve_page(struct vmballoon *b, bool can_sleep)
428 /* inform monitor */ 431 /* inform monitor */
429 locked = vmballoon_send_lock_page(b, page_to_pfn(page)); 432 locked = vmballoon_send_lock_page(b, page_to_pfn(page));
430 if (!locked) { 433 if (!locked) {
434 STATS_INC(b->stats.refused_alloc);
435
431 if (b->reset_required) { 436 if (b->reset_required) {
432 __free_page(page); 437 __free_page(page);
433 return -EIO; 438 return -EIO;
434 } 439 }
435 440
436 /* place on list of non-balloonable pages, retry allocation */ 441 /*
442 * Place page on the list of non-balloonable pages
443 * and retry allocation, unless we already accumulated
444 * too many of them, in which case take a breather.
445 */
437 list_add(&page->lru, &b->refused_pages); 446 list_add(&page->lru, &b->refused_pages);
438 STATS_INC(b->stats.refused_alloc); 447 if (++b->n_refused_pages >= VMW_BALLOON_MAX_REFUSED)
448 return -EIO;
439 } 449 }
440 } while (!locked); 450 } while (!locked);
441 451
@@ -483,6 +493,8 @@ static void vmballoon_release_refused_pages(struct vmballoon *b)
483 __free_page(page); 493 __free_page(page);
484 STATS_INC(b->stats.refused_free); 494 STATS_INC(b->stats.refused_free);
485 } 495 }
496
497 b->n_refused_pages = 0;
486} 498}
487 499
488/* 500/*
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 3168ebd616b2..569e94da844c 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1252,9 +1252,8 @@ EXPORT_SYMBOL(mmc_card_can_sleep);
1252/** 1252/**
1253 * mmc_suspend_host - suspend a host 1253 * mmc_suspend_host - suspend a host
1254 * @host: mmc host 1254 * @host: mmc host
1255 * @state: suspend mode (PM_SUSPEND_xxx)
1256 */ 1255 */
1257int mmc_suspend_host(struct mmc_host *host, pm_message_t state) 1256int mmc_suspend_host(struct mmc_host *host)
1258{ 1257{
1259 int err = 0; 1258 int err = 0;
1260 1259
diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c
index 0d96080d44b0..63772e7e7608 100644
--- a/drivers/mmc/core/sd_ops.c
+++ b/drivers/mmc/core/sd_ops.c
@@ -79,8 +79,6 @@ int mmc_wait_for_app_cmd(struct mmc_host *host, struct mmc_card *card,
79 * we cannot use the retries field in mmc_command. 79 * we cannot use the retries field in mmc_command.
80 */ 80 */
81 for (i = 0;i <= retries;i++) { 81 for (i = 0;i <= retries;i++) {
82 memset(&mrq, 0, sizeof(struct mmc_request));
83
84 err = mmc_app_cmd(host, card); 82 err = mmc_app_cmd(host, card);
85 if (err) { 83 if (err) {
86 /* no point in retrying; no APP commands allowed */ 84 /* no point in retrying; no APP commands allowed */
diff --git a/drivers/mmc/core/sdio_io.c b/drivers/mmc/core/sdio_io.c
index ff27c8c71355..0f687cdeb064 100644
--- a/drivers/mmc/core/sdio_io.c
+++ b/drivers/mmc/core/sdio_io.c
@@ -406,6 +406,36 @@ void sdio_writeb(struct sdio_func *func, u8 b, unsigned int addr, int *err_ret)
406EXPORT_SYMBOL_GPL(sdio_writeb); 406EXPORT_SYMBOL_GPL(sdio_writeb);
407 407
408/** 408/**
409 * sdio_writeb_readb - write and read a byte from SDIO function
410 * @func: SDIO function to access
411 * @write_byte: byte to write
412 * @addr: address to write to
413 * @err_ret: optional status value from transfer
414 *
415 * Performs a RAW (Read after Write) operation as defined by SDIO spec -
416 * single byte is written to address space of a given SDIO function and
417 * response is read back from the same address, both using single request.
418 * If there is a problem with the operation, 0xff is returned and
419 * @err_ret will contain the error code.
420 */
421u8 sdio_writeb_readb(struct sdio_func *func, u8 write_byte,
422 unsigned int addr, int *err_ret)
423{
424 int ret;
425 u8 val;
426
427 ret = mmc_io_rw_direct(func->card, 1, func->num, addr,
428 write_byte, &val);
429 if (err_ret)
430 *err_ret = ret;
431 if (ret)
432 val = 0xff;
433
434 return val;
435}
436EXPORT_SYMBOL_GPL(sdio_writeb_readb);
437
438/**
409 * sdio_memcpy_fromio - read a chunk of memory from a SDIO function 439 * sdio_memcpy_fromio - read a chunk of memory from a SDIO function
410 * @func: SDIO function to access 440 * @func: SDIO function to access
411 * @dst: buffer to store the data 441 * @dst: buffer to store the data
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 2e13b94769fd..f06d06e7fdfa 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -136,6 +136,18 @@ config MMC_SDHCI_S3C
136 136
137 If unsure, say N. 137 If unsure, say N.
138 138
139config MMC_SDHCI_SPEAR
140 tristate "SDHCI support on ST SPEAr platform"
141 depends on MMC_SDHCI && PLAT_SPEAR
142 help
143 This selects the Secure Digital Host Controller Interface (SDHCI)
144 often referrered to as the HSMMC block in some of the ST SPEAR range
145 of SoC
146
147 If you have a controller with this interface, say Y or M here.
148
149 If unsure, say N.
150
139config MMC_SDHCI_S3C_DMA 151config MMC_SDHCI_S3C_DMA
140 bool "DMA support on S3C SDHCI" 152 bool "DMA support on S3C SDHCI"
141 depends on MMC_SDHCI_S3C && EXPERIMENTAL 153 depends on MMC_SDHCI_S3C && EXPERIMENTAL
@@ -237,7 +249,7 @@ config MMC_IMX
237 249
238config MMC_MSM7X00A 250config MMC_MSM7X00A
239 tristate "Qualcomm MSM 7X00A SDCC Controller Support" 251 tristate "Qualcomm MSM 7X00A SDCC Controller Support"
240 depends on MMC && ARCH_MSM 252 depends on MMC && ARCH_MSM && !ARCH_MSM7X30
241 help 253 help
242 This provides support for the SD/MMC cell found in the 254 This provides support for the SD/MMC cell found in the
243 MSM 7X00A controllers from Qualcomm. 255 MSM 7X00A controllers from Qualcomm.
@@ -412,3 +424,11 @@ config SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND
412 depends on SDH_BFIN 424 depends on SDH_BFIN
413 help 425 help
414 If you say yes here SD-Cards may work on the EZkit. 426 If you say yes here SD-Cards may work on the EZkit.
427
428config MMC_SH_MMCIF
429 tristate "SuperH Internal MMCIF support"
430 depends on MMC_BLOCK && (SUPERH || ARCH_SHMOBILE)
431 help
432 This selects the MMC Host Interface controler (MMCIF).
433
434 This driver supports MMCIF in sh7724/sh7757/sh7372.
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index f4803977dfce..e30c2ee48894 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_MMC_SDHCI) += sdhci.o
14obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o 14obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o
15obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o 15obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o
16obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o 16obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o
17obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o
17obj-$(CONFIG_MMC_WBSD) += wbsd.o 18obj-$(CONFIG_MMC_WBSD) += wbsd.o
18obj-$(CONFIG_MMC_AU1X) += au1xmmc.o 19obj-$(CONFIG_MMC_AU1X) += au1xmmc.o
19obj-$(CONFIG_MMC_OMAP) += omap.o 20obj-$(CONFIG_MMC_OMAP) += omap.o
@@ -34,6 +35,7 @@ obj-$(CONFIG_MMC_TMIO) += tmio_mmc.o
34obj-$(CONFIG_MMC_CB710) += cb710-mmc.o 35obj-$(CONFIG_MMC_CB710) += cb710-mmc.o
35obj-$(CONFIG_MMC_VIA_SDMMC) += via-sdmmc.o 36obj-$(CONFIG_MMC_VIA_SDMMC) += via-sdmmc.o
36obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o 37obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o
38obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o
37 39
38obj-$(CONFIG_MMC_SDHCI_OF) += sdhci-of.o 40obj-$(CONFIG_MMC_SDHCI_OF) += sdhci-of.o
39sdhci-of-y := sdhci-of-core.o 41sdhci-of-y := sdhci-of-core.o
diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c
index 336d9f553f3e..5f3a599ead07 100644
--- a/drivers/mmc/host/at91_mci.c
+++ b/drivers/mmc/host/at91_mci.c
@@ -1157,7 +1157,7 @@ static int at91_mci_suspend(struct platform_device *pdev, pm_message_t state)
1157 enable_irq_wake(host->board->det_pin); 1157 enable_irq_wake(host->board->det_pin);
1158 1158
1159 if (mmc) 1159 if (mmc)
1160 ret = mmc_suspend_host(mmc, state); 1160 ret = mmc_suspend_host(mmc);
1161 1161
1162 return ret; 1162 return ret;
1163} 1163}
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index df0e8a88d85f..95ef864ad8f9 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -173,6 +173,7 @@ struct atmel_mci {
173 * @mmc: The mmc_host representing this slot. 173 * @mmc: The mmc_host representing this slot.
174 * @host: The MMC controller this slot is using. 174 * @host: The MMC controller this slot is using.
175 * @sdc_reg: Value of SDCR to be written before using this slot. 175 * @sdc_reg: Value of SDCR to be written before using this slot.
176 * @sdio_irq: SDIO irq mask for this slot.
176 * @mrq: mmc_request currently being processed or waiting to be 177 * @mrq: mmc_request currently being processed or waiting to be
177 * processed, or NULL when the slot is idle. 178 * processed, or NULL when the slot is idle.
178 * @queue_node: List node for placing this node in the @queue list of 179 * @queue_node: List node for placing this node in the @queue list of
@@ -191,6 +192,7 @@ struct atmel_mci_slot {
191 struct atmel_mci *host; 192 struct atmel_mci *host;
192 193
193 u32 sdc_reg; 194 u32 sdc_reg;
195 u32 sdio_irq;
194 196
195 struct mmc_request *mrq; 197 struct mmc_request *mrq;
196 struct list_head queue_node; 198 struct list_head queue_node;
@@ -792,7 +794,7 @@ static void atmci_start_request(struct atmel_mci *host,
792 mci_writel(host, SDCR, slot->sdc_reg); 794 mci_writel(host, SDCR, slot->sdc_reg);
793 795
794 iflags = mci_readl(host, IMR); 796 iflags = mci_readl(host, IMR);
795 if (iflags) 797 if (iflags & ~(MCI_SDIOIRQA | MCI_SDIOIRQB))
796 dev_warn(&slot->mmc->class_dev, "WARNING: IMR=0x%08x\n", 798 dev_warn(&slot->mmc->class_dev, "WARNING: IMR=0x%08x\n",
797 iflags); 799 iflags);
798 800
@@ -952,10 +954,21 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
952 if (mci_has_rwproof()) 954 if (mci_has_rwproof())
953 host->mode_reg |= (MCI_MR_WRPROOF | MCI_MR_RDPROOF); 955 host->mode_reg |= (MCI_MR_WRPROOF | MCI_MR_RDPROOF);
954 956
955 if (list_empty(&host->queue)) 957 if (atmci_is_mci2()) {
958 /* setup High Speed mode in relation with card capacity */
959 if (ios->timing == MMC_TIMING_SD_HS)
960 host->cfg_reg |= MCI_CFG_HSMODE;
961 else
962 host->cfg_reg &= ~MCI_CFG_HSMODE;
963 }
964
965 if (list_empty(&host->queue)) {
956 mci_writel(host, MR, host->mode_reg); 966 mci_writel(host, MR, host->mode_reg);
957 else 967 if (atmci_is_mci2())
968 mci_writel(host, CFG, host->cfg_reg);
969 } else {
958 host->need_clock_update = true; 970 host->need_clock_update = true;
971 }
959 972
960 spin_unlock_bh(&host->lock); 973 spin_unlock_bh(&host->lock);
961 } else { 974 } else {
@@ -1030,11 +1043,23 @@ static int atmci_get_cd(struct mmc_host *mmc)
1030 return present; 1043 return present;
1031} 1044}
1032 1045
1046static void atmci_enable_sdio_irq(struct mmc_host *mmc, int enable)
1047{
1048 struct atmel_mci_slot *slot = mmc_priv(mmc);
1049 struct atmel_mci *host = slot->host;
1050
1051 if (enable)
1052 mci_writel(host, IER, slot->sdio_irq);
1053 else
1054 mci_writel(host, IDR, slot->sdio_irq);
1055}
1056
1033static const struct mmc_host_ops atmci_ops = { 1057static const struct mmc_host_ops atmci_ops = {
1034 .request = atmci_request, 1058 .request = atmci_request,
1035 .set_ios = atmci_set_ios, 1059 .set_ios = atmci_set_ios,
1036 .get_ro = atmci_get_ro, 1060 .get_ro = atmci_get_ro,
1037 .get_cd = atmci_get_cd, 1061 .get_cd = atmci_get_cd,
1062 .enable_sdio_irq = atmci_enable_sdio_irq,
1038}; 1063};
1039 1064
1040/* Called with host->lock held */ 1065/* Called with host->lock held */
@@ -1052,8 +1077,11 @@ static void atmci_request_end(struct atmel_mci *host, struct mmc_request *mrq)
1052 * necessary if set_ios() is called when a different slot is 1077 * necessary if set_ios() is called when a different slot is
1053 * busy transfering data. 1078 * busy transfering data.
1054 */ 1079 */
1055 if (host->need_clock_update) 1080 if (host->need_clock_update) {
1056 mci_writel(host, MR, host->mode_reg); 1081 mci_writel(host, MR, host->mode_reg);
1082 if (atmci_is_mci2())
1083 mci_writel(host, CFG, host->cfg_reg);
1084 }
1057 1085
1058 host->cur_slot->mrq = NULL; 1086 host->cur_slot->mrq = NULL;
1059 host->mrq = NULL; 1087 host->mrq = NULL;
@@ -1483,6 +1511,19 @@ static void atmci_cmd_interrupt(struct atmel_mci *host, u32 status)
1483 tasklet_schedule(&host->tasklet); 1511 tasklet_schedule(&host->tasklet);
1484} 1512}
1485 1513
1514static void atmci_sdio_interrupt(struct atmel_mci *host, u32 status)
1515{
1516 int i;
1517
1518 for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) {
1519 struct atmel_mci_slot *slot = host->slot[i];
1520 if (slot && (status & slot->sdio_irq)) {
1521 mmc_signal_sdio_irq(slot->mmc);
1522 }
1523 }
1524}
1525
1526
1486static irqreturn_t atmci_interrupt(int irq, void *dev_id) 1527static irqreturn_t atmci_interrupt(int irq, void *dev_id)
1487{ 1528{
1488 struct atmel_mci *host = dev_id; 1529 struct atmel_mci *host = dev_id;
@@ -1522,6 +1563,10 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id)
1522 1563
1523 if (pending & MCI_CMDRDY) 1564 if (pending & MCI_CMDRDY)
1524 atmci_cmd_interrupt(host, status); 1565 atmci_cmd_interrupt(host, status);
1566
1567 if (pending & (MCI_SDIOIRQA | MCI_SDIOIRQB))
1568 atmci_sdio_interrupt(host, status);
1569
1525 } while (pass_count++ < 5); 1570 } while (pass_count++ < 5);
1526 1571
1527 return pass_count ? IRQ_HANDLED : IRQ_NONE; 1572 return pass_count ? IRQ_HANDLED : IRQ_NONE;
@@ -1544,7 +1589,7 @@ static irqreturn_t atmci_detect_interrupt(int irq, void *dev_id)
1544 1589
1545static int __init atmci_init_slot(struct atmel_mci *host, 1590static int __init atmci_init_slot(struct atmel_mci *host,
1546 struct mci_slot_pdata *slot_data, unsigned int id, 1591 struct mci_slot_pdata *slot_data, unsigned int id,
1547 u32 sdc_reg) 1592 u32 sdc_reg, u32 sdio_irq)
1548{ 1593{
1549 struct mmc_host *mmc; 1594 struct mmc_host *mmc;
1550 struct atmel_mci_slot *slot; 1595 struct atmel_mci_slot *slot;
@@ -1560,11 +1605,16 @@ static int __init atmci_init_slot(struct atmel_mci *host,
1560 slot->wp_pin = slot_data->wp_pin; 1605 slot->wp_pin = slot_data->wp_pin;
1561 slot->detect_is_active_high = slot_data->detect_is_active_high; 1606 slot->detect_is_active_high = slot_data->detect_is_active_high;
1562 slot->sdc_reg = sdc_reg; 1607 slot->sdc_reg = sdc_reg;
1608 slot->sdio_irq = sdio_irq;
1563 1609
1564 mmc->ops = &atmci_ops; 1610 mmc->ops = &atmci_ops;
1565 mmc->f_min = DIV_ROUND_UP(host->bus_hz, 512); 1611 mmc->f_min = DIV_ROUND_UP(host->bus_hz, 512);
1566 mmc->f_max = host->bus_hz / 2; 1612 mmc->f_max = host->bus_hz / 2;
1567 mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; 1613 mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
1614 if (sdio_irq)
1615 mmc->caps |= MMC_CAP_SDIO_IRQ;
1616 if (atmci_is_mci2())
1617 mmc->caps |= MMC_CAP_SD_HIGHSPEED;
1568 if (slot_data->bus_width >= 4) 1618 if (slot_data->bus_width >= 4)
1569 mmc->caps |= MMC_CAP_4_BIT_DATA; 1619 mmc->caps |= MMC_CAP_4_BIT_DATA;
1570 1620
@@ -1753,13 +1803,13 @@ static int __init atmci_probe(struct platform_device *pdev)
1753 ret = -ENODEV; 1803 ret = -ENODEV;
1754 if (pdata->slot[0].bus_width) { 1804 if (pdata->slot[0].bus_width) {
1755 ret = atmci_init_slot(host, &pdata->slot[0], 1805 ret = atmci_init_slot(host, &pdata->slot[0],
1756 0, MCI_SDCSEL_SLOT_A); 1806 0, MCI_SDCSEL_SLOT_A, MCI_SDIOIRQA);
1757 if (!ret) 1807 if (!ret)
1758 nr_slots++; 1808 nr_slots++;
1759 } 1809 }
1760 if (pdata->slot[1].bus_width) { 1810 if (pdata->slot[1].bus_width) {
1761 ret = atmci_init_slot(host, &pdata->slot[1], 1811 ret = atmci_init_slot(host, &pdata->slot[1],
1762 1, MCI_SDCSEL_SLOT_B); 1812 1, MCI_SDCSEL_SLOT_B, MCI_SDIOIRQB);
1763 if (!ret) 1813 if (!ret)
1764 nr_slots++; 1814 nr_slots++;
1765 } 1815 }
diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
index f5834449400e..c8da5d30a861 100644
--- a/drivers/mmc/host/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -1142,7 +1142,7 @@ static int au1xmmc_suspend(struct platform_device *pdev, pm_message_t state)
1142 struct au1xmmc_host *host = platform_get_drvdata(pdev); 1142 struct au1xmmc_host *host = platform_get_drvdata(pdev);
1143 int ret; 1143 int ret;
1144 1144
1145 ret = mmc_suspend_host(host->mmc, state); 1145 ret = mmc_suspend_host(host->mmc);
1146 if (ret) 1146 if (ret)
1147 return ret; 1147 return ret;
1148 1148
diff --git a/drivers/mmc/host/bfin_sdh.c b/drivers/mmc/host/bfin_sdh.c
index 6919e844072c..4b0e677d7295 100644
--- a/drivers/mmc/host/bfin_sdh.c
+++ b/drivers/mmc/host/bfin_sdh.c
@@ -576,7 +576,7 @@ static int sdh_suspend(struct platform_device *dev, pm_message_t state)
576 int ret = 0; 576 int ret = 0;
577 577
578 if (mmc) 578 if (mmc)
579 ret = mmc_suspend_host(mmc, state); 579 ret = mmc_suspend_host(mmc);
580 580
581 bfin_write_SDH_PWR_CTL(bfin_read_SDH_PWR_CTL() & ~PWR_ON); 581 bfin_write_SDH_PWR_CTL(bfin_read_SDH_PWR_CTL() & ~PWR_ON);
582 peripheral_free_list(drv_data->pin_req); 582 peripheral_free_list(drv_data->pin_req);
diff --git a/drivers/mmc/host/cb710-mmc.c b/drivers/mmc/host/cb710-mmc.c
index 92a324f7417c..ca3bdc831900 100644
--- a/drivers/mmc/host/cb710-mmc.c
+++ b/drivers/mmc/host/cb710-mmc.c
@@ -675,7 +675,7 @@ static int cb710_mmc_suspend(struct platform_device *pdev, pm_message_t state)
675 struct mmc_host *mmc = cb710_slot_to_mmc(slot); 675 struct mmc_host *mmc = cb710_slot_to_mmc(slot);
676 int err; 676 int err;
677 677
678 err = mmc_suspend_host(mmc, state); 678 err = mmc_suspend_host(mmc);
679 if (err) 679 if (err)
680 return err; 680 return err;
681 681
diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c
index 3bd0ba294e9d..33d9f1b00862 100644
--- a/drivers/mmc/host/davinci_mmc.c
+++ b/drivers/mmc/host/davinci_mmc.c
@@ -137,15 +137,15 @@
137 137
138/* 138/*
139 * One scatterlist dma "segment" is at most MAX_CCNT rw_threshold units, 139 * One scatterlist dma "segment" is at most MAX_CCNT rw_threshold units,
140 * and we handle up to NR_SG segments. MMC_BLOCK_BOUNCE kicks in only 140 * and we handle up to MAX_NR_SG segments. MMC_BLOCK_BOUNCE kicks in only
141 * for drivers with max_hw_segs == 1, making the segments bigger (64KB) 141 * for drivers with max_hw_segs == 1, making the segments bigger (64KB)
142 * than the page or two that's otherwise typical. NR_SG == 16 gives at 142 * than the page or two that's otherwise typical. nr_sg (passed from
143 * least the same throughput boost, using EDMA transfer linkage instead 143 * platform data) == 16 gives at least the same throughput boost, using
144 * of spending CPU time copying pages. 144 * EDMA transfer linkage instead of spending CPU time copying pages.
145 */ 145 */
146#define MAX_CCNT ((1 << 16) - 1) 146#define MAX_CCNT ((1 << 16) - 1)
147 147
148#define NR_SG 16 148#define MAX_NR_SG 16
149 149
150static unsigned rw_threshold = 32; 150static unsigned rw_threshold = 32;
151module_param(rw_threshold, uint, S_IRUGO); 151module_param(rw_threshold, uint, S_IRUGO);
@@ -171,6 +171,7 @@ struct mmc_davinci_host {
171#define DAVINCI_MMC_DATADIR_READ 1 171#define DAVINCI_MMC_DATADIR_READ 1
172#define DAVINCI_MMC_DATADIR_WRITE 2 172#define DAVINCI_MMC_DATADIR_WRITE 2
173 unsigned char data_dir; 173 unsigned char data_dir;
174 unsigned char suspended;
174 175
175 /* buffer is used during PIO of one scatterlist segment, and 176 /* buffer is used during PIO of one scatterlist segment, and
176 * is updated along with buffer_bytes_left. bytes_left applies 177 * is updated along with buffer_bytes_left. bytes_left applies
@@ -192,7 +193,7 @@ struct mmc_davinci_host {
192 struct edmacc_param tx_template; 193 struct edmacc_param tx_template;
193 struct edmacc_param rx_template; 194 struct edmacc_param rx_template;
194 unsigned n_link; 195 unsigned n_link;
195 u32 links[NR_SG - 1]; 196 u32 links[MAX_NR_SG - 1];
196 197
197 /* For PIO we walk scatterlists one segment at a time. */ 198 /* For PIO we walk scatterlists one segment at a time. */
198 unsigned int sg_len; 199 unsigned int sg_len;
@@ -202,6 +203,8 @@ struct mmc_davinci_host {
202 u8 version; 203 u8 version;
203 /* for ns in one cycle calculation */ 204 /* for ns in one cycle calculation */
204 unsigned ns_in_one_cycle; 205 unsigned ns_in_one_cycle;
206 /* Number of sg segments */
207 u8 nr_sg;
205#ifdef CONFIG_CPU_FREQ 208#ifdef CONFIG_CPU_FREQ
206 struct notifier_block freq_transition; 209 struct notifier_block freq_transition;
207#endif 210#endif
@@ -568,6 +571,7 @@ davinci_release_dma_channels(struct mmc_davinci_host *host)
568 571
569static int __init davinci_acquire_dma_channels(struct mmc_davinci_host *host) 572static int __init davinci_acquire_dma_channels(struct mmc_davinci_host *host)
570{ 573{
574 u32 link_size;
571 int r, i; 575 int r, i;
572 576
573 /* Acquire master DMA write channel */ 577 /* Acquire master DMA write channel */
@@ -593,7 +597,8 @@ static int __init davinci_acquire_dma_channels(struct mmc_davinci_host *host)
593 /* Allocate parameter RAM slots, which will later be bound to a 597 /* Allocate parameter RAM slots, which will later be bound to a
594 * channel as needed to handle a scatterlist. 598 * channel as needed to handle a scatterlist.
595 */ 599 */
596 for (i = 0; i < ARRAY_SIZE(host->links); i++) { 600 link_size = min_t(unsigned, host->nr_sg, ARRAY_SIZE(host->links));
601 for (i = 0; i < link_size; i++) {
597 r = edma_alloc_slot(EDMA_CTLR(host->txdma), EDMA_SLOT_ANY); 602 r = edma_alloc_slot(EDMA_CTLR(host->txdma), EDMA_SLOT_ANY);
598 if (r < 0) { 603 if (r < 0) {
599 dev_dbg(mmc_dev(host->mmc), "dma PaRAM alloc --> %d\n", 604 dev_dbg(mmc_dev(host->mmc), "dma PaRAM alloc --> %d\n",
@@ -905,19 +910,26 @@ static void mmc_davinci_cmd_done(struct mmc_davinci_host *host,
905 } 910 }
906} 911}
907 912
908static void 913static inline void mmc_davinci_reset_ctrl(struct mmc_davinci_host *host,
909davinci_abort_data(struct mmc_davinci_host *host, struct mmc_data *data) 914 int val)
910{ 915{
911 u32 temp; 916 u32 temp;
912 917
913 /* reset command and data state machines */
914 temp = readl(host->base + DAVINCI_MMCCTL); 918 temp = readl(host->base + DAVINCI_MMCCTL);
915 writel(temp | MMCCTL_CMDRST | MMCCTL_DATRST, 919 if (val) /* reset */
916 host->base + DAVINCI_MMCCTL); 920 temp |= MMCCTL_CMDRST | MMCCTL_DATRST;
921 else /* enable */
922 temp &= ~(MMCCTL_CMDRST | MMCCTL_DATRST);
917 923
918 temp &= ~(MMCCTL_CMDRST | MMCCTL_DATRST);
919 udelay(10);
920 writel(temp, host->base + DAVINCI_MMCCTL); 924 writel(temp, host->base + DAVINCI_MMCCTL);
925 udelay(10);
926}
927
928static void
929davinci_abort_data(struct mmc_davinci_host *host, struct mmc_data *data)
930{
931 mmc_davinci_reset_ctrl(host, 1);
932 mmc_davinci_reset_ctrl(host, 0);
921} 933}
922 934
923static irqreturn_t mmc_davinci_irq(int irq, void *dev_id) 935static irqreturn_t mmc_davinci_irq(int irq, void *dev_id)
@@ -1121,15 +1133,8 @@ static inline void mmc_davinci_cpufreq_deregister(struct mmc_davinci_host *host)
1121#endif 1133#endif
1122static void __init init_mmcsd_host(struct mmc_davinci_host *host) 1134static void __init init_mmcsd_host(struct mmc_davinci_host *host)
1123{ 1135{
1124 /* DAT line portion is diabled and in reset state */
1125 writel(readl(host->base + DAVINCI_MMCCTL) | MMCCTL_DATRST,
1126 host->base + DAVINCI_MMCCTL);
1127
1128 /* CMD line portion is diabled and in reset state */
1129 writel(readl(host->base + DAVINCI_MMCCTL) | MMCCTL_CMDRST,
1130 host->base + DAVINCI_MMCCTL);
1131 1136
1132 udelay(10); 1137 mmc_davinci_reset_ctrl(host, 1);
1133 1138
1134 writel(0, host->base + DAVINCI_MMCCLK); 1139 writel(0, host->base + DAVINCI_MMCCLK);
1135 writel(MMCCLK_CLKEN, host->base + DAVINCI_MMCCLK); 1140 writel(MMCCLK_CLKEN, host->base + DAVINCI_MMCCLK);
@@ -1137,12 +1142,7 @@ static void __init init_mmcsd_host(struct mmc_davinci_host *host)
1137 writel(0x1FFF, host->base + DAVINCI_MMCTOR); 1142 writel(0x1FFF, host->base + DAVINCI_MMCTOR);
1138 writel(0xFFFF, host->base + DAVINCI_MMCTOD); 1143 writel(0xFFFF, host->base + DAVINCI_MMCTOD);
1139 1144
1140 writel(readl(host->base + DAVINCI_MMCCTL) & ~MMCCTL_DATRST, 1145 mmc_davinci_reset_ctrl(host, 0);
1141 host->base + DAVINCI_MMCCTL);
1142 writel(readl(host->base + DAVINCI_MMCCTL) & ~MMCCTL_CMDRST,
1143 host->base + DAVINCI_MMCCTL);
1144
1145 udelay(10);
1146} 1146}
1147 1147
1148static int __init davinci_mmcsd_probe(struct platform_device *pdev) 1148static int __init davinci_mmcsd_probe(struct platform_device *pdev)
@@ -1202,6 +1202,12 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev)
1202 1202
1203 init_mmcsd_host(host); 1203 init_mmcsd_host(host);
1204 1204
1205 if (pdata->nr_sg)
1206 host->nr_sg = pdata->nr_sg - 1;
1207
1208 if (host->nr_sg > MAX_NR_SG || !host->nr_sg)
1209 host->nr_sg = MAX_NR_SG;
1210
1205 host->use_dma = use_dma; 1211 host->use_dma = use_dma;
1206 host->irq = irq; 1212 host->irq = irq;
1207 1213
@@ -1327,32 +1333,65 @@ static int __exit davinci_mmcsd_remove(struct platform_device *pdev)
1327} 1333}
1328 1334
1329#ifdef CONFIG_PM 1335#ifdef CONFIG_PM
1330static int davinci_mmcsd_suspend(struct platform_device *pdev, pm_message_t msg) 1336static int davinci_mmcsd_suspend(struct device *dev)
1331{ 1337{
1338 struct platform_device *pdev = to_platform_device(dev);
1332 struct mmc_davinci_host *host = platform_get_drvdata(pdev); 1339 struct mmc_davinci_host *host = platform_get_drvdata(pdev);
1340 int ret;
1333 1341
1334 return mmc_suspend_host(host->mmc, msg); 1342 mmc_host_enable(host->mmc);
1343 ret = mmc_suspend_host(host->mmc);
1344 if (!ret) {
1345 writel(0, host->base + DAVINCI_MMCIM);
1346 mmc_davinci_reset_ctrl(host, 1);
1347 mmc_host_disable(host->mmc);
1348 clk_disable(host->clk);
1349 host->suspended = 1;
1350 } else {
1351 host->suspended = 0;
1352 mmc_host_disable(host->mmc);
1353 }
1354
1355 return ret;
1335} 1356}
1336 1357
1337static int davinci_mmcsd_resume(struct platform_device *pdev) 1358static int davinci_mmcsd_resume(struct device *dev)
1338{ 1359{
1360 struct platform_device *pdev = to_platform_device(dev);
1339 struct mmc_davinci_host *host = platform_get_drvdata(pdev); 1361 struct mmc_davinci_host *host = platform_get_drvdata(pdev);
1362 int ret;
1363
1364 if (!host->suspended)
1365 return 0;
1340 1366
1341 return mmc_resume_host(host->mmc); 1367 clk_enable(host->clk);
1368 mmc_host_enable(host->mmc);
1369
1370 mmc_davinci_reset_ctrl(host, 0);
1371 ret = mmc_resume_host(host->mmc);
1372 if (!ret)
1373 host->suspended = 0;
1374
1375 return ret;
1342} 1376}
1377
1378static const struct dev_pm_ops davinci_mmcsd_pm = {
1379 .suspend = davinci_mmcsd_suspend,
1380 .resume = davinci_mmcsd_resume,
1381};
1382
1383#define davinci_mmcsd_pm_ops (&davinci_mmcsd_pm)
1343#else 1384#else
1344#define davinci_mmcsd_suspend NULL 1385#define davinci_mmcsd_pm_ops NULL
1345#define davinci_mmcsd_resume NULL
1346#endif 1386#endif
1347 1387
1348static struct platform_driver davinci_mmcsd_driver = { 1388static struct platform_driver davinci_mmcsd_driver = {
1349 .driver = { 1389 .driver = {
1350 .name = "davinci_mmc", 1390 .name = "davinci_mmc",
1351 .owner = THIS_MODULE, 1391 .owner = THIS_MODULE,
1392 .pm = davinci_mmcsd_pm_ops,
1352 }, 1393 },
1353 .remove = __exit_p(davinci_mmcsd_remove), 1394 .remove = __exit_p(davinci_mmcsd_remove),
1354 .suspend = davinci_mmcsd_suspend,
1355 .resume = davinci_mmcsd_resume,
1356}; 1395};
1357 1396
1358static int __init davinci_mmcsd_init(void) 1397static int __init davinci_mmcsd_init(void)
diff --git a/drivers/mmc/host/imxmmc.c b/drivers/mmc/host/imxmmc.c
index bf98d7cc928a..9a68ff4353a2 100644
--- a/drivers/mmc/host/imxmmc.c
+++ b/drivers/mmc/host/imxmmc.c
@@ -1115,7 +1115,7 @@ static int imxmci_suspend(struct platform_device *dev, pm_message_t state)
1115 int ret = 0; 1115 int ret = 0;
1116 1116
1117 if (mmc) 1117 if (mmc)
1118 ret = mmc_suspend_host(mmc, state); 1118 ret = mmc_suspend_host(mmc);
1119 1119
1120 return ret; 1120 return ret;
1121} 1121}
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index ff115d920888..4917af96bae1 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -824,7 +824,7 @@ static int mmci_suspend(struct amba_device *dev, pm_message_t state)
824 if (mmc) { 824 if (mmc) {
825 struct mmci_host *host = mmc_priv(mmc); 825 struct mmci_host *host = mmc_priv(mmc);
826 826
827 ret = mmc_suspend_host(mmc, state); 827 ret = mmc_suspend_host(mmc);
828 if (ret == 0) 828 if (ret == 0)
829 writel(0, host->base + MMCIMASK0); 829 writel(0, host->base + MMCIMASK0);
830 } 830 }
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 61f1d27fed3f..24e09454e522 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -1327,7 +1327,7 @@ msmsdcc_suspend(struct platform_device *dev, pm_message_t state)
1327 disable_irq(host->stat_irq); 1327 disable_irq(host->stat_irq);
1328 1328
1329 if (mmc->card && mmc->card->type != MMC_TYPE_SDIO) 1329 if (mmc->card && mmc->card->type != MMC_TYPE_SDIO)
1330 rc = mmc_suspend_host(mmc, state); 1330 rc = mmc_suspend_host(mmc);
1331 if (!rc) 1331 if (!rc)
1332 msmsdcc_writel(host, 0, MMCIMASK0); 1332 msmsdcc_writel(host, 0, MMCIMASK0);
1333 if (host->clks_on) 1333 if (host->clks_on)
diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c
index 34e23489811a..366eefa77c5a 100644
--- a/drivers/mmc/host/mvsdio.c
+++ b/drivers/mmc/host/mvsdio.c
@@ -865,7 +865,7 @@ static int mvsd_suspend(struct platform_device *dev, pm_message_t state)
865 int ret = 0; 865 int ret = 0;
866 866
867 if (mmc) 867 if (mmc)
868 ret = mmc_suspend_host(mmc, state); 868 ret = mmc_suspend_host(mmc);
869 869
870 return ret; 870 return ret;
871} 871}
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c
index ec18e3b60342..d9d4a72e0ec7 100644
--- a/drivers/mmc/host/mxcmmc.c
+++ b/drivers/mmc/host/mxcmmc.c
@@ -932,7 +932,7 @@ static int mxcmci_suspend(struct platform_device *dev, pm_message_t state)
932 int ret = 0; 932 int ret = 0;
933 933
934 if (mmc) 934 if (mmc)
935 ret = mmc_suspend_host(mmc, state); 935 ret = mmc_suspend_host(mmc);
936 936
937 return ret; 937 return ret;
938} 938}
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index 84d280406341..d98ddcfac5e5 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -39,30 +39,30 @@
39#include <plat/fpga.h> 39#include <plat/fpga.h>
40 40
41#define OMAP_MMC_REG_CMD 0x00 41#define OMAP_MMC_REG_CMD 0x00
42#define OMAP_MMC_REG_ARGL 0x04 42#define OMAP_MMC_REG_ARGL 0x01
43#define OMAP_MMC_REG_ARGH 0x08 43#define OMAP_MMC_REG_ARGH 0x02
44#define OMAP_MMC_REG_CON 0x0c 44#define OMAP_MMC_REG_CON 0x03
45#define OMAP_MMC_REG_STAT 0x10 45#define OMAP_MMC_REG_STAT 0x04
46#define OMAP_MMC_REG_IE 0x14 46#define OMAP_MMC_REG_IE 0x05
47#define OMAP_MMC_REG_CTO 0x18 47#define OMAP_MMC_REG_CTO 0x06
48#define OMAP_MMC_REG_DTO 0x1c 48#define OMAP_MMC_REG_DTO 0x07
49#define OMAP_MMC_REG_DATA 0x20 49#define OMAP_MMC_REG_DATA 0x08
50#define OMAP_MMC_REG_BLEN 0x24 50#define OMAP_MMC_REG_BLEN 0x09
51#define OMAP_MMC_REG_NBLK 0x28 51#define OMAP_MMC_REG_NBLK 0x0a
52#define OMAP_MMC_REG_BUF 0x2c 52#define OMAP_MMC_REG_BUF 0x0b
53#define OMAP_MMC_REG_SDIO 0x34 53#define OMAP_MMC_REG_SDIO 0x0d
54#define OMAP_MMC_REG_REV 0x3c 54#define OMAP_MMC_REG_REV 0x0f
55#define OMAP_MMC_REG_RSP0 0x40 55#define OMAP_MMC_REG_RSP0 0x10
56#define OMAP_MMC_REG_RSP1 0x44 56#define OMAP_MMC_REG_RSP1 0x11
57#define OMAP_MMC_REG_RSP2 0x48 57#define OMAP_MMC_REG_RSP2 0x12
58#define OMAP_MMC_REG_RSP3 0x4c 58#define OMAP_MMC_REG_RSP3 0x13
59#define OMAP_MMC_REG_RSP4 0x50 59#define OMAP_MMC_REG_RSP4 0x14
60#define OMAP_MMC_REG_RSP5 0x54 60#define OMAP_MMC_REG_RSP5 0x15
61#define OMAP_MMC_REG_RSP6 0x58 61#define OMAP_MMC_REG_RSP6 0x16
62#define OMAP_MMC_REG_RSP7 0x5c 62#define OMAP_MMC_REG_RSP7 0x17
63#define OMAP_MMC_REG_IOSR 0x60 63#define OMAP_MMC_REG_IOSR 0x18
64#define OMAP_MMC_REG_SYSC 0x64 64#define OMAP_MMC_REG_SYSC 0x19
65#define OMAP_MMC_REG_SYSS 0x68 65#define OMAP_MMC_REG_SYSS 0x1a
66 66
67#define OMAP_MMC_STAT_CARD_ERR (1 << 14) 67#define OMAP_MMC_STAT_CARD_ERR (1 << 14)
68#define OMAP_MMC_STAT_CARD_IRQ (1 << 13) 68#define OMAP_MMC_STAT_CARD_IRQ (1 << 13)
@@ -78,8 +78,9 @@
78#define OMAP_MMC_STAT_CARD_BUSY (1 << 2) 78#define OMAP_MMC_STAT_CARD_BUSY (1 << 2)
79#define OMAP_MMC_STAT_END_OF_CMD (1 << 0) 79#define OMAP_MMC_STAT_END_OF_CMD (1 << 0)
80 80
81#define OMAP_MMC_READ(host, reg) __raw_readw((host)->virt_base + OMAP_MMC_REG_##reg) 81#define OMAP_MMC_REG(host, reg) (OMAP_MMC_REG_##reg << (host)->reg_shift)
82#define OMAP_MMC_WRITE(host, reg, val) __raw_writew((val), (host)->virt_base + OMAP_MMC_REG_##reg) 82#define OMAP_MMC_READ(host, reg) __raw_readw((host)->virt_base + OMAP_MMC_REG(host, reg))
83#define OMAP_MMC_WRITE(host, reg, val) __raw_writew((val), (host)->virt_base + OMAP_MMC_REG(host, reg))
83 84
84/* 85/*
85 * Command types 86 * Command types
@@ -133,6 +134,7 @@ struct mmc_omap_host {
133 int irq; 134 int irq;
134 unsigned char bus_mode; 135 unsigned char bus_mode;
135 unsigned char hw_bus_mode; 136 unsigned char hw_bus_mode;
137 unsigned int reg_shift;
136 138
137 struct work_struct cmd_abort_work; 139 struct work_struct cmd_abort_work;
138 unsigned abort:1; 140 unsigned abort:1;
@@ -680,9 +682,9 @@ mmc_omap_xfer_data(struct mmc_omap_host *host, int write)
680 host->data->bytes_xfered += n; 682 host->data->bytes_xfered += n;
681 683
682 if (write) { 684 if (write) {
683 __raw_writesw(host->virt_base + OMAP_MMC_REG_DATA, host->buffer, n); 685 __raw_writesw(host->virt_base + OMAP_MMC_REG(host, DATA), host->buffer, n);
684 } else { 686 } else {
685 __raw_readsw(host->virt_base + OMAP_MMC_REG_DATA, host->buffer, n); 687 __raw_readsw(host->virt_base + OMAP_MMC_REG(host, DATA), host->buffer, n);
686 } 688 }
687} 689}
688 690
@@ -900,7 +902,7 @@ mmc_omap_prepare_dma(struct mmc_omap_host *host, struct mmc_data *data)
900 int dst_port = 0; 902 int dst_port = 0;
901 int sync_dev = 0; 903 int sync_dev = 0;
902 904
903 data_addr = host->phys_base + OMAP_MMC_REG_DATA; 905 data_addr = host->phys_base + OMAP_MMC_REG(host, DATA);
904 frame = data->blksz; 906 frame = data->blksz;
905 count = sg_dma_len(sg); 907 count = sg_dma_len(sg);
906 908
@@ -1155,7 +1157,6 @@ static void mmc_omap_start_request(struct mmc_omap_host *host,
1155 mmc_omap_start_command(host, req->cmd); 1157 mmc_omap_start_command(host, req->cmd);
1156 if (host->dma_in_use) 1158 if (host->dma_in_use)
1157 omap_start_dma(host->dma_ch); 1159 omap_start_dma(host->dma_ch);
1158 BUG_ON(irqs_disabled());
1159} 1160}
1160 1161
1161static void mmc_omap_request(struct mmc_host *mmc, struct mmc_request *req) 1162static void mmc_omap_request(struct mmc_host *mmc, struct mmc_request *req)
@@ -1493,6 +1494,8 @@ static int __init mmc_omap_probe(struct platform_device *pdev)
1493 } 1494 }
1494 } 1495 }
1495 1496
1497 host->reg_shift = (cpu_is_omap7xx() ? 1 : 2);
1498
1496 return 0; 1499 return 0;
1497 1500
1498err_plat_cleanup: 1501err_plat_cleanup:
@@ -1557,7 +1560,7 @@ static int mmc_omap_suspend(struct platform_device *pdev, pm_message_t mesg)
1557 struct mmc_omap_slot *slot; 1560 struct mmc_omap_slot *slot;
1558 1561
1559 slot = host->slots[i]; 1562 slot = host->slots[i];
1560 ret = mmc_suspend_host(slot->mmc, mesg); 1563 ret = mmc_suspend_host(slot->mmc);
1561 if (ret < 0) { 1564 if (ret < 0) {
1562 while (--i >= 0) { 1565 while (--i >= 0) {
1563 slot = host->slots[i]; 1566 slot = host->slots[i];
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index e9caf694c59e..b032828c6126 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -157,12 +157,10 @@ struct omap_hsmmc_host {
157 */ 157 */
158 struct regulator *vcc; 158 struct regulator *vcc;
159 struct regulator *vcc_aux; 159 struct regulator *vcc_aux;
160 struct semaphore sem;
161 struct work_struct mmc_carddetect_work; 160 struct work_struct mmc_carddetect_work;
162 void __iomem *base; 161 void __iomem *base;
163 resource_size_t mapbase; 162 resource_size_t mapbase;
164 spinlock_t irq_lock; /* Prevent races with irq handler */ 163 spinlock_t irq_lock; /* Prevent races with irq handler */
165 unsigned long flags;
166 unsigned int id; 164 unsigned int id;
167 unsigned int dma_len; 165 unsigned int dma_len;
168 unsigned int dma_sg_idx; 166 unsigned int dma_sg_idx;
@@ -183,6 +181,7 @@ struct omap_hsmmc_host {
183 int protect_card; 181 int protect_card;
184 int reqs_blocked; 182 int reqs_blocked;
185 int use_reg; 183 int use_reg;
184 int req_in_progress;
186 185
187 struct omap_mmc_platform_data *pdata; 186 struct omap_mmc_platform_data *pdata;
188}; 187};
@@ -524,6 +523,27 @@ static void omap_hsmmc_stop_clock(struct omap_hsmmc_host *host)
524 dev_dbg(mmc_dev(host->mmc), "MMC Clock is not stoped\n"); 523 dev_dbg(mmc_dev(host->mmc), "MMC Clock is not stoped\n");
525} 524}
526 525
526static void omap_hsmmc_enable_irq(struct omap_hsmmc_host *host)
527{
528 unsigned int irq_mask;
529
530 if (host->use_dma)
531 irq_mask = INT_EN_MASK & ~(BRR_ENABLE | BWR_ENABLE);
532 else
533 irq_mask = INT_EN_MASK;
534
535 OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
536 OMAP_HSMMC_WRITE(host->base, ISE, irq_mask);
537 OMAP_HSMMC_WRITE(host->base, IE, irq_mask);
538}
539
540static void omap_hsmmc_disable_irq(struct omap_hsmmc_host *host)
541{
542 OMAP_HSMMC_WRITE(host->base, ISE, 0);
543 OMAP_HSMMC_WRITE(host->base, IE, 0);
544 OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
545}
546
527#ifdef CONFIG_PM 547#ifdef CONFIG_PM
528 548
529/* 549/*
@@ -592,9 +612,7 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host)
592 && time_before(jiffies, timeout)) 612 && time_before(jiffies, timeout))
593 ; 613 ;
594 614
595 OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR); 615 omap_hsmmc_disable_irq(host);
596 OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK);
597 OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK);
598 616
599 /* Do not initialize card-specific things if the power is off */ 617 /* Do not initialize card-specific things if the power is off */
600 if (host->power_mode == MMC_POWER_OFF) 618 if (host->power_mode == MMC_POWER_OFF)
@@ -697,6 +715,8 @@ static void send_init_stream(struct omap_hsmmc_host *host)
697 return; 715 return;
698 716
699 disable_irq(host->irq); 717 disable_irq(host->irq);
718
719 OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK);
700 OMAP_HSMMC_WRITE(host->base, CON, 720 OMAP_HSMMC_WRITE(host->base, CON,
701 OMAP_HSMMC_READ(host->base, CON) | INIT_STREAM); 721 OMAP_HSMMC_READ(host->base, CON) | INIT_STREAM);
702 OMAP_HSMMC_WRITE(host->base, CMD, INIT_STREAM_CMD); 722 OMAP_HSMMC_WRITE(host->base, CMD, INIT_STREAM_CMD);
@@ -762,17 +782,7 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd,
762 mmc_hostname(host->mmc), cmd->opcode, cmd->arg); 782 mmc_hostname(host->mmc), cmd->opcode, cmd->arg);
763 host->cmd = cmd; 783 host->cmd = cmd;
764 784
765 /* 785 omap_hsmmc_enable_irq(host);
766 * Clear status bits and enable interrupts
767 */
768 OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
769 OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK);
770
771 if (host->use_dma)
772 OMAP_HSMMC_WRITE(host->base, IE,
773 INT_EN_MASK & ~(BRR_ENABLE | BWR_ENABLE));
774 else
775 OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK);
776 786
777 host->response_busy = 0; 787 host->response_busy = 0;
778 if (cmd->flags & MMC_RSP_PRESENT) { 788 if (cmd->flags & MMC_RSP_PRESENT) {
@@ -806,13 +816,7 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd,
806 if (host->use_dma) 816 if (host->use_dma)
807 cmdreg |= DMA_EN; 817 cmdreg |= DMA_EN;
808 818
809 /* 819 host->req_in_progress = 1;
810 * In an interrupt context (i.e. STOP command), the spinlock is unlocked
811 * by the interrupt handler, otherwise (i.e. for a new request) it is
812 * unlocked here.
813 */
814 if (!in_interrupt())
815 spin_unlock_irqrestore(&host->irq_lock, host->flags);
816 820
817 OMAP_HSMMC_WRITE(host->base, ARG, cmd->arg); 821 OMAP_HSMMC_WRITE(host->base, ARG, cmd->arg);
818 OMAP_HSMMC_WRITE(host->base, CMD, cmdreg); 822 OMAP_HSMMC_WRITE(host->base, CMD, cmdreg);
@@ -827,6 +831,23 @@ omap_hsmmc_get_dma_dir(struct omap_hsmmc_host *host, struct mmc_data *data)
827 return DMA_FROM_DEVICE; 831 return DMA_FROM_DEVICE;
828} 832}
829 833
834static void omap_hsmmc_request_done(struct omap_hsmmc_host *host, struct mmc_request *mrq)
835{
836 int dma_ch;
837
838 spin_lock(&host->irq_lock);
839 host->req_in_progress = 0;
840 dma_ch = host->dma_ch;
841 spin_unlock(&host->irq_lock);
842
843 omap_hsmmc_disable_irq(host);
844 /* Do not complete the request if DMA is still in progress */
845 if (mrq->data && host->use_dma && dma_ch != -1)
846 return;
847 host->mrq = NULL;
848 mmc_request_done(host->mmc, mrq);
849}
850
830/* 851/*
831 * Notify the transfer complete to MMC core 852 * Notify the transfer complete to MMC core
832 */ 853 */
@@ -843,25 +864,19 @@ omap_hsmmc_xfer_done(struct omap_hsmmc_host *host, struct mmc_data *data)
843 return; 864 return;
844 } 865 }
845 866
846 host->mrq = NULL; 867 omap_hsmmc_request_done(host, mrq);
847 mmc_request_done(host->mmc, mrq);
848 return; 868 return;
849 } 869 }
850 870
851 host->data = NULL; 871 host->data = NULL;
852 872
853 if (host->use_dma && host->dma_ch != -1)
854 dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len,
855 omap_hsmmc_get_dma_dir(host, data));
856
857 if (!data->error) 873 if (!data->error)
858 data->bytes_xfered += data->blocks * (data->blksz); 874 data->bytes_xfered += data->blocks * (data->blksz);
859 else 875 else
860 data->bytes_xfered = 0; 876 data->bytes_xfered = 0;
861 877
862 if (!data->stop) { 878 if (!data->stop) {
863 host->mrq = NULL; 879 omap_hsmmc_request_done(host, data->mrq);
864 mmc_request_done(host->mmc, data->mrq);
865 return; 880 return;
866 } 881 }
867 omap_hsmmc_start_command(host, data->stop, NULL); 882 omap_hsmmc_start_command(host, data->stop, NULL);
@@ -887,10 +902,8 @@ omap_hsmmc_cmd_done(struct omap_hsmmc_host *host, struct mmc_command *cmd)
887 cmd->resp[0] = OMAP_HSMMC_READ(host->base, RSP10); 902 cmd->resp[0] = OMAP_HSMMC_READ(host->base, RSP10);
888 } 903 }
889 } 904 }
890 if ((host->data == NULL && !host->response_busy) || cmd->error) { 905 if ((host->data == NULL && !host->response_busy) || cmd->error)
891 host->mrq = NULL; 906 omap_hsmmc_request_done(host, cmd->mrq);
892 mmc_request_done(host->mmc, cmd->mrq);
893 }
894} 907}
895 908
896/* 909/*
@@ -898,14 +911,19 @@ omap_hsmmc_cmd_done(struct omap_hsmmc_host *host, struct mmc_command *cmd)
898 */ 911 */
899static void omap_hsmmc_dma_cleanup(struct omap_hsmmc_host *host, int errno) 912static void omap_hsmmc_dma_cleanup(struct omap_hsmmc_host *host, int errno)
900{ 913{
914 int dma_ch;
915
901 host->data->error = errno; 916 host->data->error = errno;
902 917
903 if (host->use_dma && host->dma_ch != -1) { 918 spin_lock(&host->irq_lock);
919 dma_ch = host->dma_ch;
920 host->dma_ch = -1;
921 spin_unlock(&host->irq_lock);
922
923 if (host->use_dma && dma_ch != -1) {
904 dma_unmap_sg(mmc_dev(host->mmc), host->data->sg, host->dma_len, 924 dma_unmap_sg(mmc_dev(host->mmc), host->data->sg, host->dma_len,
905 omap_hsmmc_get_dma_dir(host, host->data)); 925 omap_hsmmc_get_dma_dir(host, host->data));
906 omap_free_dma(host->dma_ch); 926 omap_free_dma(dma_ch);
907 host->dma_ch = -1;
908 up(&host->sem);
909 } 927 }
910 host->data = NULL; 928 host->data = NULL;
911} 929}
@@ -967,28 +985,21 @@ static inline void omap_hsmmc_reset_controller_fsm(struct omap_hsmmc_host *host,
967 __func__); 985 __func__);
968} 986}
969 987
970/* 988static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status)
971 * MMC controller IRQ handler
972 */
973static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id)
974{ 989{
975 struct omap_hsmmc_host *host = dev_id;
976 struct mmc_data *data; 990 struct mmc_data *data;
977 int end_cmd = 0, end_trans = 0, status; 991 int end_cmd = 0, end_trans = 0;
978 992
979 spin_lock(&host->irq_lock); 993 if (!host->req_in_progress) {
980 994 do {
981 if (host->mrq == NULL) { 995 OMAP_HSMMC_WRITE(host->base, STAT, status);
982 OMAP_HSMMC_WRITE(host->base, STAT, 996 /* Flush posted write */
983 OMAP_HSMMC_READ(host->base, STAT)); 997 status = OMAP_HSMMC_READ(host->base, STAT);
984 /* Flush posted write */ 998 } while (status & INT_EN_MASK);
985 OMAP_HSMMC_READ(host->base, STAT); 999 return;
986 spin_unlock(&host->irq_lock);
987 return IRQ_HANDLED;
988 } 1000 }
989 1001
990 data = host->data; 1002 data = host->data;
991 status = OMAP_HSMMC_READ(host->base, STAT);
992 dev_dbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status); 1003 dev_dbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status);
993 1004
994 if (status & ERR) { 1005 if (status & ERR) {
@@ -1041,15 +1052,27 @@ static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id)
1041 } 1052 }
1042 1053
1043 OMAP_HSMMC_WRITE(host->base, STAT, status); 1054 OMAP_HSMMC_WRITE(host->base, STAT, status);
1044 /* Flush posted write */
1045 OMAP_HSMMC_READ(host->base, STAT);
1046 1055
1047 if (end_cmd || ((status & CC) && host->cmd)) 1056 if (end_cmd || ((status & CC) && host->cmd))
1048 omap_hsmmc_cmd_done(host, host->cmd); 1057 omap_hsmmc_cmd_done(host, host->cmd);
1049 if ((end_trans || (status & TC)) && host->mrq) 1058 if ((end_trans || (status & TC)) && host->mrq)
1050 omap_hsmmc_xfer_done(host, data); 1059 omap_hsmmc_xfer_done(host, data);
1060}
1051 1061
1052 spin_unlock(&host->irq_lock); 1062/*
1063 * MMC controller IRQ handler
1064 */
1065static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id)
1066{
1067 struct omap_hsmmc_host *host = dev_id;
1068 int status;
1069
1070 status = OMAP_HSMMC_READ(host->base, STAT);
1071 do {
1072 omap_hsmmc_do_irq(host, status);
1073 /* Flush posted write */
1074 status = OMAP_HSMMC_READ(host->base, STAT);
1075 } while (status & INT_EN_MASK);
1053 1076
1054 return IRQ_HANDLED; 1077 return IRQ_HANDLED;
1055} 1078}
@@ -1244,31 +1267,47 @@ static void omap_hsmmc_config_dma_params(struct omap_hsmmc_host *host,
1244/* 1267/*
1245 * DMA call back function 1268 * DMA call back function
1246 */ 1269 */
1247static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *data) 1270static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *cb_data)
1248{ 1271{
1249 struct omap_hsmmc_host *host = data; 1272 struct omap_hsmmc_host *host = cb_data;
1273 struct mmc_data *data = host->mrq->data;
1274 int dma_ch, req_in_progress;
1250 1275
1251 if (ch_status & OMAP2_DMA_MISALIGNED_ERR_IRQ) 1276 if (ch_status & OMAP2_DMA_MISALIGNED_ERR_IRQ)
1252 dev_dbg(mmc_dev(host->mmc), "MISALIGNED_ADRS_ERR\n"); 1277 dev_dbg(mmc_dev(host->mmc), "MISALIGNED_ADRS_ERR\n");
1253 1278
1254 if (host->dma_ch < 0) 1279 spin_lock(&host->irq_lock);
1280 if (host->dma_ch < 0) {
1281 spin_unlock(&host->irq_lock);
1255 return; 1282 return;
1283 }
1256 1284
1257 host->dma_sg_idx++; 1285 host->dma_sg_idx++;
1258 if (host->dma_sg_idx < host->dma_len) { 1286 if (host->dma_sg_idx < host->dma_len) {
1259 /* Fire up the next transfer. */ 1287 /* Fire up the next transfer. */
1260 omap_hsmmc_config_dma_params(host, host->data, 1288 omap_hsmmc_config_dma_params(host, data,
1261 host->data->sg + host->dma_sg_idx); 1289 data->sg + host->dma_sg_idx);
1290 spin_unlock(&host->irq_lock);
1262 return; 1291 return;
1263 } 1292 }
1264 1293
1265 omap_free_dma(host->dma_ch); 1294 dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len,
1295 omap_hsmmc_get_dma_dir(host, data));
1296
1297 req_in_progress = host->req_in_progress;
1298 dma_ch = host->dma_ch;
1266 host->dma_ch = -1; 1299 host->dma_ch = -1;
1267 /* 1300 spin_unlock(&host->irq_lock);
1268 * DMA Callback: run in interrupt context. 1301
1269 * mutex_unlock will throw a kernel warning if used. 1302 omap_free_dma(dma_ch);
1270 */ 1303
1271 up(&host->sem); 1304 /* If DMA has finished after TC, complete the request */
1305 if (!req_in_progress) {
1306 struct mmc_request *mrq = host->mrq;
1307
1308 host->mrq = NULL;
1309 mmc_request_done(host->mmc, mrq);
1310 }
1272} 1311}
1273 1312
1274/* 1313/*
@@ -1277,7 +1316,7 @@ static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *data)
1277static int omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host, 1316static int omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host,
1278 struct mmc_request *req) 1317 struct mmc_request *req)
1279{ 1318{
1280 int dma_ch = 0, ret = 0, err = 1, i; 1319 int dma_ch = 0, ret = 0, i;
1281 struct mmc_data *data = req->data; 1320 struct mmc_data *data = req->data;
1282 1321
1283 /* Sanity check: all the SG entries must be aligned by block size. */ 1322 /* Sanity check: all the SG entries must be aligned by block size. */
@@ -1294,23 +1333,7 @@ static int omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host,
1294 */ 1333 */
1295 return -EINVAL; 1334 return -EINVAL;
1296 1335
1297 /* 1336 BUG_ON(host->dma_ch != -1);
1298 * If for some reason the DMA transfer is still active,
1299 * we wait for timeout period and free the dma
1300 */
1301 if (host->dma_ch != -1) {
1302 set_current_state(TASK_UNINTERRUPTIBLE);
1303 schedule_timeout(100);
1304 if (down_trylock(&host->sem)) {
1305 omap_free_dma(host->dma_ch);
1306 host->dma_ch = -1;
1307 up(&host->sem);
1308 return err;
1309 }
1310 } else {
1311 if (down_trylock(&host->sem))
1312 return err;
1313 }
1314 1337
1315 ret = omap_request_dma(omap_hsmmc_get_dma_sync_dev(host, data), 1338 ret = omap_request_dma(omap_hsmmc_get_dma_sync_dev(host, data),
1316 "MMC/SD", omap_hsmmc_dma_cb, host, &dma_ch); 1339 "MMC/SD", omap_hsmmc_dma_cb, host, &dma_ch);
@@ -1410,37 +1433,27 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req)
1410 struct omap_hsmmc_host *host = mmc_priv(mmc); 1433 struct omap_hsmmc_host *host = mmc_priv(mmc);
1411 int err; 1434 int err;
1412 1435
1413 /* 1436 BUG_ON(host->req_in_progress);
1414 * Prevent races with the interrupt handler because of unexpected 1437 BUG_ON(host->dma_ch != -1);
1415 * interrupts, but not if we are already in interrupt context i.e. 1438 if (host->protect_card) {
1416 * retries. 1439 if (host->reqs_blocked < 3) {
1417 */ 1440 /*
1418 if (!in_interrupt()) { 1441 * Ensure the controller is left in a consistent
1419 spin_lock_irqsave(&host->irq_lock, host->flags); 1442 * state by resetting the command and data state
1420 /* 1443 * machines.
1421 * Protect the card from I/O if there is a possibility 1444 */
1422 * it can be removed. 1445 omap_hsmmc_reset_controller_fsm(host, SRD);
1423 */ 1446 omap_hsmmc_reset_controller_fsm(host, SRC);
1424 if (host->protect_card) { 1447 host->reqs_blocked += 1;
1425 if (host->reqs_blocked < 3) { 1448 }
1426 /* 1449 req->cmd->error = -EBADF;
1427 * Ensure the controller is left in a consistent 1450 if (req->data)
1428 * state by resetting the command and data state 1451 req->data->error = -EBADF;
1429 * machines. 1452 req->cmd->retries = 0;
1430 */ 1453 mmc_request_done(mmc, req);
1431 omap_hsmmc_reset_controller_fsm(host, SRD); 1454 return;
1432 omap_hsmmc_reset_controller_fsm(host, SRC); 1455 } else if (host->reqs_blocked)
1433 host->reqs_blocked += 1; 1456 host->reqs_blocked = 0;
1434 }
1435 req->cmd->error = -EBADF;
1436 if (req->data)
1437 req->data->error = -EBADF;
1438 spin_unlock_irqrestore(&host->irq_lock, host->flags);
1439 mmc_request_done(mmc, req);
1440 return;
1441 } else if (host->reqs_blocked)
1442 host->reqs_blocked = 0;
1443 }
1444 WARN_ON(host->mrq != NULL); 1457 WARN_ON(host->mrq != NULL);
1445 host->mrq = req; 1458 host->mrq = req;
1446 err = omap_hsmmc_prepare_data(host, req); 1459 err = omap_hsmmc_prepare_data(host, req);
@@ -1449,8 +1462,6 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req)
1449 if (req->data) 1462 if (req->data)
1450 req->data->error = err; 1463 req->data->error = err;
1451 host->mrq = NULL; 1464 host->mrq = NULL;
1452 if (!in_interrupt())
1453 spin_unlock_irqrestore(&host->irq_lock, host->flags);
1454 mmc_request_done(mmc, req); 1465 mmc_request_done(mmc, req);
1455 return; 1466 return;
1456 } 1467 }
@@ -2019,7 +2030,6 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
2019 mmc->f_min = 400000; 2030 mmc->f_min = 400000;
2020 mmc->f_max = 52000000; 2031 mmc->f_max = 52000000;
2021 2032
2022 sema_init(&host->sem, 1);
2023 spin_lock_init(&host->irq_lock); 2033 spin_lock_init(&host->irq_lock);
2024 2034
2025 host->iclk = clk_get(&pdev->dev, "ick"); 2035 host->iclk = clk_get(&pdev->dev, "ick");
@@ -2162,8 +2172,7 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
2162 } 2172 }
2163 } 2173 }
2164 2174
2165 OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK); 2175 omap_hsmmc_disable_irq(host);
2166 OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK);
2167 2176
2168 mmc_host_lazy_disable(host->mmc); 2177 mmc_host_lazy_disable(host->mmc);
2169 2178
@@ -2258,10 +2267,12 @@ static int omap_hsmmc_remove(struct platform_device *pdev)
2258} 2267}
2259 2268
2260#ifdef CONFIG_PM 2269#ifdef CONFIG_PM
2261static int omap_hsmmc_suspend(struct platform_device *pdev, pm_message_t state) 2270static int omap_hsmmc_suspend(struct device *dev)
2262{ 2271{
2263 int ret = 0; 2272 int ret = 0;
2273 struct platform_device *pdev = to_platform_device(dev);
2264 struct omap_hsmmc_host *host = platform_get_drvdata(pdev); 2274 struct omap_hsmmc_host *host = platform_get_drvdata(pdev);
2275 pm_message_t state = PMSG_SUSPEND; /* unused by MMC core */
2265 2276
2266 if (host && host->suspended) 2277 if (host && host->suspended)
2267 return 0; 2278 return 0;
@@ -2281,12 +2292,9 @@ static int omap_hsmmc_suspend(struct platform_device *pdev, pm_message_t state)
2281 } 2292 }
2282 cancel_work_sync(&host->mmc_carddetect_work); 2293 cancel_work_sync(&host->mmc_carddetect_work);
2283 mmc_host_enable(host->mmc); 2294 mmc_host_enable(host->mmc);
2284 ret = mmc_suspend_host(host->mmc, state); 2295 ret = mmc_suspend_host(host->mmc);
2285 if (ret == 0) { 2296 if (ret == 0) {
2286 OMAP_HSMMC_WRITE(host->base, ISE, 0); 2297 omap_hsmmc_disable_irq(host);
2287 OMAP_HSMMC_WRITE(host->base, IE, 0);
2288
2289
2290 OMAP_HSMMC_WRITE(host->base, HCTL, 2298 OMAP_HSMMC_WRITE(host->base, HCTL,
2291 OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP); 2299 OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP);
2292 mmc_host_disable(host->mmc); 2300 mmc_host_disable(host->mmc);
@@ -2310,9 +2318,10 @@ static int omap_hsmmc_suspend(struct platform_device *pdev, pm_message_t state)
2310} 2318}
2311 2319
2312/* Routine to resume the MMC device */ 2320/* Routine to resume the MMC device */
2313static int omap_hsmmc_resume(struct platform_device *pdev) 2321static int omap_hsmmc_resume(struct device *dev)
2314{ 2322{
2315 int ret = 0; 2323 int ret = 0;
2324 struct platform_device *pdev = to_platform_device(dev);
2316 struct omap_hsmmc_host *host = platform_get_drvdata(pdev); 2325 struct omap_hsmmc_host *host = platform_get_drvdata(pdev);
2317 2326
2318 if (host && !host->suspended) 2327 if (host && !host->suspended)
@@ -2363,13 +2372,17 @@ clk_en_err:
2363#define omap_hsmmc_resume NULL 2372#define omap_hsmmc_resume NULL
2364#endif 2373#endif
2365 2374
2366static struct platform_driver omap_hsmmc_driver = { 2375static struct dev_pm_ops omap_hsmmc_dev_pm_ops = {
2367 .remove = omap_hsmmc_remove,
2368 .suspend = omap_hsmmc_suspend, 2376 .suspend = omap_hsmmc_suspend,
2369 .resume = omap_hsmmc_resume, 2377 .resume = omap_hsmmc_resume,
2378};
2379
2380static struct platform_driver omap_hsmmc_driver = {
2381 .remove = omap_hsmmc_remove,
2370 .driver = { 2382 .driver = {
2371 .name = DRIVER_NAME, 2383 .name = DRIVER_NAME,
2372 .owner = THIS_MODULE, 2384 .owner = THIS_MODULE,
2385 .pm = &omap_hsmmc_dev_pm_ops,
2373 }, 2386 },
2374}; 2387};
2375 2388
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index e4f00e70a749..0a4e43f37140 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -813,7 +813,7 @@ static int pxamci_suspend(struct device *dev)
813 int ret = 0; 813 int ret = 0;
814 814
815 if (mmc) 815 if (mmc)
816 ret = mmc_suspend_host(mmc, PMSG_SUSPEND); 816 ret = mmc_suspend_host(mmc);
817 817
818 return ret; 818 return ret;
819} 819}
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
index 2fdf7689ae6c..2e16e0a90a5e 100644
--- a/drivers/mmc/host/s3cmci.c
+++ b/drivers/mmc/host/s3cmci.c
@@ -1881,9 +1881,8 @@ MODULE_DEVICE_TABLE(platform, s3cmci_driver_ids);
1881static int s3cmci_suspend(struct device *dev) 1881static int s3cmci_suspend(struct device *dev)
1882{ 1882{
1883 struct mmc_host *mmc = platform_get_drvdata(to_platform_device(dev)); 1883 struct mmc_host *mmc = platform_get_drvdata(to_platform_device(dev));
1884 struct pm_message event = { PM_EVENT_SUSPEND };
1885 1884
1886 return mmc_suspend_host(mmc, event); 1885 return mmc_suspend_host(mmc);
1887} 1886}
1888 1887
1889static int s3cmci_resume(struct device *dev) 1888static int s3cmci_resume(struct device *dev)
diff --git a/drivers/mmc/host/sdhci-of-core.c b/drivers/mmc/host/sdhci-of-core.c
index 7802a543d8fc..a2e9820cd42f 100644
--- a/drivers/mmc/host/sdhci-of-core.c
+++ b/drivers/mmc/host/sdhci-of-core.c
@@ -89,7 +89,7 @@ static int sdhci_of_suspend(struct of_device *ofdev, pm_message_t state)
89{ 89{
90 struct sdhci_host *host = dev_get_drvdata(&ofdev->dev); 90 struct sdhci_host *host = dev_get_drvdata(&ofdev->dev);
91 91
92 return mmc_suspend_host(host->mmc, state); 92 return mmc_suspend_host(host->mmc);
93} 93}
94 94
95static int sdhci_of_resume(struct of_device *ofdev) 95static int sdhci_of_resume(struct of_device *ofdev)
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index d5b11a17e648..c8623de13af3 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -129,12 +129,12 @@ struct sdhci_of_data sdhci_esdhc = {
129 SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET | 129 SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET |
130 SDHCI_QUIRK_NO_CARD_NO_RESET, 130 SDHCI_QUIRK_NO_CARD_NO_RESET,
131 .ops = { 131 .ops = {
132 .readl = sdhci_be32bs_readl, 132 .read_l = sdhci_be32bs_readl,
133 .readw = esdhc_readw, 133 .read_w = esdhc_readw,
134 .readb = sdhci_be32bs_readb, 134 .read_b = sdhci_be32bs_readb,
135 .writel = sdhci_be32bs_writel, 135 .write_l = sdhci_be32bs_writel,
136 .writew = esdhc_writew, 136 .write_w = esdhc_writew,
137 .writeb = esdhc_writeb, 137 .write_b = esdhc_writeb,
138 .set_clock = esdhc_set_clock, 138 .set_clock = esdhc_set_clock,
139 .enable_dma = esdhc_enable_dma, 139 .enable_dma = esdhc_enable_dma,
140 .get_max_clock = esdhc_get_max_clock, 140 .get_max_clock = esdhc_get_max_clock,
diff --git a/drivers/mmc/host/sdhci-of-hlwd.c b/drivers/mmc/host/sdhci-of-hlwd.c
index 35117f3ed757..68ddb7546ae2 100644
--- a/drivers/mmc/host/sdhci-of-hlwd.c
+++ b/drivers/mmc/host/sdhci-of-hlwd.c
@@ -55,11 +55,11 @@ struct sdhci_of_data sdhci_hlwd = {
55 .quirks = SDHCI_QUIRK_32BIT_DMA_ADDR | 55 .quirks = SDHCI_QUIRK_32BIT_DMA_ADDR |
56 SDHCI_QUIRK_32BIT_DMA_SIZE, 56 SDHCI_QUIRK_32BIT_DMA_SIZE,
57 .ops = { 57 .ops = {
58 .readl = sdhci_be32bs_readl, 58 .read_l = sdhci_be32bs_readl,
59 .readw = sdhci_be32bs_readw, 59 .read_w = sdhci_be32bs_readw,
60 .readb = sdhci_be32bs_readb, 60 .read_b = sdhci_be32bs_readb,
61 .writel = sdhci_hlwd_writel, 61 .write_l = sdhci_hlwd_writel,
62 .writew = sdhci_hlwd_writew, 62 .write_w = sdhci_hlwd_writew,
63 .writeb = sdhci_hlwd_writeb, 63 .write_b = sdhci_hlwd_writeb,
64 }, 64 },
65}; 65};
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index 6701af629c30..65483fdea45b 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -628,7 +628,7 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
628 host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_pci_slot)); 628 host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_pci_slot));
629 if (IS_ERR(host)) { 629 if (IS_ERR(host)) {
630 dev_err(&pdev->dev, "cannot allocate host\n"); 630 dev_err(&pdev->dev, "cannot allocate host\n");
631 return ERR_PTR(PTR_ERR(host)); 631 return ERR_CAST(host);
632 } 632 }
633 633
634 slot = sdhci_priv(host); 634 slot = sdhci_priv(host);
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
index 297f40ae6ad5..b6ee0d719698 100644
--- a/drivers/mmc/host/sdhci-pltfm.c
+++ b/drivers/mmc/host/sdhci-pltfm.c
@@ -29,6 +29,7 @@
29#include <linux/mmc/host.h> 29#include <linux/mmc/host.h>
30 30
31#include <linux/io.h> 31#include <linux/io.h>
32#include <linux/sdhci-pltfm.h>
32 33
33#include "sdhci.h" 34#include "sdhci.h"
34 35
@@ -49,19 +50,18 @@ static struct sdhci_ops sdhci_pltfm_ops = {
49 50
50static int __devinit sdhci_pltfm_probe(struct platform_device *pdev) 51static int __devinit sdhci_pltfm_probe(struct platform_device *pdev)
51{ 52{
53 struct sdhci_pltfm_data *pdata = pdev->dev.platform_data;
52 struct sdhci_host *host; 54 struct sdhci_host *host;
53 struct resource *iomem; 55 struct resource *iomem;
54 int ret; 56 int ret;
55 57
56 BUG_ON(pdev == NULL);
57
58 iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 58 iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
59 if (!iomem) { 59 if (!iomem) {
60 ret = -ENOMEM; 60 ret = -ENOMEM;
61 goto err; 61 goto err;
62 } 62 }
63 63
64 if (resource_size(iomem) != 0x100) 64 if (resource_size(iomem) < 0x100)
65 dev_err(&pdev->dev, "Invalid iomem size. You may " 65 dev_err(&pdev->dev, "Invalid iomem size. You may "
66 "experience problems.\n"); 66 "experience problems.\n");
67 67
@@ -76,7 +76,12 @@ static int __devinit sdhci_pltfm_probe(struct platform_device *pdev)
76 } 76 }
77 77
78 host->hw_name = "platform"; 78 host->hw_name = "platform";
79 host->ops = &sdhci_pltfm_ops; 79 if (pdata && pdata->ops)
80 host->ops = pdata->ops;
81 else
82 host->ops = &sdhci_pltfm_ops;
83 if (pdata)
84 host->quirks = pdata->quirks;
80 host->irq = platform_get_irq(pdev, 0); 85 host->irq = platform_get_irq(pdev, 0);
81 86
82 if (!request_mem_region(iomem->start, resource_size(iomem), 87 if (!request_mem_region(iomem->start, resource_size(iomem),
@@ -93,6 +98,12 @@ static int __devinit sdhci_pltfm_probe(struct platform_device *pdev)
93 goto err_remap; 98 goto err_remap;
94 } 99 }
95 100
101 if (pdata && pdata->init) {
102 ret = pdata->init(host);
103 if (ret)
104 goto err_plat_init;
105 }
106
96 ret = sdhci_add_host(host); 107 ret = sdhci_add_host(host);
97 if (ret) 108 if (ret)
98 goto err_add_host; 109 goto err_add_host;
@@ -102,6 +113,9 @@ static int __devinit sdhci_pltfm_probe(struct platform_device *pdev)
102 return 0; 113 return 0;
103 114
104err_add_host: 115err_add_host:
116 if (pdata && pdata->exit)
117 pdata->exit(host);
118err_plat_init:
105 iounmap(host->ioaddr); 119 iounmap(host->ioaddr);
106err_remap: 120err_remap:
107 release_mem_region(iomem->start, resource_size(iomem)); 121 release_mem_region(iomem->start, resource_size(iomem));
@@ -114,6 +128,7 @@ err:
114 128
115static int __devexit sdhci_pltfm_remove(struct platform_device *pdev) 129static int __devexit sdhci_pltfm_remove(struct platform_device *pdev)
116{ 130{
131 struct sdhci_pltfm_data *pdata = pdev->dev.platform_data;
117 struct sdhci_host *host = platform_get_drvdata(pdev); 132 struct sdhci_host *host = platform_get_drvdata(pdev);
118 struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 133 struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
119 int dead; 134 int dead;
@@ -125,6 +140,8 @@ static int __devexit sdhci_pltfm_remove(struct platform_device *pdev)
125 dead = 1; 140 dead = 1;
126 141
127 sdhci_remove_host(host, dead); 142 sdhci_remove_host(host, dead);
143 if (pdata && pdata->exit)
144 pdata->exit(host);
128 iounmap(host->ioaddr); 145 iounmap(host->ioaddr);
129 release_mem_region(iomem->start, resource_size(iomem)); 146 release_mem_region(iomem->start, resource_size(iomem));
130 sdhci_free_host(host); 147 sdhci_free_host(host);
@@ -165,4 +182,3 @@ MODULE_DESCRIPTION("Secure Digital Host Controller Interface platform driver");
165MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>"); 182MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>");
166MODULE_LICENSE("GPL v2"); 183MODULE_LICENSE("GPL v2");
167MODULE_ALIAS("platform:sdhci"); 184MODULE_ALIAS("platform:sdhci");
168
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
index 2136794c0cfa..af217924a76e 100644
--- a/drivers/mmc/host/sdhci-s3c.c
+++ b/drivers/mmc/host/sdhci-s3c.c
@@ -317,12 +317,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
317 host->irq = irq; 317 host->irq = irq;
318 318
319 /* Setup quirks for the controller */ 319 /* Setup quirks for the controller */
320 320 host->quirks |= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC;
321 /* Currently with ADMA enabled we are getting some length
322 * interrupts that are not being dealt with, do disable
323 * ADMA until this is sorted out. */
324 host->quirks |= SDHCI_QUIRK_BROKEN_ADMA;
325 host->quirks |= SDHCI_QUIRK_32BIT_ADMA_SIZE;
326 321
327#ifndef CONFIG_MMC_SDHCI_S3C_DMA 322#ifndef CONFIG_MMC_SDHCI_S3C_DMA
328 323
@@ -330,9 +325,6 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
330 * support as well. */ 325 * support as well. */
331 host->quirks |= SDHCI_QUIRK_BROKEN_DMA; 326 host->quirks |= SDHCI_QUIRK_BROKEN_DMA;
332 327
333 /* PIO currently has problems with multi-block IO */
334 host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK;
335
336#endif /* CONFIG_MMC_SDHCI_S3C_DMA */ 328#endif /* CONFIG_MMC_SDHCI_S3C_DMA */
337 329
338 /* It seems we do not get an DATA transfer complete on non-busy 330 /* It seems we do not get an DATA transfer complete on non-busy
diff --git a/drivers/mmc/host/sdhci-spear.c b/drivers/mmc/host/sdhci-spear.c
new file mode 100644
index 000000000000..d70c54c7b70a
--- /dev/null
+++ b/drivers/mmc/host/sdhci-spear.c
@@ -0,0 +1,298 @@
1/*
2 * drivers/mmc/host/sdhci-spear.c
3 *
4 * Support of SDHCI platform devices for spear soc family
5 *
6 * Copyright (C) 2010 ST Microelectronics
7 * Viresh Kumar<viresh.kumar@st.com>
8 *
9 * Inspired by sdhci-pltfm.c
10 *
11 * This file is licensed under the terms of the GNU General Public
12 * License version 2. This program is licensed "as is" without any
13 * warranty of any kind, whether express or implied.
14 */
15
16#include <linux/clk.h>
17#include <linux/delay.h>
18#include <linux/gpio.h>
19#include <linux/highmem.h>
20#include <linux/interrupt.h>
21#include <linux/irq.h>
22#include <linux/platform_device.h>
23#include <linux/slab.h>
24#include <linux/mmc/host.h>
25#include <linux/mmc/sdhci-spear.h>
26#include <linux/io.h>
27#include "sdhci.h"
28
29struct spear_sdhci {
30 struct clk *clk;
31 struct sdhci_plat_data *data;
32};
33
34/* sdhci ops */
35static struct sdhci_ops sdhci_pltfm_ops = {
36 /* Nothing to do for now. */
37};
38
39/* gpio card detection interrupt handler */
40static irqreturn_t sdhci_gpio_irq(int irq, void *dev_id)
41{
42 struct platform_device *pdev = dev_id;
43 struct sdhci_host *host = platform_get_drvdata(pdev);
44 struct spear_sdhci *sdhci = dev_get_platdata(&pdev->dev);
45 unsigned long gpio_irq_type;
46 int val;
47
48 val = gpio_get_value(sdhci->data->card_int_gpio);
49
50 /* val == 1 -> card removed, val == 0 -> card inserted */
51 /* if card removed - set irq for low level, else vice versa */
52 gpio_irq_type = val ? IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH;
53 set_irq_type(irq, gpio_irq_type);
54
55 if (sdhci->data->card_power_gpio >= 0) {
56 if (!sdhci->data->power_always_enb) {
57 /* if card inserted, give power, otherwise remove it */
58 val = sdhci->data->power_active_high ? !val : val ;
59 gpio_set_value(sdhci->data->card_power_gpio, val);
60 }
61 }
62
63 /* inform sdhci driver about card insertion/removal */
64 tasklet_schedule(&host->card_tasklet);
65
66 return IRQ_HANDLED;
67}
68
69static int __devinit sdhci_probe(struct platform_device *pdev)
70{
71 struct sdhci_host *host;
72 struct resource *iomem;
73 struct spear_sdhci *sdhci;
74 int ret;
75
76 BUG_ON(pdev == NULL);
77
78 iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
79 if (!iomem) {
80 ret = -ENOMEM;
81 dev_dbg(&pdev->dev, "memory resource not defined\n");
82 goto err;
83 }
84
85 if (!request_mem_region(iomem->start, resource_size(iomem),
86 "spear-sdhci")) {
87 ret = -EBUSY;
88 dev_dbg(&pdev->dev, "cannot request region\n");
89 goto err;
90 }
91
92 sdhci = kzalloc(sizeof(*sdhci), GFP_KERNEL);
93 if (!sdhci) {
94 ret = -ENOMEM;
95 dev_dbg(&pdev->dev, "cannot allocate memory for sdhci\n");
96 goto err_kzalloc;
97 }
98
99 /* clk enable */
100 sdhci->clk = clk_get(&pdev->dev, NULL);
101 if (IS_ERR(sdhci->clk)) {
102 ret = PTR_ERR(sdhci->clk);
103 dev_dbg(&pdev->dev, "Error getting clock\n");
104 goto err_clk_get;
105 }
106
107 ret = clk_enable(sdhci->clk);
108 if (ret) {
109 dev_dbg(&pdev->dev, "Error enabling clock\n");
110 goto err_clk_enb;
111 }
112
113 /* overwrite platform_data */
114 sdhci->data = dev_get_platdata(&pdev->dev);
115 pdev->dev.platform_data = sdhci;
116
117 if (pdev->dev.parent)
118 host = sdhci_alloc_host(pdev->dev.parent, 0);
119 else
120 host = sdhci_alloc_host(&pdev->dev, 0);
121
122 if (IS_ERR(host)) {
123 ret = PTR_ERR(host);
124 dev_dbg(&pdev->dev, "error allocating host\n");
125 goto err_alloc_host;
126 }
127
128 host->hw_name = "sdhci";
129 host->ops = &sdhci_pltfm_ops;
130 host->irq = platform_get_irq(pdev, 0);
131 host->quirks = SDHCI_QUIRK_BROKEN_ADMA;
132
133 host->ioaddr = ioremap(iomem->start, resource_size(iomem));
134 if (!host->ioaddr) {
135 ret = -ENOMEM;
136 dev_dbg(&pdev->dev, "failed to remap registers\n");
137 goto err_ioremap;
138 }
139
140 ret = sdhci_add_host(host);
141 if (ret) {
142 dev_dbg(&pdev->dev, "error adding host\n");
143 goto err_add_host;
144 }
145
146 platform_set_drvdata(pdev, host);
147
148 /*
149 * It is optional to use GPIOs for sdhci Power control & sdhci card
150 * interrupt detection. If sdhci->data is NULL, then use original sdhci
151 * lines otherwise GPIO lines.
152 * If GPIO is selected for power control, then power should be disabled
153 * after card removal and should be enabled when card insertion
154 * interrupt occurs
155 */
156 if (!sdhci->data)
157 return 0;
158
159 if (sdhci->data->card_power_gpio >= 0) {
160 int val = 0;
161
162 ret = gpio_request(sdhci->data->card_power_gpio, "sdhci");
163 if (ret < 0) {
164 dev_dbg(&pdev->dev, "gpio request fail: %d\n",
165 sdhci->data->card_power_gpio);
166 goto err_pgpio_request;
167 }
168
169 if (sdhci->data->power_always_enb)
170 val = sdhci->data->power_active_high;
171 else
172 val = !sdhci->data->power_active_high;
173
174 ret = gpio_direction_output(sdhci->data->card_power_gpio, val);
175 if (ret) {
176 dev_dbg(&pdev->dev, "gpio set direction fail: %d\n",
177 sdhci->data->card_power_gpio);
178 goto err_pgpio_direction;
179 }
180
181 gpio_set_value(sdhci->data->card_power_gpio, 1);
182 }
183
184 if (sdhci->data->card_int_gpio >= 0) {
185 ret = gpio_request(sdhci->data->card_int_gpio, "sdhci");
186 if (ret < 0) {
187 dev_dbg(&pdev->dev, "gpio request fail: %d\n",
188 sdhci->data->card_int_gpio);
189 goto err_igpio_request;
190 }
191
192 ret = gpio_direction_input(sdhci->data->card_int_gpio);
193 if (ret) {
194 dev_dbg(&pdev->dev, "gpio set direction fail: %d\n",
195 sdhci->data->card_int_gpio);
196 goto err_igpio_direction;
197 }
198 ret = request_irq(gpio_to_irq(sdhci->data->card_int_gpio),
199 sdhci_gpio_irq, IRQF_TRIGGER_LOW,
200 mmc_hostname(host->mmc), pdev);
201 if (ret) {
202 dev_dbg(&pdev->dev, "gpio request irq fail: %d\n",
203 sdhci->data->card_int_gpio);
204 goto err_igpio_request_irq;
205 }
206
207 }
208
209 return 0;
210
211err_igpio_request_irq:
212err_igpio_direction:
213 if (sdhci->data->card_int_gpio >= 0)
214 gpio_free(sdhci->data->card_int_gpio);
215err_igpio_request:
216err_pgpio_direction:
217 if (sdhci->data->card_power_gpio >= 0)
218 gpio_free(sdhci->data->card_power_gpio);
219err_pgpio_request:
220 platform_set_drvdata(pdev, NULL);
221 sdhci_remove_host(host, 1);
222err_add_host:
223 iounmap(host->ioaddr);
224err_ioremap:
225 sdhci_free_host(host);
226err_alloc_host:
227 clk_disable(sdhci->clk);
228err_clk_enb:
229 clk_put(sdhci->clk);
230err_clk_get:
231 kfree(sdhci);
232err_kzalloc:
233 release_mem_region(iomem->start, resource_size(iomem));
234err:
235 dev_err(&pdev->dev, "spear-sdhci probe failed: %d\n", ret);
236 return ret;
237}
238
239static int __devexit sdhci_remove(struct platform_device *pdev)
240{
241 struct sdhci_host *host = platform_get_drvdata(pdev);
242 struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
243 struct spear_sdhci *sdhci = dev_get_platdata(&pdev->dev);
244 int dead;
245 u32 scratch;
246
247 if (sdhci->data) {
248 if (sdhci->data->card_int_gpio >= 0) {
249 free_irq(gpio_to_irq(sdhci->data->card_int_gpio), pdev);
250 gpio_free(sdhci->data->card_int_gpio);
251 }
252
253 if (sdhci->data->card_power_gpio >= 0)
254 gpio_free(sdhci->data->card_power_gpio);
255 }
256
257 platform_set_drvdata(pdev, NULL);
258 dead = 0;
259 scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
260 if (scratch == (u32)-1)
261 dead = 1;
262
263 sdhci_remove_host(host, dead);
264 iounmap(host->ioaddr);
265 sdhci_free_host(host);
266 clk_disable(sdhci->clk);
267 clk_put(sdhci->clk);
268 kfree(sdhci);
269 if (iomem)
270 release_mem_region(iomem->start, resource_size(iomem));
271
272 return 0;
273}
274
275static struct platform_driver sdhci_driver = {
276 .driver = {
277 .name = "sdhci",
278 .owner = THIS_MODULE,
279 },
280 .probe = sdhci_probe,
281 .remove = __devexit_p(sdhci_remove),
282};
283
284static int __init sdhci_init(void)
285{
286 return platform_driver_register(&sdhci_driver);
287}
288module_init(sdhci_init);
289
290static void __exit sdhci_exit(void)
291{
292 platform_driver_unregister(&sdhci_driver);
293}
294module_exit(sdhci_exit);
295
296MODULE_DESCRIPTION("SPEAr Secure Digital Host Controller Interface driver");
297MODULE_AUTHOR("Viresh Kumar <viresh.kumar@st.com>");
298MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 9d4fdfa685e5..c6d1bd8d4ac4 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -496,12 +496,22 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
496 WARN_ON((desc - host->adma_desc) > (128 * 2 + 1) * 4); 496 WARN_ON((desc - host->adma_desc) > (128 * 2 + 1) * 4);
497 } 497 }
498 498
499 /* 499 if (host->quirks & SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC) {
500 * Add a terminating entry. 500 /*
501 */ 501 * Mark the last descriptor as the terminating descriptor
502 */
503 if (desc != host->adma_desc) {
504 desc -= 8;
505 desc[0] |= 0x2; /* end */
506 }
507 } else {
508 /*
509 * Add a terminating entry.
510 */
502 511
503 /* nop, end, valid */ 512 /* nop, end, valid */
504 sdhci_set_adma_desc(desc, 0, 0, 0x3); 513 sdhci_set_adma_desc(desc, 0, 0, 0x3);
514 }
505 515
506 /* 516 /*
507 * Resync align buffer as we might have changed it. 517 * Resync align buffer as we might have changed it.
@@ -1587,7 +1597,7 @@ int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state)
1587 1597
1588 sdhci_disable_card_detection(host); 1598 sdhci_disable_card_detection(host);
1589 1599
1590 ret = mmc_suspend_host(host->mmc, state); 1600 ret = mmc_suspend_host(host->mmc);
1591 if (ret) 1601 if (ret)
1592 return ret; 1602 return ret;
1593 1603
@@ -1744,7 +1754,8 @@ int sdhci_add_host(struct sdhci_host *host)
1744 host->max_clk = 1754 host->max_clk =
1745 (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT; 1755 (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT;
1746 host->max_clk *= 1000000; 1756 host->max_clk *= 1000000;
1747 if (host->max_clk == 0) { 1757 if (host->max_clk == 0 || host->quirks &
1758 SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN) {
1748 if (!host->ops->get_max_clock) { 1759 if (!host->ops->get_max_clock) {
1749 printk(KERN_ERR 1760 printk(KERN_ERR
1750 "%s: Hardware doesn't specify base clock " 1761 "%s: Hardware doesn't specify base clock "
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 842f46f94284..c8468134adc9 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -127,7 +127,7 @@
127#define SDHCI_INT_DATA_MASK (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | \ 127#define SDHCI_INT_DATA_MASK (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | \
128 SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \ 128 SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \
129 SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \ 129 SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \
130 SDHCI_INT_DATA_END_BIT | SDHCI_ADMA_ERROR) 130 SDHCI_INT_DATA_END_BIT | SDHCI_INT_ADMA_ERROR)
131#define SDHCI_INT_ALL_MASK ((unsigned int)-1) 131#define SDHCI_INT_ALL_MASK ((unsigned int)-1)
132 132
133#define SDHCI_ACMD12_ERR 0x3C 133#define SDHCI_ACMD12_ERR 0x3C
@@ -236,6 +236,10 @@ struct sdhci_host {
236#define SDHCI_QUIRK_DELAY_AFTER_POWER (1<<23) 236#define SDHCI_QUIRK_DELAY_AFTER_POWER (1<<23)
237/* Controller uses SDCLK instead of TMCLK for data timeouts */ 237/* Controller uses SDCLK instead of TMCLK for data timeouts */
238#define SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK (1<<24) 238#define SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK (1<<24)
239/* Controller reports wrong base clock capability */
240#define SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN (1<<25)
241/* Controller cannot support End Attribute in NOP ADMA descriptor */
242#define SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC (1<<26)
239 243
240 int irq; /* Device IRQ */ 244 int irq; /* Device IRQ */
241 void __iomem * ioaddr; /* Mapped address */ 245 void __iomem * ioaddr; /* Mapped address */
@@ -294,12 +298,12 @@ struct sdhci_host {
294 298
295struct sdhci_ops { 299struct sdhci_ops {
296#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS 300#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
297 u32 (*readl)(struct sdhci_host *host, int reg); 301 u32 (*read_l)(struct sdhci_host *host, int reg);
298 u16 (*readw)(struct sdhci_host *host, int reg); 302 u16 (*read_w)(struct sdhci_host *host, int reg);
299 u8 (*readb)(struct sdhci_host *host, int reg); 303 u8 (*read_b)(struct sdhci_host *host, int reg);
300 void (*writel)(struct sdhci_host *host, u32 val, int reg); 304 void (*write_l)(struct sdhci_host *host, u32 val, int reg);
301 void (*writew)(struct sdhci_host *host, u16 val, int reg); 305 void (*write_w)(struct sdhci_host *host, u16 val, int reg);
302 void (*writeb)(struct sdhci_host *host, u8 val, int reg); 306 void (*write_b)(struct sdhci_host *host, u8 val, int reg);
303#endif 307#endif
304 308
305 void (*set_clock)(struct sdhci_host *host, unsigned int clock); 309 void (*set_clock)(struct sdhci_host *host, unsigned int clock);
@@ -314,48 +318,48 @@ struct sdhci_ops {
314 318
315static inline void sdhci_writel(struct sdhci_host *host, u32 val, int reg) 319static inline void sdhci_writel(struct sdhci_host *host, u32 val, int reg)
316{ 320{
317 if (unlikely(host->ops->writel)) 321 if (unlikely(host->ops->write_l))
318 host->ops->writel(host, val, reg); 322 host->ops->write_l(host, val, reg);
319 else 323 else
320 writel(val, host->ioaddr + reg); 324 writel(val, host->ioaddr + reg);
321} 325}
322 326
323static inline void sdhci_writew(struct sdhci_host *host, u16 val, int reg) 327static inline void sdhci_writew(struct sdhci_host *host, u16 val, int reg)
324{ 328{
325 if (unlikely(host->ops->writew)) 329 if (unlikely(host->ops->write_w))
326 host->ops->writew(host, val, reg); 330 host->ops->write_w(host, val, reg);
327 else 331 else
328 writew(val, host->ioaddr + reg); 332 writew(val, host->ioaddr + reg);
329} 333}
330 334
331static inline void sdhci_writeb(struct sdhci_host *host, u8 val, int reg) 335static inline void sdhci_writeb(struct sdhci_host *host, u8 val, int reg)
332{ 336{
333 if (unlikely(host->ops->writeb)) 337 if (unlikely(host->ops->write_b))
334 host->ops->writeb(host, val, reg); 338 host->ops->write_b(host, val, reg);
335 else 339 else
336 writeb(val, host->ioaddr + reg); 340 writeb(val, host->ioaddr + reg);
337} 341}
338 342
339static inline u32 sdhci_readl(struct sdhci_host *host, int reg) 343static inline u32 sdhci_readl(struct sdhci_host *host, int reg)
340{ 344{
341 if (unlikely(host->ops->readl)) 345 if (unlikely(host->ops->read_l))
342 return host->ops->readl(host, reg); 346 return host->ops->read_l(host, reg);
343 else 347 else
344 return readl(host->ioaddr + reg); 348 return readl(host->ioaddr + reg);
345} 349}
346 350
347static inline u16 sdhci_readw(struct sdhci_host *host, int reg) 351static inline u16 sdhci_readw(struct sdhci_host *host, int reg)
348{ 352{
349 if (unlikely(host->ops->readw)) 353 if (unlikely(host->ops->read_w))
350 return host->ops->readw(host, reg); 354 return host->ops->read_w(host, reg);
351 else 355 else
352 return readw(host->ioaddr + reg); 356 return readw(host->ioaddr + reg);
353} 357}
354 358
355static inline u8 sdhci_readb(struct sdhci_host *host, int reg) 359static inline u8 sdhci_readb(struct sdhci_host *host, int reg)
356{ 360{
357 if (unlikely(host->ops->readb)) 361 if (unlikely(host->ops->read_b))
358 return host->ops->readb(host, reg); 362 return host->ops->read_b(host, reg);
359 else 363 else
360 return readb(host->ioaddr + reg); 364 return readb(host->ioaddr + reg);
361} 365}
diff --git a/drivers/mmc/host/sdricoh_cs.c b/drivers/mmc/host/sdricoh_cs.c
index cb41e9c3ac07..e7507af3856e 100644
--- a/drivers/mmc/host/sdricoh_cs.c
+++ b/drivers/mmc/host/sdricoh_cs.c
@@ -519,7 +519,7 @@ static int sdricoh_pcmcia_suspend(struct pcmcia_device *link)
519{ 519{
520 struct mmc_host *mmc = link->priv; 520 struct mmc_host *mmc = link->priv;
521 dev_dbg(&link->dev, "suspend\n"); 521 dev_dbg(&link->dev, "suspend\n");
522 mmc_suspend_host(mmc, PMSG_SUSPEND); 522 mmc_suspend_host(mmc);
523 return 0; 523 return 0;
524} 524}
525 525
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
new file mode 100644
index 000000000000..5d3f824bb5a3
--- /dev/null
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -0,0 +1,940 @@
1/*
2 * MMCIF eMMC driver.
3 *
4 * Copyright (C) 2010 Renesas Solutions Corp.
5 * Yusuke Goda <yusuke.goda.sx@renesas.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License.
10 *
11 *
12 * TODO
13 * 1. DMA
14 * 2. Power management
15 * 3. Handle MMC errors better
16 *
17 */
18
19#include <linux/dma-mapping.h>
20#include <linux/mmc/host.h>
21#include <linux/mmc/card.h>
22#include <linux/mmc/core.h>
23#include <linux/mmc/mmc.h>
24#include <linux/mmc/sdio.h>
25#include <linux/delay.h>
26#include <linux/platform_device.h>
27#include <linux/clk.h>
28#include <linux/mmc/sh_mmcif.h>
29
30#define DRIVER_NAME "sh_mmcif"
31#define DRIVER_VERSION "2010-04-28"
32
33/* CE_CMD_SET */
34#define CMD_MASK 0x3f000000
35#define CMD_SET_RTYP_NO ((0 << 23) | (0 << 22))
36#define CMD_SET_RTYP_6B ((0 << 23) | (1 << 22)) /* R1/R1b/R3/R4/R5 */
37#define CMD_SET_RTYP_17B ((1 << 23) | (0 << 22)) /* R2 */
38#define CMD_SET_RBSY (1 << 21) /* R1b */
39#define CMD_SET_CCSEN (1 << 20)
40#define CMD_SET_WDAT (1 << 19) /* 1: on data, 0: no data */
41#define CMD_SET_DWEN (1 << 18) /* 1: write, 0: read */
42#define CMD_SET_CMLTE (1 << 17) /* 1: multi block trans, 0: single */
43#define CMD_SET_CMD12EN (1 << 16) /* 1: CMD12 auto issue */
44#define CMD_SET_RIDXC_INDEX ((0 << 15) | (0 << 14)) /* index check */
45#define CMD_SET_RIDXC_BITS ((0 << 15) | (1 << 14)) /* check bits check */
46#define CMD_SET_RIDXC_NO ((1 << 15) | (0 << 14)) /* no check */
47#define CMD_SET_CRC7C ((0 << 13) | (0 << 12)) /* CRC7 check*/
48#define CMD_SET_CRC7C_BITS ((0 << 13) | (1 << 12)) /* check bits check*/
49#define CMD_SET_CRC7C_INTERNAL ((1 << 13) | (0 << 12)) /* internal CRC7 check*/
50#define CMD_SET_CRC16C (1 << 10) /* 0: CRC16 check*/
51#define CMD_SET_CRCSTE (1 << 8) /* 1: not receive CRC status */
52#define CMD_SET_TBIT (1 << 7) /* 1: tran mission bit "Low" */
53#define CMD_SET_OPDM (1 << 6) /* 1: open/drain */
54#define CMD_SET_CCSH (1 << 5)
55#define CMD_SET_DATW_1 ((0 << 1) | (0 << 0)) /* 1bit */
56#define CMD_SET_DATW_4 ((0 << 1) | (1 << 0)) /* 4bit */
57#define CMD_SET_DATW_8 ((1 << 1) | (0 << 0)) /* 8bit */
58
59/* CE_CMD_CTRL */
60#define CMD_CTRL_BREAK (1 << 0)
61
62/* CE_BLOCK_SET */
63#define BLOCK_SIZE_MASK 0x0000ffff
64
65/* CE_CLK_CTRL */
66#define CLK_ENABLE (1 << 24) /* 1: output mmc clock */
67#define CLK_CLEAR ((1 << 19) | (1 << 18) | (1 << 17) | (1 << 16))
68#define CLK_SUP_PCLK ((1 << 19) | (1 << 18) | (1 << 17) | (1 << 16))
69#define SRSPTO_256 ((1 << 13) | (0 << 12)) /* resp timeout */
70#define SRBSYTO_29 ((1 << 11) | (1 << 10) | \
71 (1 << 9) | (1 << 8)) /* resp busy timeout */
72#define SRWDTO_29 ((1 << 7) | (1 << 6) | \
73 (1 << 5) | (1 << 4)) /* read/write timeout */
74#define SCCSTO_29 ((1 << 3) | (1 << 2) | \
75 (1 << 1) | (1 << 0)) /* ccs timeout */
76
77/* CE_BUF_ACC */
78#define BUF_ACC_DMAWEN (1 << 25)
79#define BUF_ACC_DMAREN (1 << 24)
80#define BUF_ACC_BUSW_32 (0 << 17)
81#define BUF_ACC_BUSW_16 (1 << 17)
82#define BUF_ACC_ATYP (1 << 16)
83
84/* CE_INT */
85#define INT_CCSDE (1 << 29)
86#define INT_CMD12DRE (1 << 26)
87#define INT_CMD12RBE (1 << 25)
88#define INT_CMD12CRE (1 << 24)
89#define INT_DTRANE (1 << 23)
90#define INT_BUFRE (1 << 22)
91#define INT_BUFWEN (1 << 21)
92#define INT_BUFREN (1 << 20)
93#define INT_CCSRCV (1 << 19)
94#define INT_RBSYE (1 << 17)
95#define INT_CRSPE (1 << 16)
96#define INT_CMDVIO (1 << 15)
97#define INT_BUFVIO (1 << 14)
98#define INT_WDATERR (1 << 11)
99#define INT_RDATERR (1 << 10)
100#define INT_RIDXERR (1 << 9)
101#define INT_RSPERR (1 << 8)
102#define INT_CCSTO (1 << 5)
103#define INT_CRCSTO (1 << 4)
104#define INT_WDATTO (1 << 3)
105#define INT_RDATTO (1 << 2)
106#define INT_RBSYTO (1 << 1)
107#define INT_RSPTO (1 << 0)
108#define INT_ERR_STS (INT_CMDVIO | INT_BUFVIO | INT_WDATERR | \
109 INT_RDATERR | INT_RIDXERR | INT_RSPERR | \
110 INT_CCSTO | INT_CRCSTO | INT_WDATTO | \
111 INT_RDATTO | INT_RBSYTO | INT_RSPTO)
112
113/* CE_INT_MASK */
114#define MASK_ALL 0x00000000
115#define MASK_MCCSDE (1 << 29)
116#define MASK_MCMD12DRE (1 << 26)
117#define MASK_MCMD12RBE (1 << 25)
118#define MASK_MCMD12CRE (1 << 24)
119#define MASK_MDTRANE (1 << 23)
120#define MASK_MBUFRE (1 << 22)
121#define MASK_MBUFWEN (1 << 21)
122#define MASK_MBUFREN (1 << 20)
123#define MASK_MCCSRCV (1 << 19)
124#define MASK_MRBSYE (1 << 17)
125#define MASK_MCRSPE (1 << 16)
126#define MASK_MCMDVIO (1 << 15)
127#define MASK_MBUFVIO (1 << 14)
128#define MASK_MWDATERR (1 << 11)
129#define MASK_MRDATERR (1 << 10)
130#define MASK_MRIDXERR (1 << 9)
131#define MASK_MRSPERR (1 << 8)
132#define MASK_MCCSTO (1 << 5)
133#define MASK_MCRCSTO (1 << 4)
134#define MASK_MWDATTO (1 << 3)
135#define MASK_MRDATTO (1 << 2)
136#define MASK_MRBSYTO (1 << 1)
137#define MASK_MRSPTO (1 << 0)
138
139/* CE_HOST_STS1 */
140#define STS1_CMDSEQ (1 << 31)
141
142/* CE_HOST_STS2 */
143#define STS2_CRCSTE (1 << 31)
144#define STS2_CRC16E (1 << 30)
145#define STS2_AC12CRCE (1 << 29)
146#define STS2_RSPCRC7E (1 << 28)
147#define STS2_CRCSTEBE (1 << 27)
148#define STS2_RDATEBE (1 << 26)
149#define STS2_AC12REBE (1 << 25)
150#define STS2_RSPEBE (1 << 24)
151#define STS2_AC12IDXE (1 << 23)
152#define STS2_RSPIDXE (1 << 22)
153#define STS2_CCSTO (1 << 15)
154#define STS2_RDATTO (1 << 14)
155#define STS2_DATBSYTO (1 << 13)
156#define STS2_CRCSTTO (1 << 12)
157#define STS2_AC12BSYTO (1 << 11)
158#define STS2_RSPBSYTO (1 << 10)
159#define STS2_AC12RSPTO (1 << 9)
160#define STS2_RSPTO (1 << 8)
161#define STS2_CRC_ERR (STS2_CRCSTE | STS2_CRC16E | \
162 STS2_AC12CRCE | STS2_RSPCRC7E | STS2_CRCSTEBE)
163#define STS2_TIMEOUT_ERR (STS2_CCSTO | STS2_RDATTO | \
164 STS2_DATBSYTO | STS2_CRCSTTO | \
165 STS2_AC12BSYTO | STS2_RSPBSYTO | \
166 STS2_AC12RSPTO | STS2_RSPTO)
167
168/* CE_VERSION */
169#define SOFT_RST_ON (1 << 31)
170#define SOFT_RST_OFF (0 << 31)
171
172#define CLKDEV_EMMC_DATA 52000000 /* 52MHz */
173#define CLKDEV_MMC_DATA 20000000 /* 20MHz */
174#define CLKDEV_INIT 400000 /* 400 KHz */
175
176struct sh_mmcif_host {
177 struct mmc_host *mmc;
178 struct mmc_data *data;
179 struct mmc_command *cmd;
180 struct platform_device *pd;
181 struct clk *hclk;
182 unsigned int clk;
183 int bus_width;
184 u16 wait_int;
185 u16 sd_error;
186 long timeout;
187 void __iomem *addr;
188 wait_queue_head_t intr_wait;
189};
190
191
192static inline void sh_mmcif_bitset(struct sh_mmcif_host *host,
193 unsigned int reg, u32 val)
194{
195 writel(val | readl(host->addr + reg), host->addr + reg);
196}
197
198static inline void sh_mmcif_bitclr(struct sh_mmcif_host *host,
199 unsigned int reg, u32 val)
200{
201 writel(~val & readl(host->addr + reg), host->addr + reg);
202}
203
204
205static void sh_mmcif_clock_control(struct sh_mmcif_host *host, unsigned int clk)
206{
207 struct sh_mmcif_plat_data *p = host->pd->dev.platform_data;
208
209 sh_mmcif_bitclr(host, MMCIF_CE_CLK_CTRL, CLK_ENABLE);
210 sh_mmcif_bitclr(host, MMCIF_CE_CLK_CTRL, CLK_CLEAR);
211
212 if (!clk)
213 return;
214 if (p->sup_pclk && clk == host->clk)
215 sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_SUP_PCLK);
216 else
217 sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_CLEAR &
218 (ilog2(__rounddown_pow_of_two(host->clk / clk)) << 16));
219
220 sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_ENABLE);
221}
222
223static void sh_mmcif_sync_reset(struct sh_mmcif_host *host)
224{
225 u32 tmp;
226
227 tmp = 0x010f0000 & sh_mmcif_readl(host->addr, MMCIF_CE_CLK_CTRL);
228
229 sh_mmcif_writel(host->addr, MMCIF_CE_VERSION, SOFT_RST_ON);
230 sh_mmcif_writel(host->addr, MMCIF_CE_VERSION, SOFT_RST_OFF);
231 sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, tmp |
232 SRSPTO_256 | SRBSYTO_29 | SRWDTO_29 | SCCSTO_29);
233 /* byte swap on */
234 sh_mmcif_bitset(host, MMCIF_CE_BUF_ACC, BUF_ACC_ATYP);
235}
236
237static int sh_mmcif_error_manage(struct sh_mmcif_host *host)
238{
239 u32 state1, state2;
240 int ret, timeout = 10000000;
241
242 host->sd_error = 0;
243 host->wait_int = 0;
244
245 state1 = sh_mmcif_readl(host->addr, MMCIF_CE_HOST_STS1);
246 state2 = sh_mmcif_readl(host->addr, MMCIF_CE_HOST_STS2);
247 pr_debug("%s: ERR HOST_STS1 = %08x\n", DRIVER_NAME, state1);
248 pr_debug("%s: ERR HOST_STS2 = %08x\n", DRIVER_NAME, state2);
249
250 if (state1 & STS1_CMDSEQ) {
251 sh_mmcif_bitset(host, MMCIF_CE_CMD_CTRL, CMD_CTRL_BREAK);
252 sh_mmcif_bitset(host, MMCIF_CE_CMD_CTRL, ~CMD_CTRL_BREAK);
253 while (1) {
254 timeout--;
255 if (timeout < 0) {
256 pr_err(DRIVER_NAME": Forceed end of " \
257 "command sequence timeout err\n");
258 return -EIO;
259 }
260 if (!(sh_mmcif_readl(host->addr, MMCIF_CE_HOST_STS1)
261 & STS1_CMDSEQ))
262 break;
263 mdelay(1);
264 }
265 sh_mmcif_sync_reset(host);
266 pr_debug(DRIVER_NAME": Forced end of command sequence\n");
267 return -EIO;
268 }
269
270 if (state2 & STS2_CRC_ERR) {
271 pr_debug(DRIVER_NAME": Happened CRC error\n");
272 ret = -EIO;
273 } else if (state2 & STS2_TIMEOUT_ERR) {
274 pr_debug(DRIVER_NAME": Happened Timeout error\n");
275 ret = -ETIMEDOUT;
276 } else {
277 pr_debug(DRIVER_NAME": Happened End/Index error\n");
278 ret = -EIO;
279 }
280 return ret;
281}
282
283static int sh_mmcif_single_read(struct sh_mmcif_host *host,
284 struct mmc_request *mrq)
285{
286 struct mmc_data *data = mrq->data;
287 long time;
288 u32 blocksize, i, *p = sg_virt(data->sg);
289
290 host->wait_int = 0;
291
292 /* buf read enable */
293 sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN);
294 time = wait_event_interruptible_timeout(host->intr_wait,
295 host->wait_int == 1 ||
296 host->sd_error == 1, host->timeout);
297 if (host->wait_int != 1 && (time == 0 || host->sd_error != 0))
298 return sh_mmcif_error_manage(host);
299
300 host->wait_int = 0;
301 blocksize = (BLOCK_SIZE_MASK &
302 sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET)) + 3;
303 for (i = 0; i < blocksize / 4; i++)
304 *p++ = sh_mmcif_readl(host->addr, MMCIF_CE_DATA);
305
306 /* buffer read end */
307 sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFRE);
308 time = wait_event_interruptible_timeout(host->intr_wait,
309 host->wait_int == 1 ||
310 host->sd_error == 1, host->timeout);
311 if (host->wait_int != 1 && (time == 0 || host->sd_error != 0))
312 return sh_mmcif_error_manage(host);
313
314 host->wait_int = 0;
315 return 0;
316}
317
318static int sh_mmcif_multi_read(struct sh_mmcif_host *host,
319 struct mmc_request *mrq)
320{
321 struct mmc_data *data = mrq->data;
322 long time;
323 u32 blocksize, i, j, sec, *p;
324
325 blocksize = BLOCK_SIZE_MASK & sh_mmcif_readl(host->addr,
326 MMCIF_CE_BLOCK_SET);
327 for (j = 0; j < data->sg_len; j++) {
328 p = sg_virt(data->sg);
329 host->wait_int = 0;
330 for (sec = 0; sec < data->sg->length / blocksize; sec++) {
331 sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN);
332 /* buf read enable */
333 time = wait_event_interruptible_timeout(host->intr_wait,
334 host->wait_int == 1 ||
335 host->sd_error == 1, host->timeout);
336
337 if (host->wait_int != 1 &&
338 (time == 0 || host->sd_error != 0))
339 return sh_mmcif_error_manage(host);
340
341 host->wait_int = 0;
342 for (i = 0; i < blocksize / 4; i++)
343 *p++ = sh_mmcif_readl(host->addr,
344 MMCIF_CE_DATA);
345 }
346 if (j < data->sg_len - 1)
347 data->sg++;
348 }
349 return 0;
350}
351
352static int sh_mmcif_single_write(struct sh_mmcif_host *host,
353 struct mmc_request *mrq)
354{
355 struct mmc_data *data = mrq->data;
356 long time;
357 u32 blocksize, i, *p = sg_virt(data->sg);
358
359 host->wait_int = 0;
360 sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN);
361
362 /* buf write enable */
363 time = wait_event_interruptible_timeout(host->intr_wait,
364 host->wait_int == 1 ||
365 host->sd_error == 1, host->timeout);
366 if (host->wait_int != 1 && (time == 0 || host->sd_error != 0))
367 return sh_mmcif_error_manage(host);
368
369 host->wait_int = 0;
370 blocksize = (BLOCK_SIZE_MASK &
371 sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET)) + 3;
372 for (i = 0; i < blocksize / 4; i++)
373 sh_mmcif_writel(host->addr, MMCIF_CE_DATA, *p++);
374
375 /* buffer write end */
376 sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MDTRANE);
377
378 time = wait_event_interruptible_timeout(host->intr_wait,
379 host->wait_int == 1 ||
380 host->sd_error == 1, host->timeout);
381 if (host->wait_int != 1 && (time == 0 || host->sd_error != 0))
382 return sh_mmcif_error_manage(host);
383
384 host->wait_int = 0;
385 return 0;
386}
387
388static int sh_mmcif_multi_write(struct sh_mmcif_host *host,
389 struct mmc_request *mrq)
390{
391 struct mmc_data *data = mrq->data;
392 long time;
393 u32 i, sec, j, blocksize, *p;
394
395 blocksize = BLOCK_SIZE_MASK & sh_mmcif_readl(host->addr,
396 MMCIF_CE_BLOCK_SET);
397
398 for (j = 0; j < data->sg_len; j++) {
399 p = sg_virt(data->sg);
400 host->wait_int = 0;
401 for (sec = 0; sec < data->sg->length / blocksize; sec++) {
402 sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN);
403 /* buf write enable*/
404 time = wait_event_interruptible_timeout(host->intr_wait,
405 host->wait_int == 1 ||
406 host->sd_error == 1, host->timeout);
407
408 if (host->wait_int != 1 &&
409 (time == 0 || host->sd_error != 0))
410 return sh_mmcif_error_manage(host);
411
412 host->wait_int = 0;
413 for (i = 0; i < blocksize / 4; i++)
414 sh_mmcif_writel(host->addr,
415 MMCIF_CE_DATA, *p++);
416 }
417 if (j < data->sg_len - 1)
418 data->sg++;
419 }
420 return 0;
421}
422
423static void sh_mmcif_get_response(struct sh_mmcif_host *host,
424 struct mmc_command *cmd)
425{
426 if (cmd->flags & MMC_RSP_136) {
427 cmd->resp[0] = sh_mmcif_readl(host->addr, MMCIF_CE_RESP3);
428 cmd->resp[1] = sh_mmcif_readl(host->addr, MMCIF_CE_RESP2);
429 cmd->resp[2] = sh_mmcif_readl(host->addr, MMCIF_CE_RESP1);
430 cmd->resp[3] = sh_mmcif_readl(host->addr, MMCIF_CE_RESP0);
431 } else
432 cmd->resp[0] = sh_mmcif_readl(host->addr, MMCIF_CE_RESP0);
433}
434
435static void sh_mmcif_get_cmd12response(struct sh_mmcif_host *host,
436 struct mmc_command *cmd)
437{
438 cmd->resp[0] = sh_mmcif_readl(host->addr, MMCIF_CE_RESP_CMD12);
439}
440
441static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host,
442 struct mmc_request *mrq, struct mmc_command *cmd, u32 opc)
443{
444 u32 tmp = 0;
445
446 /* Response Type check */
447 switch (mmc_resp_type(cmd)) {
448 case MMC_RSP_NONE:
449 tmp |= CMD_SET_RTYP_NO;
450 break;
451 case MMC_RSP_R1:
452 case MMC_RSP_R1B:
453 case MMC_RSP_R3:
454 tmp |= CMD_SET_RTYP_6B;
455 break;
456 case MMC_RSP_R2:
457 tmp |= CMD_SET_RTYP_17B;
458 break;
459 default:
460 pr_err(DRIVER_NAME": Not support type response.\n");
461 break;
462 }
463 switch (opc) {
464 /* RBSY */
465 case MMC_SWITCH:
466 case MMC_STOP_TRANSMISSION:
467 case MMC_SET_WRITE_PROT:
468 case MMC_CLR_WRITE_PROT:
469 case MMC_ERASE:
470 case MMC_GEN_CMD:
471 tmp |= CMD_SET_RBSY;
472 break;
473 }
474 /* WDAT / DATW */
475 if (host->data) {
476 tmp |= CMD_SET_WDAT;
477 switch (host->bus_width) {
478 case MMC_BUS_WIDTH_1:
479 tmp |= CMD_SET_DATW_1;
480 break;
481 case MMC_BUS_WIDTH_4:
482 tmp |= CMD_SET_DATW_4;
483 break;
484 case MMC_BUS_WIDTH_8:
485 tmp |= CMD_SET_DATW_8;
486 break;
487 default:
488 pr_err(DRIVER_NAME": Not support bus width.\n");
489 break;
490 }
491 }
492 /* DWEN */
493 if (opc == MMC_WRITE_BLOCK || opc == MMC_WRITE_MULTIPLE_BLOCK)
494 tmp |= CMD_SET_DWEN;
495 /* CMLTE/CMD12EN */
496 if (opc == MMC_READ_MULTIPLE_BLOCK || opc == MMC_WRITE_MULTIPLE_BLOCK) {
497 tmp |= CMD_SET_CMLTE | CMD_SET_CMD12EN;
498 sh_mmcif_bitset(host, MMCIF_CE_BLOCK_SET,
499 mrq->data->blocks << 16);
500 }
501 /* RIDXC[1:0] check bits */
502 if (opc == MMC_SEND_OP_COND || opc == MMC_ALL_SEND_CID ||
503 opc == MMC_SEND_CSD || opc == MMC_SEND_CID)
504 tmp |= CMD_SET_RIDXC_BITS;
505 /* RCRC7C[1:0] check bits */
506 if (opc == MMC_SEND_OP_COND)
507 tmp |= CMD_SET_CRC7C_BITS;
508 /* RCRC7C[1:0] internal CRC7 */
509 if (opc == MMC_ALL_SEND_CID ||
510 opc == MMC_SEND_CSD || opc == MMC_SEND_CID)
511 tmp |= CMD_SET_CRC7C_INTERNAL;
512
513 return opc = ((opc << 24) | tmp);
514}
515
516static u32 sh_mmcif_data_trans(struct sh_mmcif_host *host,
517 struct mmc_request *mrq, u32 opc)
518{
519 u32 ret;
520
521 switch (opc) {
522 case MMC_READ_MULTIPLE_BLOCK:
523 ret = sh_mmcif_multi_read(host, mrq);
524 break;
525 case MMC_WRITE_MULTIPLE_BLOCK:
526 ret = sh_mmcif_multi_write(host, mrq);
527 break;
528 case MMC_WRITE_BLOCK:
529 ret = sh_mmcif_single_write(host, mrq);
530 break;
531 case MMC_READ_SINGLE_BLOCK:
532 case MMC_SEND_EXT_CSD:
533 ret = sh_mmcif_single_read(host, mrq);
534 break;
535 default:
536 pr_err(DRIVER_NAME": NOT SUPPORT CMD = d'%08d\n", opc);
537 ret = -EINVAL;
538 break;
539 }
540 return ret;
541}
542
543static void sh_mmcif_start_cmd(struct sh_mmcif_host *host,
544 struct mmc_request *mrq, struct mmc_command *cmd)
545{
546 long time;
547 int ret = 0, mask = 0;
548 u32 opc = cmd->opcode;
549
550 host->cmd = cmd;
551
552 switch (opc) {
553 /* respons busy check */
554 case MMC_SWITCH:
555 case MMC_STOP_TRANSMISSION:
556 case MMC_SET_WRITE_PROT:
557 case MMC_CLR_WRITE_PROT:
558 case MMC_ERASE:
559 case MMC_GEN_CMD:
560 mask = MASK_MRBSYE;
561 break;
562 default:
563 mask = MASK_MCRSPE;
564 break;
565 }
566 mask |= MASK_MCMDVIO | MASK_MBUFVIO | MASK_MWDATERR |
567 MASK_MRDATERR | MASK_MRIDXERR | MASK_MRSPERR |
568 MASK_MCCSTO | MASK_MCRCSTO | MASK_MWDATTO |
569 MASK_MRDATTO | MASK_MRBSYTO | MASK_MRSPTO;
570
571 if (host->data) {
572 sh_mmcif_writel(host->addr, MMCIF_CE_BLOCK_SET, 0);
573 sh_mmcif_writel(host->addr, MMCIF_CE_BLOCK_SET,
574 mrq->data->blksz);
575 }
576 opc = sh_mmcif_set_cmd(host, mrq, cmd, opc);
577
578 sh_mmcif_writel(host->addr, MMCIF_CE_INT, 0xD80430C0);
579 sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, mask);
580 /* set arg */
581 sh_mmcif_writel(host->addr, MMCIF_CE_ARG, cmd->arg);
582 host->wait_int = 0;
583 /* set cmd */
584 sh_mmcif_writel(host->addr, MMCIF_CE_CMD_SET, opc);
585
586 time = wait_event_interruptible_timeout(host->intr_wait,
587 host->wait_int == 1 || host->sd_error == 1, host->timeout);
588 if (host->wait_int != 1 && time == 0) {
589 cmd->error = sh_mmcif_error_manage(host);
590 return;
591 }
592 if (host->sd_error) {
593 switch (cmd->opcode) {
594 case MMC_ALL_SEND_CID:
595 case MMC_SELECT_CARD:
596 case MMC_APP_CMD:
597 cmd->error = -ETIMEDOUT;
598 break;
599 default:
600 pr_debug("%s: Cmd(d'%d) err\n",
601 DRIVER_NAME, cmd->opcode);
602 cmd->error = sh_mmcif_error_manage(host);
603 break;
604 }
605 host->sd_error = 0;
606 host->wait_int = 0;
607 return;
608 }
609 if (!(cmd->flags & MMC_RSP_PRESENT)) {
610 cmd->error = ret;
611 host->wait_int = 0;
612 return;
613 }
614 if (host->wait_int == 1) {
615 sh_mmcif_get_response(host, cmd);
616 host->wait_int = 0;
617 }
618 if (host->data) {
619 ret = sh_mmcif_data_trans(host, mrq, cmd->opcode);
620 if (ret < 0)
621 mrq->data->bytes_xfered = 0;
622 else
623 mrq->data->bytes_xfered =
624 mrq->data->blocks * mrq->data->blksz;
625 }
626 cmd->error = ret;
627}
628
629static void sh_mmcif_stop_cmd(struct sh_mmcif_host *host,
630 struct mmc_request *mrq, struct mmc_command *cmd)
631{
632 long time;
633
634 if (mrq->cmd->opcode == MMC_READ_MULTIPLE_BLOCK)
635 sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MCMD12DRE);
636 else if (mrq->cmd->opcode == MMC_WRITE_MULTIPLE_BLOCK)
637 sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MCMD12RBE);
638 else {
639 pr_err(DRIVER_NAME": not support stop cmd\n");
640 cmd->error = sh_mmcif_error_manage(host);
641 return;
642 }
643
644 time = wait_event_interruptible_timeout(host->intr_wait,
645 host->wait_int == 1 ||
646 host->sd_error == 1, host->timeout);
647 if (host->wait_int != 1 && (time == 0 || host->sd_error != 0)) {
648 cmd->error = sh_mmcif_error_manage(host);
649 return;
650 }
651 sh_mmcif_get_cmd12response(host, cmd);
652 host->wait_int = 0;
653 cmd->error = 0;
654}
655
656static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq)
657{
658 struct sh_mmcif_host *host = mmc_priv(mmc);
659
660 switch (mrq->cmd->opcode) {
661 /* MMCIF does not support SD/SDIO command */
662 case SD_IO_SEND_OP_COND:
663 case MMC_APP_CMD:
664 mrq->cmd->error = -ETIMEDOUT;
665 mmc_request_done(mmc, mrq);
666 return;
667 case MMC_SEND_EXT_CSD: /* = SD_SEND_IF_COND (8) */
668 if (!mrq->data) {
669 /* send_if_cond cmd (not support) */
670 mrq->cmd->error = -ETIMEDOUT;
671 mmc_request_done(mmc, mrq);
672 return;
673 }
674 break;
675 default:
676 break;
677 }
678 host->data = mrq->data;
679 sh_mmcif_start_cmd(host, mrq, mrq->cmd);
680 host->data = NULL;
681
682 if (mrq->cmd->error != 0) {
683 mmc_request_done(mmc, mrq);
684 return;
685 }
686 if (mrq->stop)
687 sh_mmcif_stop_cmd(host, mrq, mrq->stop);
688 mmc_request_done(mmc, mrq);
689}
690
691static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
692{
693 struct sh_mmcif_host *host = mmc_priv(mmc);
694 struct sh_mmcif_plat_data *p = host->pd->dev.platform_data;
695
696 if (ios->power_mode == MMC_POWER_OFF) {
697 /* clock stop */
698 sh_mmcif_clock_control(host, 0);
699 if (p->down_pwr)
700 p->down_pwr(host->pd);
701 return;
702 } else if (ios->power_mode == MMC_POWER_UP) {
703 if (p->set_pwr)
704 p->set_pwr(host->pd, ios->power_mode);
705 }
706
707 if (ios->clock)
708 sh_mmcif_clock_control(host, ios->clock);
709
710 host->bus_width = ios->bus_width;
711}
712
713static struct mmc_host_ops sh_mmcif_ops = {
714 .request = sh_mmcif_request,
715 .set_ios = sh_mmcif_set_ios,
716};
717
718static void sh_mmcif_detect(struct mmc_host *mmc)
719{
720 mmc_detect_change(mmc, 0);
721}
722
723static irqreturn_t sh_mmcif_intr(int irq, void *dev_id)
724{
725 struct sh_mmcif_host *host = dev_id;
726 u32 state = 0;
727 int err = 0;
728
729 state = sh_mmcif_readl(host->addr, MMCIF_CE_INT);
730
731 if (state & INT_RBSYE) {
732 sh_mmcif_writel(host->addr, MMCIF_CE_INT,
733 ~(INT_RBSYE | INT_CRSPE));
734 sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MRBSYE);
735 } else if (state & INT_CRSPE) {
736 sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_CRSPE);
737 sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MCRSPE);
738 } else if (state & INT_BUFREN) {
739 sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_BUFREN);
740 sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MBUFREN);
741 } else if (state & INT_BUFWEN) {
742 sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_BUFWEN);
743 sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN);
744 } else if (state & INT_CMD12DRE) {
745 sh_mmcif_writel(host->addr, MMCIF_CE_INT,
746 ~(INT_CMD12DRE | INT_CMD12RBE |
747 INT_CMD12CRE | INT_BUFRE));
748 sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MCMD12DRE);
749 } else if (state & INT_BUFRE) {
750 sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_BUFRE);
751 sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MBUFRE);
752 } else if (state & INT_DTRANE) {
753 sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_DTRANE);
754 sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MDTRANE);
755 } else if (state & INT_CMD12RBE) {
756 sh_mmcif_writel(host->addr, MMCIF_CE_INT,
757 ~(INT_CMD12RBE | INT_CMD12CRE));
758 sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MCMD12RBE);
759 } else if (state & INT_ERR_STS) {
760 /* err interrupts */
761 sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~state);
762 sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state);
763 err = 1;
764 } else {
765 pr_debug("%s: Not support int\n", DRIVER_NAME);
766 sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~state);
767 sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state);
768 err = 1;
769 }
770 if (err) {
771 host->sd_error = 1;
772 pr_debug("%s: int err state = %08x\n", DRIVER_NAME, state);
773 }
774 host->wait_int = 1;
775 wake_up(&host->intr_wait);
776
777 return IRQ_HANDLED;
778}
779
780static int __devinit sh_mmcif_probe(struct platform_device *pdev)
781{
782 int ret = 0, irq[2];
783 struct mmc_host *mmc;
784 struct sh_mmcif_host *host = NULL;
785 struct sh_mmcif_plat_data *pd = NULL;
786 struct resource *res;
787 void __iomem *reg;
788 char clk_name[8];
789
790 irq[0] = platform_get_irq(pdev, 0);
791 irq[1] = platform_get_irq(pdev, 1);
792 if (irq[0] < 0 || irq[1] < 0) {
793 pr_err(DRIVER_NAME": Get irq error\n");
794 return -ENXIO;
795 }
796 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
797 if (!res) {
798 dev_err(&pdev->dev, "platform_get_resource error.\n");
799 return -ENXIO;
800 }
801 reg = ioremap(res->start, resource_size(res));
802 if (!reg) {
803 dev_err(&pdev->dev, "ioremap error.\n");
804 return -ENOMEM;
805 }
806 pd = (struct sh_mmcif_plat_data *)(pdev->dev.platform_data);
807 if (!pd) {
808 dev_err(&pdev->dev, "sh_mmcif plat data error.\n");
809 ret = -ENXIO;
810 goto clean_up;
811 }
812 mmc = mmc_alloc_host(sizeof(struct sh_mmcif_host), &pdev->dev);
813 if (!mmc) {
814 ret = -ENOMEM;
815 goto clean_up;
816 }
817 host = mmc_priv(mmc);
818 host->mmc = mmc;
819 host->addr = reg;
820 host->timeout = 1000;
821
822 snprintf(clk_name, sizeof(clk_name), "mmc%d", pdev->id);
823 host->hclk = clk_get(&pdev->dev, clk_name);
824 if (IS_ERR(host->hclk)) {
825 dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name);
826 ret = PTR_ERR(host->hclk);
827 goto clean_up1;
828 }
829 clk_enable(host->hclk);
830 host->clk = clk_get_rate(host->hclk);
831 host->pd = pdev;
832
833 init_waitqueue_head(&host->intr_wait);
834
835 mmc->ops = &sh_mmcif_ops;
836 mmc->f_max = host->clk;
837 /* close to 400KHz */
838 if (mmc->f_max < 51200000)
839 mmc->f_min = mmc->f_max / 128;
840 else if (mmc->f_max < 102400000)
841 mmc->f_min = mmc->f_max / 256;
842 else
843 mmc->f_min = mmc->f_max / 512;
844 if (pd->ocr)
845 mmc->ocr_avail = pd->ocr;
846 mmc->caps = MMC_CAP_MMC_HIGHSPEED;
847 if (pd->caps)
848 mmc->caps |= pd->caps;
849 mmc->max_phys_segs = 128;
850 mmc->max_hw_segs = 128;
851 mmc->max_blk_size = 512;
852 mmc->max_blk_count = 65535;
853 mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
854 mmc->max_seg_size = mmc->max_req_size;
855
856 sh_mmcif_sync_reset(host);
857 platform_set_drvdata(pdev, host);
858 mmc_add_host(mmc);
859
860 ret = request_irq(irq[0], sh_mmcif_intr, 0, "sh_mmc:error", host);
861 if (ret) {
862 pr_err(DRIVER_NAME": request_irq error (sh_mmc:error)\n");
863 goto clean_up2;
864 }
865 ret = request_irq(irq[1], sh_mmcif_intr, 0, "sh_mmc:int", host);
866 if (ret) {
867 free_irq(irq[0], host);
868 pr_err(DRIVER_NAME": request_irq error (sh_mmc:int)\n");
869 goto clean_up2;
870 }
871
872 sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
873 sh_mmcif_detect(host->mmc);
874
875 pr_info("%s: driver version %s\n", DRIVER_NAME, DRIVER_VERSION);
876 pr_debug("%s: chip ver H'%04x\n", DRIVER_NAME,
877 sh_mmcif_readl(host->addr, MMCIF_CE_VERSION) & 0x0000ffff);
878 return ret;
879
880clean_up2:
881 clk_disable(host->hclk);
882clean_up1:
883 mmc_free_host(mmc);
884clean_up:
885 if (reg)
886 iounmap(reg);
887 return ret;
888}
889
890static int __devexit sh_mmcif_remove(struct platform_device *pdev)
891{
892 struct sh_mmcif_host *host = platform_get_drvdata(pdev);
893 int irq[2];
894
895 sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
896
897 irq[0] = platform_get_irq(pdev, 0);
898 irq[1] = platform_get_irq(pdev, 1);
899
900 if (host->addr)
901 iounmap(host->addr);
902
903 platform_set_drvdata(pdev, NULL);
904 mmc_remove_host(host->mmc);
905
906 free_irq(irq[0], host);
907 free_irq(irq[1], host);
908
909 clk_disable(host->hclk);
910 mmc_free_host(host->mmc);
911
912 return 0;
913}
914
915static struct platform_driver sh_mmcif_driver = {
916 .probe = sh_mmcif_probe,
917 .remove = sh_mmcif_remove,
918 .driver = {
919 .name = DRIVER_NAME,
920 },
921};
922
923static int __init sh_mmcif_init(void)
924{
925 return platform_driver_register(&sh_mmcif_driver);
926}
927
928static void __exit sh_mmcif_exit(void)
929{
930 platform_driver_unregister(&sh_mmcif_driver);
931}
932
933module_init(sh_mmcif_init);
934module_exit(sh_mmcif_exit);
935
936
937MODULE_DESCRIPTION("SuperH on-chip MMC/eMMC interface driver");
938MODULE_LICENSE("GPL");
939MODULE_ALIAS(DRIVER_NAME);
940MODULE_AUTHOR("Yusuke Goda <yusuke.goda.sx@renesas.com>");
diff --git a/drivers/mmc/host/tifm_sd.c b/drivers/mmc/host/tifm_sd.c
index 82554ddec6b3..cec99958b652 100644
--- a/drivers/mmc/host/tifm_sd.c
+++ b/drivers/mmc/host/tifm_sd.c
@@ -1032,7 +1032,7 @@ static void tifm_sd_remove(struct tifm_dev *sock)
1032 1032
1033static int tifm_sd_suspend(struct tifm_dev *sock, pm_message_t state) 1033static int tifm_sd_suspend(struct tifm_dev *sock, pm_message_t state)
1034{ 1034{
1035 return mmc_suspend_host(tifm_get_drvdata(sock), state); 1035 return mmc_suspend_host(tifm_get_drvdata(sock));
1036} 1036}
1037 1037
1038static int tifm_sd_resume(struct tifm_dev *sock) 1038static int tifm_sd_resume(struct tifm_dev *sock)
diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c
index 883fcac21004..ee7d0a5a51c4 100644
--- a/drivers/mmc/host/tmio_mmc.c
+++ b/drivers/mmc/host/tmio_mmc.c
@@ -768,7 +768,7 @@ static int tmio_mmc_suspend(struct platform_device *dev, pm_message_t state)
768 struct mmc_host *mmc = platform_get_drvdata(dev); 768 struct mmc_host *mmc = platform_get_drvdata(dev);
769 int ret; 769 int ret;
770 770
771 ret = mmc_suspend_host(mmc, state); 771 ret = mmc_suspend_host(mmc);
772 772
773 /* Tell MFD core it can disable us now.*/ 773 /* Tell MFD core it can disable us now.*/
774 if (!ret && cell->disable) 774 if (!ret && cell->disable)
diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c
index 632858a94376..19f2d72dbca5 100644
--- a/drivers/mmc/host/via-sdmmc.c
+++ b/drivers/mmc/host/via-sdmmc.c
@@ -1280,7 +1280,7 @@ static int via_sd_suspend(struct pci_dev *pcidev, pm_message_t state)
1280 via_save_pcictrlreg(host); 1280 via_save_pcictrlreg(host);
1281 via_save_sdcreg(host); 1281 via_save_sdcreg(host);
1282 1282
1283 ret = mmc_suspend_host(host->mmc, state); 1283 ret = mmc_suspend_host(host->mmc);
1284 1284
1285 pci_save_state(pcidev); 1285 pci_save_state(pcidev);
1286 pci_enable_wake(pcidev, pci_choose_state(pcidev, state), 0); 1286 pci_enable_wake(pcidev, pci_choose_state(pcidev, state), 0);
diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c
index 69efe01eece8..0012f5d13d28 100644
--- a/drivers/mmc/host/wbsd.c
+++ b/drivers/mmc/host/wbsd.c
@@ -1819,7 +1819,7 @@ static int wbsd_suspend(struct wbsd_host *host, pm_message_t state)
1819{ 1819{
1820 BUG_ON(host == NULL); 1820 BUG_ON(host == NULL);
1821 1821
1822 return mmc_suspend_host(host->mmc, state); 1822 return mmc_suspend_host(host->mmc);
1823} 1823}
1824 1824
1825static int wbsd_resume(struct wbsd_host *host) 1825static int wbsd_resume(struct wbsd_host *host)
diff --git a/drivers/mtd/maps/pismo.c b/drivers/mtd/maps/pismo.c
index eb476b7f8d11..f4ce273e93fd 100644
--- a/drivers/mtd/maps/pismo.c
+++ b/drivers/mtd/maps/pismo.c
@@ -234,7 +234,6 @@ static int __devexit pismo_remove(struct i2c_client *client)
234 /* FIXME: set_vpp needs saner arguments */ 234 /* FIXME: set_vpp needs saner arguments */
235 pismo_setvpp_remove_fix(pismo); 235 pismo_setvpp_remove_fix(pismo);
236 236
237 i2c_set_clientdata(client, NULL);
238 kfree(pismo); 237 kfree(pismo);
239 238
240 return 0; 239 return 0;
@@ -286,7 +285,6 @@ static int __devinit pismo_probe(struct i2c_client *client,
286 return 0; 285 return 0;
287 286
288 exit_free: 287 exit_free:
289 i2c_set_clientdata(client, NULL);
290 kfree(pismo); 288 kfree(pismo);
291 return ret; 289 return ret;
292} 290}
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 000d65ea55a4..91c8013cf0d9 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -404,14 +404,9 @@ static int mtd_do_writeoob(struct file *file, struct mtd_info *mtd,
404 if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs)) 404 if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs))
405 return -EINVAL; 405 return -EINVAL;
406 406
407 ops.oobbuf = kmalloc(length, GFP_KERNEL); 407 ops.oobbuf = memdup_user(ptr, length);
408 if (!ops.oobbuf) 408 if (IS_ERR(ops.oobbuf))
409 return -ENOMEM; 409 return PTR_ERR(ops.oobbuf);
410
411 if (copy_from_user(ops.oobbuf, ptr, length)) {
412 kfree(ops.oobbuf);
413 return -EFAULT;
414 }
415 410
416 start &= ~((uint64_t)mtd->oobsize - 1); 411 start &= ~((uint64_t)mtd->oobsize - 1);
417 ret = mtd->write_oob(mtd, start, &ops); 412 ret = mtd->write_oob(mtd, start, &ops);
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 98a04b3c9526..ffc3720929f1 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -1,13 +1,3 @@
1menuconfig MTD_NAND
2 tristate "NAND Device Support"
3 depends on MTD
4 select MTD_NAND_IDS
5 select MTD_NAND_ECC
6 help
7 This enables support for accessing all type of NAND flash
8 devices. For further information see
9 <http://www.linux-mtd.infradead.org/doc/nand.html>.
10
11config MTD_NAND_ECC 1config MTD_NAND_ECC
12 tristate 2 tristate
13 3
@@ -19,6 +9,17 @@ config MTD_NAND_ECC_SMC
19 Software ECC according to the Smart Media Specification. 9 Software ECC according to the Smart Media Specification.
20 The original Linux implementation had byte 0 and 1 swapped. 10 The original Linux implementation had byte 0 and 1 swapped.
21 11
12
13menuconfig MTD_NAND
14 tristate "NAND Device Support"
15 depends on MTD
16 select MTD_NAND_IDS
17 select MTD_NAND_ECC
18 help
19 This enables support for accessing all type of NAND flash
20 devices. For further information see
21 <http://www.linux-mtd.infradead.org/doc/nand.html>.
22
22if MTD_NAND 23if MTD_NAND
23 24
24config MTD_NAND_VERIFY_WRITE 25config MTD_NAND_VERIFY_WRITE
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
index 00aea6f7d1f1..1312eda57ba6 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -232,7 +232,7 @@ static int __devinit fun_probe(struct of_device *ofdev,
232 if (!fun) 232 if (!fun)
233 return -ENOMEM; 233 return -ENOMEM;
234 234
235 ret = of_address_to_resource(ofdev->node, 0, &io_res); 235 ret = of_address_to_resource(ofdev->dev.of_node, 0, &io_res);
236 if (ret) { 236 if (ret) {
237 dev_err(&ofdev->dev, "can't get IO base\n"); 237 dev_err(&ofdev->dev, "can't get IO base\n");
238 goto err1; 238 goto err1;
@@ -244,7 +244,8 @@ static int __devinit fun_probe(struct of_device *ofdev,
244 goto err1; 244 goto err1;
245 } 245 }
246 246
247 prop = of_get_property(ofdev->node, "fsl,upm-addr-offset", &size); 247 prop = of_get_property(ofdev->dev.of_node, "fsl,upm-addr-offset",
248 &size);
248 if (!prop || size != sizeof(uint32_t)) { 249 if (!prop || size != sizeof(uint32_t)) {
249 dev_err(&ofdev->dev, "can't get UPM address offset\n"); 250 dev_err(&ofdev->dev, "can't get UPM address offset\n");
250 ret = -EINVAL; 251 ret = -EINVAL;
@@ -252,7 +253,7 @@ static int __devinit fun_probe(struct of_device *ofdev,
252 } 253 }
253 fun->upm_addr_offset = *prop; 254 fun->upm_addr_offset = *prop;
254 255
255 prop = of_get_property(ofdev->node, "fsl,upm-cmd-offset", &size); 256 prop = of_get_property(ofdev->dev.of_node, "fsl,upm-cmd-offset", &size);
256 if (!prop || size != sizeof(uint32_t)) { 257 if (!prop || size != sizeof(uint32_t)) {
257 dev_err(&ofdev->dev, "can't get UPM command offset\n"); 258 dev_err(&ofdev->dev, "can't get UPM command offset\n");
258 ret = -EINVAL; 259 ret = -EINVAL;
@@ -260,7 +261,7 @@ static int __devinit fun_probe(struct of_device *ofdev,
260 } 261 }
261 fun->upm_cmd_offset = *prop; 262 fun->upm_cmd_offset = *prop;
262 263
263 prop = of_get_property(ofdev->node, 264 prop = of_get_property(ofdev->dev.of_node,
264 "fsl,upm-addr-line-cs-offsets", &size); 265 "fsl,upm-addr-line-cs-offsets", &size);
265 if (prop && (size / sizeof(uint32_t)) > 0) { 266 if (prop && (size / sizeof(uint32_t)) > 0) {
266 fun->mchip_count = size / sizeof(uint32_t); 267 fun->mchip_count = size / sizeof(uint32_t);
@@ -276,7 +277,7 @@ static int __devinit fun_probe(struct of_device *ofdev,
276 277
277 for (i = 0; i < fun->mchip_count; i++) { 278 for (i = 0; i < fun->mchip_count; i++) {
278 fun->rnb_gpio[i] = -1; 279 fun->rnb_gpio[i] = -1;
279 rnb_gpio = of_get_gpio(ofdev->node, i); 280 rnb_gpio = of_get_gpio(ofdev->dev.of_node, i);
280 if (rnb_gpio >= 0) { 281 if (rnb_gpio >= 0) {
281 ret = gpio_request(rnb_gpio, dev_name(&ofdev->dev)); 282 ret = gpio_request(rnb_gpio, dev_name(&ofdev->dev));
282 if (ret) { 283 if (ret) {
@@ -292,13 +293,13 @@ static int __devinit fun_probe(struct of_device *ofdev,
292 } 293 }
293 } 294 }
294 295
295 prop = of_get_property(ofdev->node, "chip-delay", NULL); 296 prop = of_get_property(ofdev->dev.of_node, "chip-delay", NULL);
296 if (prop) 297 if (prop)
297 fun->chip_delay = *prop; 298 fun->chip_delay = *prop;
298 else 299 else
299 fun->chip_delay = 50; 300 fun->chip_delay = 50;
300 301
301 prop = of_get_property(ofdev->node, "fsl,upm-wait-flags", &size); 302 prop = of_get_property(ofdev->dev.of_node, "fsl,upm-wait-flags", &size);
302 if (prop && size == sizeof(uint32_t)) 303 if (prop && size == sizeof(uint32_t))
303 fun->wait_flags = *prop; 304 fun->wait_flags = *prop;
304 else 305 else
@@ -315,7 +316,7 @@ static int __devinit fun_probe(struct of_device *ofdev,
315 fun->dev = &ofdev->dev; 316 fun->dev = &ofdev->dev;
316 fun->last_ctrl = NAND_CLE; 317 fun->last_ctrl = NAND_CLE;
317 318
318 ret = fun_chip_init(fun, ofdev->node, &io_res); 319 ret = fun_chip_init(fun, ofdev->dev.of_node, &io_res);
319 if (ret) 320 if (ret)
320 goto err2; 321 goto err2;
321 322
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index 3d0867d829cb..0a130dcaa129 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -650,7 +650,7 @@ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd)
650static int __devinit mpc5121_nfc_probe(struct of_device *op, 650static int __devinit mpc5121_nfc_probe(struct of_device *op,
651 const struct of_device_id *match) 651 const struct of_device_id *match)
652{ 652{
653 struct device_node *rootnode, *dn = op->node; 653 struct device_node *rootnode, *dn = op->dev.of_node;
654 struct device *dev = &op->dev; 654 struct device *dev = &op->dev;
655 struct mpc5121_nfc_prv *prv; 655 struct mpc5121_nfc_prv *prv;
656 struct resource res; 656 struct resource res;
@@ -889,12 +889,12 @@ static struct of_device_id mpc5121_nfc_match[] __devinitdata = {
889}; 889};
890 890
891static struct of_platform_driver mpc5121_nfc_driver = { 891static struct of_platform_driver mpc5121_nfc_driver = {
892 .match_table = mpc5121_nfc_match,
893 .probe = mpc5121_nfc_probe, 892 .probe = mpc5121_nfc_probe,
894 .remove = __devexit_p(mpc5121_nfc_remove), 893 .remove = __devexit_p(mpc5121_nfc_remove),
895 .driver = { 894 .driver = {
896 .name = DRV_NAME, 895 .name = DRV_NAME,
897 .owner = THIS_MODULE, 896 .owner = THIS_MODULE,
897 .of_match_table = mpc5121_nfc_match,
898 }, 898 },
899}; 899};
900 900
diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c
index 78a423295474..bcfc851fe550 100644
--- a/drivers/mtd/nand/r852.c
+++ b/drivers/mtd/nand/r852.c
@@ -150,7 +150,6 @@ static void r852_dma_done(struct r852_device *dev, int error)
150 if (dev->phys_dma_addr && dev->phys_dma_addr != dev->phys_bounce_buffer) 150 if (dev->phys_dma_addr && dev->phys_dma_addr != dev->phys_bounce_buffer)
151 pci_unmap_single(dev->pci_dev, dev->phys_dma_addr, R852_DMA_LEN, 151 pci_unmap_single(dev->pci_dev, dev->phys_dma_addr, R852_DMA_LEN,
152 dev->dma_dir ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); 152 dev->dma_dir ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
153 complete(&dev->dma_done);
154} 153}
155 154
156/* 155/*
@@ -182,6 +181,7 @@ static void r852_do_dma(struct r852_device *dev, uint8_t *buf, int do_read)
182 /* Set dma direction */ 181 /* Set dma direction */
183 dev->dma_dir = do_read; 182 dev->dma_dir = do_read;
184 dev->dma_stage = 1; 183 dev->dma_stage = 1;
184 INIT_COMPLETION(dev->dma_done);
185 185
186 dbg_verbose("doing dma %s ", do_read ? "read" : "write"); 186 dbg_verbose("doing dma %s ", do_read ? "read" : "write");
187 187
@@ -494,6 +494,11 @@ int r852_ecc_correct(struct mtd_info *mtd, uint8_t *dat,
494 if (dev->card_unstable) 494 if (dev->card_unstable)
495 return 0; 495 return 0;
496 496
497 if (dev->dma_error) {
498 dev->dma_error = 0;
499 return -1;
500 }
501
497 r852_write_reg(dev, R852_CTL, dev->ctlreg | R852_CTL_ECC_ACCESS); 502 r852_write_reg(dev, R852_CTL, dev->ctlreg | R852_CTL_ECC_ACCESS);
498 ecc_reg = r852_read_reg_dword(dev, R852_DATALINE); 503 ecc_reg = r852_read_reg_dword(dev, R852_DATALINE);
499 r852_write_reg(dev, R852_CTL, dev->ctlreg); 504 r852_write_reg(dev, R852_CTL, dev->ctlreg);
@@ -707,6 +712,7 @@ void r852_card_detect_work(struct work_struct *work)
707 container_of(work, struct r852_device, card_detect_work.work); 712 container_of(work, struct r852_device, card_detect_work.work);
708 713
709 r852_card_update_present(dev); 714 r852_card_update_present(dev);
715 r852_update_card_detect(dev);
710 dev->card_unstable = 0; 716 dev->card_unstable = 0;
711 717
712 /* False alarm */ 718 /* False alarm */
@@ -722,7 +728,6 @@ void r852_card_detect_work(struct work_struct *work)
722 else 728 else
723 r852_unregister_nand_device(dev); 729 r852_unregister_nand_device(dev);
724exit: 730exit:
725 /* Update detection logic */
726 r852_update_card_detect(dev); 731 r852_update_card_detect(dev);
727} 732}
728 733
@@ -796,6 +801,7 @@ static irqreturn_t r852_irq(int irq, void *data)
796 if (dma_status & R852_DMA_IRQ_ERROR) { 801 if (dma_status & R852_DMA_IRQ_ERROR) {
797 dbg("recieved dma error IRQ"); 802 dbg("recieved dma error IRQ");
798 r852_dma_done(dev, -EIO); 803 r852_dma_done(dev, -EIO);
804 complete(&dev->dma_done);
799 goto out; 805 goto out;
800 } 806 }
801 807
@@ -825,8 +831,10 @@ static irqreturn_t r852_irq(int irq, void *data)
825 r852_dma_enable(dev); 831 r852_dma_enable(dev);
826 832
827 /* Operation done */ 833 /* Operation done */
828 if (dev->dma_stage == 3) 834 if (dev->dma_stage == 3) {
829 r852_dma_done(dev, 0); 835 r852_dma_done(dev, 0);
836 complete(&dev->dma_done);
837 }
830 goto out; 838 goto out;
831 } 839 }
832 840
@@ -940,18 +948,19 @@ int r852_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
940 948
941 r852_dma_test(dev); 949 r852_dma_test(dev);
942 950
951 dev->irq = pci_dev->irq;
952 spin_lock_init(&dev->irqlock);
953
954 dev->card_detected = 0;
955 r852_card_update_present(dev);
956
943 /*register irq handler*/ 957 /*register irq handler*/
944 error = -ENODEV; 958 error = -ENODEV;
945 if (request_irq(pci_dev->irq, &r852_irq, IRQF_SHARED, 959 if (request_irq(pci_dev->irq, &r852_irq, IRQF_SHARED,
946 DRV_NAME, dev)) 960 DRV_NAME, dev))
947 goto error10; 961 goto error10;
948 962
949 dev->irq = pci_dev->irq;
950 spin_lock_init(&dev->irqlock);
951
952 /* kick initial present test */ 963 /* kick initial present test */
953 dev->card_detected = 0;
954 r852_card_update_present(dev);
955 queue_delayed_work(dev->card_workqueue, 964 queue_delayed_work(dev->card_workqueue,
956 &dev->card_detect_work, 0); 965 &dev->card_detect_work, 0);
957 966
@@ -1081,7 +1090,7 @@ int r852_resume(struct device *device)
1081 dev->card_detected ? "added" : "removed"); 1090 dev->card_detected ? "added" : "removed");
1082 1091
1083 queue_delayed_work(dev->card_workqueue, 1092 queue_delayed_work(dev->card_workqueue,
1084 &dev->card_detect_work, 1000); 1093 &dev->card_detect_work, msecs_to_jiffies(1000));
1085 return 0; 1094 return 0;
1086 } 1095 }
1087 1096
diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c
index 884852dc7eb4..cc728b12de82 100644
--- a/drivers/mtd/nand/socrates_nand.c
+++ b/drivers/mtd/nand/socrates_nand.c
@@ -183,7 +183,7 @@ static int __devinit socrates_nand_probe(struct of_device *ofdev,
183 return -ENOMEM; 183 return -ENOMEM;
184 } 184 }
185 185
186 host->io_base = of_iomap(ofdev->node, 0); 186 host->io_base = of_iomap(ofdev->dev.of_node, 0);
187 if (host->io_base == NULL) { 187 if (host->io_base == NULL) {
188 printk(KERN_ERR "socrates_nand: ioremap failed\n"); 188 printk(KERN_ERR "socrates_nand: ioremap failed\n");
189 kfree(host); 189 kfree(host);
@@ -244,7 +244,7 @@ static int __devinit socrates_nand_probe(struct of_device *ofdev,
244#ifdef CONFIG_MTD_OF_PARTS 244#ifdef CONFIG_MTD_OF_PARTS
245 if (num_partitions == 0) { 245 if (num_partitions == 0) {
246 num_partitions = of_mtd_parse_partitions(&ofdev->dev, 246 num_partitions = of_mtd_parse_partitions(&ofdev->dev,
247 ofdev->node, 247 ofdev->dev.of_node,
248 &partitions); 248 &partitions);
249 if (num_partitions < 0) { 249 if (num_partitions < 0) {
250 res = num_partitions; 250 res = num_partitions;
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c
index 72ebb3f06b86..4dfa6b90c21c 100644
--- a/drivers/mtd/ubi/cdev.c
+++ b/drivers/mtd/ubi/cdev.c
@@ -189,8 +189,7 @@ static loff_t vol_cdev_llseek(struct file *file, loff_t offset, int origin)
189 return new_offset; 189 return new_offset;
190} 190}
191 191
192static int vol_cdev_fsync(struct file *file, struct dentry *dentry, 192static int vol_cdev_fsync(struct file *file, int datasync)
193 int datasync)
194{ 193{
195 struct ubi_volume_desc *desc = file->private_data; 194 struct ubi_volume_desc *desc = file->private_data;
196 struct ubi_device *ubi = desc->vol->ubi; 195 struct ubi_device *ubi = desc->vol->ubi;
diff --git a/drivers/net/3c507.c b/drivers/net/3c507.c
index 82eaf65d2d85..ea9b7a098c9b 100644
--- a/drivers/net/3c507.c
+++ b/drivers/net/3c507.c
@@ -551,8 +551,7 @@ static irqreturn_t el16_interrupt(int irq, void *dev_id)
551 void __iomem *shmem; 551 void __iomem *shmem;
552 552
553 if (dev == NULL) { 553 if (dev == NULL) {
554 pr_err("%s: net_interrupt(): irq %d for unknown device.\n", 554 pr_err("net_interrupt(): irq %d for unknown device.\n", irq);
555 dev->name, irq);
556 return IRQ_NONE; 555 return IRQ_NONE;
557 } 556 }
558 557
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index 9c149750e2bf..284a5f4a63ac 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -598,8 +598,8 @@ rx_next:
598 goto rx_status_loop; 598 goto rx_status_loop;
599 599
600 spin_lock_irqsave(&cp->lock, flags); 600 spin_lock_irqsave(&cp->lock, flags);
601 cpw16_f(IntrMask, cp_intr_mask);
602 __napi_complete(napi); 601 __napi_complete(napi);
602 cpw16_f(IntrMask, cp_intr_mask);
603 spin_unlock_irqrestore(&cp->lock, flags); 603 spin_unlock_irqrestore(&cp->lock, flags);
604 } 604 }
605 605
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index 4ba72933f0da..97d8068b372b 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -860,6 +860,7 @@ retry:
860 } 860 }
861 861
862 /* if unknown chip, assume array element #0, original RTL-8139 in this case */ 862 /* if unknown chip, assume array element #0, original RTL-8139 in this case */
863 i = 0;
863 dev_dbg(&pdev->dev, "unknown chip version, assuming RTL-8139\n"); 864 dev_dbg(&pdev->dev, "unknown chip version, assuming RTL-8139\n");
864 dev_dbg(&pdev->dev, "TxConfig = 0x%lx\n", RTL_R32 (TxConfig)); 865 dev_dbg(&pdev->dev, "TxConfig = 0x%lx\n", RTL_R32 (TxConfig));
865 tp->chipset = 0; 866 tp->chipset = 0;
@@ -2088,8 +2089,8 @@ static int rtl8139_poll(struct napi_struct *napi, int budget)
2088 * again when we think we are done. 2089 * again when we think we are done.
2089 */ 2090 */
2090 spin_lock_irqsave(&tp->lock, flags); 2091 spin_lock_irqsave(&tp->lock, flags);
2091 RTL_W16_F(IntrMask, rtl8139_intr_mask);
2092 __napi_complete(napi); 2092 __napi_complete(napi);
2093 RTL_W16_F(IntrMask, rtl8139_intr_mask);
2093 spin_unlock_irqrestore(&tp->lock, flags); 2094 spin_unlock_irqrestore(&tp->lock, flags);
2094 } 2095 }
2095 spin_unlock(&tp->rx_lock); 2096 spin_unlock(&tp->rx_lock);
diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c
index c911bfb55b19..b9ad799c719f 100644
--- a/drivers/net/benet/be_cmds.c
+++ b/drivers/net/benet/be_cmds.c
@@ -294,7 +294,7 @@ int be_cmd_POST(struct be_adapter *adapter)
294 } else { 294 } else {
295 return 0; 295 return 0;
296 } 296 }
297 } while (timeout < 20); 297 } while (timeout < 40);
298 298
299 dev_err(&adapter->pdev->dev, "POST timeout; stage=0x%x\n", stage); 299 dev_err(&adapter->pdev->dev, "POST timeout; stage=0x%x\n", stage);
300 return -1; 300 return -1;
@@ -1429,7 +1429,7 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
1429 wrb = wrb_from_mccq(adapter); 1429 wrb = wrb_from_mccq(adapter);
1430 if (!wrb) { 1430 if (!wrb) {
1431 status = -EBUSY; 1431 status = -EBUSY;
1432 goto err; 1432 goto err_unlock;
1433 } 1433 }
1434 req = cmd->va; 1434 req = cmd->va;
1435 sge = nonembedded_sgl(wrb); 1435 sge = nonembedded_sgl(wrb);
@@ -1457,7 +1457,10 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
1457 else 1457 else
1458 status = adapter->flash_status; 1458 status = adapter->flash_status;
1459 1459
1460err: 1460 return status;
1461
1462err_unlock:
1463 spin_unlock_bh(&adapter->mcc_lock);
1461 return status; 1464 return status;
1462} 1465}
1463 1466
@@ -1497,7 +1500,7 @@ err:
1497 return status; 1500 return status;
1498} 1501}
1499 1502
1500extern int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac, 1503int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
1501 struct be_dma_mem *nonemb_cmd) 1504 struct be_dma_mem *nonemb_cmd)
1502{ 1505{
1503 struct be_mcc_wrb *wrb; 1506 struct be_mcc_wrb *wrb;
@@ -1590,7 +1593,7 @@ int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
1590 1593
1591 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL, 1594 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
1592 OPCODE_LOWLEVEL_LOOPBACK_TEST, sizeof(*req)); 1595 OPCODE_LOWLEVEL_LOOPBACK_TEST, sizeof(*req));
1593 req->hdr.timeout = 4; 1596 req->hdr.timeout = cpu_to_le32(4);
1594 1597
1595 req->pattern = cpu_to_le64(pattern); 1598 req->pattern = cpu_to_le64(pattern);
1596 req->src_port = cpu_to_le32(port_num); 1599 req->src_port = cpu_to_le32(port_num);
@@ -1662,7 +1665,7 @@ err:
1662 return status; 1665 return status;
1663} 1666}
1664 1667
1665extern int be_cmd_get_seeprom_data(struct be_adapter *adapter, 1668int be_cmd_get_seeprom_data(struct be_adapter *adapter,
1666 struct be_dma_mem *nonemb_cmd) 1669 struct be_dma_mem *nonemb_cmd)
1667{ 1670{
1668 struct be_mcc_wrb *wrb; 1671 struct be_mcc_wrb *wrb;
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c
index aa065c71ddd8..54b14272f333 100644
--- a/drivers/net/benet/be_main.c
+++ b/drivers/net/benet/be_main.c
@@ -1861,7 +1861,7 @@ static int be_setup(struct be_adapter *adapter)
1861 goto if_destroy; 1861 goto if_destroy;
1862 } 1862 }
1863 vf++; 1863 vf++;
1864 } while (vf < num_vfs); 1864 }
1865 } else if (!be_physfn(adapter)) { 1865 } else if (!be_physfn(adapter)) {
1866 status = be_cmd_mac_addr_query(adapter, mac, 1866 status = be_cmd_mac_addr_query(adapter, mac,
1867 MAC_ADDRESS_TYPE_NETWORK, false, adapter->if_handle); 1867 MAC_ADDRESS_TYPE_NETWORK, false, adapter->if_handle);
diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c
index 39250b2ca886..959add2410bf 100644
--- a/drivers/net/bmac.c
+++ b/drivers/net/bmac.c
@@ -1654,8 +1654,11 @@ MODULE_DEVICE_TABLE (of, bmac_match);
1654 1654
1655static struct macio_driver bmac_driver = 1655static struct macio_driver bmac_driver =
1656{ 1656{
1657 .name = "bmac", 1657 .driver = {
1658 .match_table = bmac_match, 1658 .name = "bmac",
1659 .owner = THIS_MODULE,
1660 .of_match_table = bmac_match,
1661 },
1659 .probe = bmac_probe, 1662 .probe = bmac_probe,
1660 .remove = bmac_remove, 1663 .remove = bmac_remove,
1661#ifdef CONFIG_PM 1664#ifdef CONFIG_PM
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 188e356c30a3..949d7a9dcf92 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -247,6 +247,7 @@ static const struct flash_spec flash_5709 = {
247MODULE_DEVICE_TABLE(pci, bnx2_pci_tbl); 247MODULE_DEVICE_TABLE(pci, bnx2_pci_tbl);
248 248
249static void bnx2_init_napi(struct bnx2 *bp); 249static void bnx2_init_napi(struct bnx2 *bp);
250static void bnx2_del_napi(struct bnx2 *bp);
250 251
251static inline u32 bnx2_tx_avail(struct bnx2 *bp, struct bnx2_tx_ring_info *txr) 252static inline u32 bnx2_tx_avail(struct bnx2 *bp, struct bnx2_tx_ring_info *txr)
252{ 253{
@@ -6270,6 +6271,7 @@ open_err:
6270 bnx2_free_skbs(bp); 6271 bnx2_free_skbs(bp);
6271 bnx2_free_irq(bp); 6272 bnx2_free_irq(bp);
6272 bnx2_free_mem(bp); 6273 bnx2_free_mem(bp);
6274 bnx2_del_napi(bp);
6273 return rc; 6275 return rc;
6274} 6276}
6275 6277
@@ -6537,6 +6539,7 @@ bnx2_close(struct net_device *dev)
6537 bnx2_free_irq(bp); 6539 bnx2_free_irq(bp);
6538 bnx2_free_skbs(bp); 6540 bnx2_free_skbs(bp);
6539 bnx2_free_mem(bp); 6541 bnx2_free_mem(bp);
6542 bnx2_del_napi(bp);
6540 bp->link_up = 0; 6543 bp->link_up = 0;
6541 netif_carrier_off(bp->dev); 6544 netif_carrier_off(bp->dev);
6542 bnx2_set_power_state(bp, PCI_D3hot); 6545 bnx2_set_power_state(bp, PCI_D3hot);
@@ -8227,7 +8230,16 @@ bnx2_bus_string(struct bnx2 *bp, char *str)
8227 return str; 8230 return str;
8228} 8231}
8229 8232
8230static void __devinit 8233static void
8234bnx2_del_napi(struct bnx2 *bp)
8235{
8236 int i;
8237
8238 for (i = 0; i < bp->irq_nvecs; i++)
8239 netif_napi_del(&bp->bnx2_napi[i].napi);
8240}
8241
8242static void
8231bnx2_init_napi(struct bnx2 *bp) 8243bnx2_init_napi(struct bnx2 *bp)
8232{ 8244{
8233 int i; 8245 int i;
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index 05b751719bd5..2c5227c02fa0 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -63,6 +63,16 @@ config CAN_BFIN
63 To compile this driver as a module, choose M here: the 63 To compile this driver as a module, choose M here: the
64 module will be called bfin_can. 64 module will be called bfin_can.
65 65
66config CAN_JANZ_ICAN3
67 tristate "Janz VMOD-ICAN3 Intelligent CAN controller"
68 depends on CAN_DEV && MFD_JANZ_CMODIO
69 ---help---
70 Driver for Janz VMOD-ICAN3 Intelligent CAN controller module, which
71 connects to a MODULbus carrier board.
72
73 This driver can also be built as a module. If so, the module will be
74 called janz-ican3.ko.
75
66source "drivers/net/can/mscan/Kconfig" 76source "drivers/net/can/mscan/Kconfig"
67 77
68source "drivers/net/can/sja1000/Kconfig" 78source "drivers/net/can/sja1000/Kconfig"
diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
index 7a702f28d01c..9047cd066fea 100644
--- a/drivers/net/can/Makefile
+++ b/drivers/net/can/Makefile
@@ -15,5 +15,6 @@ obj-$(CONFIG_CAN_AT91) += at91_can.o
15obj-$(CONFIG_CAN_TI_HECC) += ti_hecc.o 15obj-$(CONFIG_CAN_TI_HECC) += ti_hecc.o
16obj-$(CONFIG_CAN_MCP251X) += mcp251x.o 16obj-$(CONFIG_CAN_MCP251X) += mcp251x.o
17obj-$(CONFIG_CAN_BFIN) += bfin_can.o 17obj-$(CONFIG_CAN_BFIN) += bfin_can.o
18obj-$(CONFIG_CAN_JANZ_ICAN3) += janz-ican3.o
18 19
19ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG 20ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c
new file mode 100644
index 000000000000..6e533dcc36c0
--- /dev/null
+++ b/drivers/net/can/janz-ican3.c
@@ -0,0 +1,1830 @@
1/*
2 * Janz MODULbus VMOD-ICAN3 CAN Interface Driver
3 *
4 * Copyright (c) 2010 Ira W. Snyder <iws@ovro.caltech.edu>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 */
11
12#include <linux/kernel.h>
13#include <linux/module.h>
14#include <linux/init.h>
15#include <linux/interrupt.h>
16#include <linux/delay.h>
17#include <linux/platform_device.h>
18
19#include <linux/netdevice.h>
20#include <linux/can.h>
21#include <linux/can/dev.h>
22#include <linux/can/error.h>
23
24#include <linux/mfd/janz.h>
25
26/* the DPM has 64k of memory, organized into 256x 256 byte pages */
27#define DPM_NUM_PAGES 256
28#define DPM_PAGE_SIZE 256
29#define DPM_PAGE_ADDR(p) ((p) * DPM_PAGE_SIZE)
30
31/* JANZ ICAN3 "old-style" host interface queue page numbers */
32#define QUEUE_OLD_CONTROL 0
33#define QUEUE_OLD_RB0 1
34#define QUEUE_OLD_RB1 2
35#define QUEUE_OLD_WB0 3
36#define QUEUE_OLD_WB1 4
37
38/* Janz ICAN3 "old-style" host interface control registers */
39#define MSYNC_PEER 0x00 /* ICAN only */
40#define MSYNC_LOCL 0x01 /* host only */
41#define TARGET_RUNNING 0x02
42
43#define MSYNC_RB0 0x01
44#define MSYNC_RB1 0x02
45#define MSYNC_RBLW 0x04
46#define MSYNC_RB_MASK (MSYNC_RB0 | MSYNC_RB1)
47
48#define MSYNC_WB0 0x10
49#define MSYNC_WB1 0x20
50#define MSYNC_WBLW 0x40
51#define MSYNC_WB_MASK (MSYNC_WB0 | MSYNC_WB1)
52
53/* Janz ICAN3 "new-style" host interface queue page numbers */
54#define QUEUE_TOHOST 5
55#define QUEUE_FROMHOST_MID 6
56#define QUEUE_FROMHOST_HIGH 7
57#define QUEUE_FROMHOST_LOW 8
58
59/* The first free page in the DPM is #9 */
60#define DPM_FREE_START 9
61
62/* Janz ICAN3 "new-style" and "fast" host interface descriptor flags */
63#define DESC_VALID 0x80
64#define DESC_WRAP 0x40
65#define DESC_INTERRUPT 0x20
66#define DESC_IVALID 0x10
67#define DESC_LEN(len) (len)
68
69/* Janz ICAN3 Firmware Messages */
70#define MSG_CONNECTI 0x02
71#define MSG_DISCONNECT 0x03
72#define MSG_IDVERS 0x04
73#define MSG_MSGLOST 0x05
74#define MSG_NEWHOSTIF 0x08
75#define MSG_INQUIRY 0x0a
76#define MSG_SETAFILMASK 0x10
77#define MSG_INITFDPMQUEUE 0x11
78#define MSG_HWCONF 0x12
79#define MSG_FMSGLOST 0x15
80#define MSG_CEVTIND 0x37
81#define MSG_CBTRREQ 0x41
82#define MSG_COFFREQ 0x42
83#define MSG_CONREQ 0x43
84#define MSG_CCONFREQ 0x47
85
86/*
87 * Janz ICAN3 CAN Inquiry Message Types
88 *
89 * NOTE: there appears to be a firmware bug here. You must send
90 * NOTE: INQUIRY_STATUS and expect to receive an INQUIRY_EXTENDED
91 * NOTE: response. The controller never responds to a message with
92 * NOTE: the INQUIRY_EXTENDED subspec :(
93 */
94#define INQUIRY_STATUS 0x00
95#define INQUIRY_TERMINATION 0x01
96#define INQUIRY_EXTENDED 0x04
97
98/* Janz ICAN3 CAN Set Acceptance Filter Mask Message Types */
99#define SETAFILMASK_REJECT 0x00
100#define SETAFILMASK_FASTIF 0x02
101
102/* Janz ICAN3 CAN Hardware Configuration Message Types */
103#define HWCONF_TERMINATE_ON 0x01
104#define HWCONF_TERMINATE_OFF 0x00
105
106/* Janz ICAN3 CAN Event Indication Message Types */
107#define CEVTIND_EI 0x01
108#define CEVTIND_DOI 0x02
109#define CEVTIND_LOST 0x04
110#define CEVTIND_FULL 0x08
111#define CEVTIND_BEI 0x10
112
113#define CEVTIND_CHIP_SJA1000 0x02
114
115#define ICAN3_BUSERR_QUOTA_MAX 255
116
117/* Janz ICAN3 CAN Frame Conversion */
118#define ICAN3_ECHO 0x10
119#define ICAN3_EFF_RTR 0x40
120#define ICAN3_SFF_RTR 0x10
121#define ICAN3_EFF 0x80
122
123#define ICAN3_CAN_TYPE_MASK 0x0f
124#define ICAN3_CAN_TYPE_SFF 0x00
125#define ICAN3_CAN_TYPE_EFF 0x01
126
127#define ICAN3_CAN_DLC_MASK 0x0f
128
129/*
130 * SJA1000 Status and Error Register Definitions
131 *
132 * Copied from drivers/net/can/sja1000/sja1000.h
133 */
134
135/* status register content */
136#define SR_BS 0x80
137#define SR_ES 0x40
138#define SR_TS 0x20
139#define SR_RS 0x10
140#define SR_TCS 0x08
141#define SR_TBS 0x04
142#define SR_DOS 0x02
143#define SR_RBS 0x01
144
145#define SR_CRIT (SR_BS|SR_ES)
146
147/* ECC register */
148#define ECC_SEG 0x1F
149#define ECC_DIR 0x20
150#define ECC_ERR 6
151#define ECC_BIT 0x00
152#define ECC_FORM 0x40
153#define ECC_STUFF 0x80
154#define ECC_MASK 0xc0
155
156/* Number of buffers for use in the "new-style" host interface */
157#define ICAN3_NEW_BUFFERS 16
158
159/* Number of buffers for use in the "fast" host interface */
160#define ICAN3_TX_BUFFERS 512
161#define ICAN3_RX_BUFFERS 1024
162
163/* SJA1000 Clock Input */
164#define ICAN3_CAN_CLOCK 8000000
165
166/* Driver Name */
167#define DRV_NAME "janz-ican3"
168
169/* DPM Control Registers -- starts at offset 0x100 in the MODULbus registers */
170struct ican3_dpm_control {
171 /* window address register */
172 u8 window_address;
173 u8 unused1;
174
175 /*
176 * Read access: clear interrupt from microcontroller
177 * Write access: send interrupt to microcontroller
178 */
179 u8 interrupt;
180 u8 unused2;
181
182 /* write-only: reset all hardware on the module */
183 u8 hwreset;
184 u8 unused3;
185
186 /* write-only: generate an interrupt to the TPU */
187 u8 tpuinterrupt;
188};
189
190struct ican3_dev {
191
192 /* must be the first member */
193 struct can_priv can;
194
195 /* CAN network device */
196 struct net_device *ndev;
197 struct napi_struct napi;
198
199 /* Device for printing */
200 struct device *dev;
201
202 /* module number */
203 unsigned int num;
204
205 /* base address of registers and IRQ */
206 struct janz_cmodio_onboard_regs __iomem *ctrl;
207 struct ican3_dpm_control __iomem *dpmctrl;
208 void __iomem *dpm;
209 int irq;
210
211 /* CAN bus termination status */
212 struct completion termination_comp;
213 bool termination_enabled;
214
215 /* CAN bus error status registers */
216 struct completion buserror_comp;
217 struct can_berr_counter bec;
218
219 /* old and new style host interface */
220 unsigned int iftype;
221
222 /*
223 * Any function which changes the current DPM page must hold this
224 * lock while it is performing data accesses. This ensures that the
225 * function will not be preempted and end up reading data from a
226 * different DPM page than it expects.
227 */
228 spinlock_t lock;
229
230 /* new host interface */
231 unsigned int rx_int;
232 unsigned int rx_num;
233 unsigned int tx_num;
234
235 /* fast host interface */
236 unsigned int fastrx_start;
237 unsigned int fastrx_int;
238 unsigned int fastrx_num;
239 unsigned int fasttx_start;
240 unsigned int fasttx_num;
241
242 /* first free DPM page */
243 unsigned int free_page;
244};
245
246struct ican3_msg {
247 u8 control;
248 u8 spec;
249 __le16 len;
250 u8 data[252];
251};
252
253struct ican3_new_desc {
254 u8 control;
255 u8 pointer;
256};
257
258struct ican3_fast_desc {
259 u8 control;
260 u8 command;
261 u8 data[14];
262};
263
264/* write to the window basic address register */
265static inline void ican3_set_page(struct ican3_dev *mod, unsigned int page)
266{
267 BUG_ON(page >= DPM_NUM_PAGES);
268 iowrite8(page, &mod->dpmctrl->window_address);
269}
270
271/*
272 * ICAN3 "old-style" host interface
273 */
274
275/*
276 * Recieve a message from the ICAN3 "old-style" firmware interface
277 *
278 * LOCKING: must hold mod->lock
279 *
280 * returns 0 on success, -ENOMEM when no message exists
281 */
282static int ican3_old_recv_msg(struct ican3_dev *mod, struct ican3_msg *msg)
283{
284 unsigned int mbox, mbox_page;
285 u8 locl, peer, xord;
286
287 /* get the MSYNC registers */
288 ican3_set_page(mod, QUEUE_OLD_CONTROL);
289 peer = ioread8(mod->dpm + MSYNC_PEER);
290 locl = ioread8(mod->dpm + MSYNC_LOCL);
291 xord = locl ^ peer;
292
293 if ((xord & MSYNC_RB_MASK) == 0x00) {
294 dev_dbg(mod->dev, "no mbox for reading\n");
295 return -ENOMEM;
296 }
297
298 /* find the first free mbox to read */
299 if ((xord & MSYNC_RB_MASK) == MSYNC_RB_MASK)
300 mbox = (xord & MSYNC_RBLW) ? MSYNC_RB0 : MSYNC_RB1;
301 else
302 mbox = (xord & MSYNC_RB0) ? MSYNC_RB0 : MSYNC_RB1;
303
304 /* copy the message */
305 mbox_page = (mbox == MSYNC_RB0) ? QUEUE_OLD_RB0 : QUEUE_OLD_RB1;
306 ican3_set_page(mod, mbox_page);
307 memcpy_fromio(msg, mod->dpm, sizeof(*msg));
308
309 /*
310 * notify the firmware that the read buffer is available
311 * for it to fill again
312 */
313 locl ^= mbox;
314
315 ican3_set_page(mod, QUEUE_OLD_CONTROL);
316 iowrite8(locl, mod->dpm + MSYNC_LOCL);
317 return 0;
318}
319
320/*
321 * Send a message through the "old-style" firmware interface
322 *
323 * LOCKING: must hold mod->lock
324 *
325 * returns 0 on success, -ENOMEM when no free space exists
326 */
327static int ican3_old_send_msg(struct ican3_dev *mod, struct ican3_msg *msg)
328{
329 unsigned int mbox, mbox_page;
330 u8 locl, peer, xord;
331
332 /* get the MSYNC registers */
333 ican3_set_page(mod, QUEUE_OLD_CONTROL);
334 peer = ioread8(mod->dpm + MSYNC_PEER);
335 locl = ioread8(mod->dpm + MSYNC_LOCL);
336 xord = locl ^ peer;
337
338 if ((xord & MSYNC_WB_MASK) == MSYNC_WB_MASK) {
339 dev_err(mod->dev, "no mbox for writing\n");
340 return -ENOMEM;
341 }
342
343 /* calculate a free mbox to use */
344 mbox = (xord & MSYNC_WB0) ? MSYNC_WB1 : MSYNC_WB0;
345
346 /* copy the message to the DPM */
347 mbox_page = (mbox == MSYNC_WB0) ? QUEUE_OLD_WB0 : QUEUE_OLD_WB1;
348 ican3_set_page(mod, mbox_page);
349 memcpy_toio(mod->dpm, msg, sizeof(*msg));
350
351 locl ^= mbox;
352 if (mbox == MSYNC_WB1)
353 locl |= MSYNC_WBLW;
354
355 ican3_set_page(mod, QUEUE_OLD_CONTROL);
356 iowrite8(locl, mod->dpm + MSYNC_LOCL);
357 return 0;
358}
359
360/*
361 * ICAN3 "new-style" Host Interface Setup
362 */
363
364static void __devinit ican3_init_new_host_interface(struct ican3_dev *mod)
365{
366 struct ican3_new_desc desc;
367 unsigned long flags;
368 void __iomem *dst;
369 int i;
370
371 spin_lock_irqsave(&mod->lock, flags);
372
373 /* setup the internal datastructures for RX */
374 mod->rx_num = 0;
375 mod->rx_int = 0;
376
377 /* tohost queue descriptors are in page 5 */
378 ican3_set_page(mod, QUEUE_TOHOST);
379 dst = mod->dpm;
380
381 /* initialize the tohost (rx) queue descriptors: pages 9-24 */
382 for (i = 0; i < ICAN3_NEW_BUFFERS; i++) {
383 desc.control = DESC_INTERRUPT | DESC_LEN(1); /* I L=1 */
384 desc.pointer = mod->free_page;
385
386 /* set wrap flag on last buffer */
387 if (i == ICAN3_NEW_BUFFERS - 1)
388 desc.control |= DESC_WRAP;
389
390 memcpy_toio(dst, &desc, sizeof(desc));
391 dst += sizeof(desc);
392 mod->free_page++;
393 }
394
395 /* fromhost (tx) mid queue descriptors are in page 6 */
396 ican3_set_page(mod, QUEUE_FROMHOST_MID);
397 dst = mod->dpm;
398
399 /* setup the internal datastructures for TX */
400 mod->tx_num = 0;
401
402 /* initialize the fromhost mid queue descriptors: pages 25-40 */
403 for (i = 0; i < ICAN3_NEW_BUFFERS; i++) {
404 desc.control = DESC_VALID | DESC_LEN(1); /* V L=1 */
405 desc.pointer = mod->free_page;
406
407 /* set wrap flag on last buffer */
408 if (i == ICAN3_NEW_BUFFERS - 1)
409 desc.control |= DESC_WRAP;
410
411 memcpy_toio(dst, &desc, sizeof(desc));
412 dst += sizeof(desc);
413 mod->free_page++;
414 }
415
416 /* fromhost hi queue descriptors are in page 7 */
417 ican3_set_page(mod, QUEUE_FROMHOST_HIGH);
418 dst = mod->dpm;
419
420 /* initialize only a single buffer in the fromhost hi queue (unused) */
421 desc.control = DESC_VALID | DESC_WRAP | DESC_LEN(1); /* VW L=1 */
422 desc.pointer = mod->free_page;
423 memcpy_toio(dst, &desc, sizeof(desc));
424 mod->free_page++;
425
426 /* fromhost low queue descriptors are in page 8 */
427 ican3_set_page(mod, QUEUE_FROMHOST_LOW);
428 dst = mod->dpm;
429
430 /* initialize only a single buffer in the fromhost low queue (unused) */
431 desc.control = DESC_VALID | DESC_WRAP | DESC_LEN(1); /* VW L=1 */
432 desc.pointer = mod->free_page;
433 memcpy_toio(dst, &desc, sizeof(desc));
434 mod->free_page++;
435
436 spin_unlock_irqrestore(&mod->lock, flags);
437}
438
439/*
440 * ICAN3 Fast Host Interface Setup
441 */
442
443static void __devinit ican3_init_fast_host_interface(struct ican3_dev *mod)
444{
445 struct ican3_fast_desc desc;
446 unsigned long flags;
447 unsigned int addr;
448 void __iomem *dst;
449 int i;
450
451 spin_lock_irqsave(&mod->lock, flags);
452
453 /* save the start recv page */
454 mod->fastrx_start = mod->free_page;
455 mod->fastrx_num = 0;
456 mod->fastrx_int = 0;
457
458 /* build a single fast tohost queue descriptor */
459 memset(&desc, 0, sizeof(desc));
460 desc.control = 0x00;
461 desc.command = 1;
462
463 /* build the tohost queue descriptor ring in memory */
464 addr = 0;
465 for (i = 0; i < ICAN3_RX_BUFFERS; i++) {
466
467 /* set the wrap bit on the last buffer */
468 if (i == ICAN3_RX_BUFFERS - 1)
469 desc.control |= DESC_WRAP;
470
471 /* switch to the correct page */
472 ican3_set_page(mod, mod->free_page);
473
474 /* copy the descriptor to the DPM */
475 dst = mod->dpm + addr;
476 memcpy_toio(dst, &desc, sizeof(desc));
477 addr += sizeof(desc);
478
479 /* move to the next page if necessary */
480 if (addr >= DPM_PAGE_SIZE) {
481 addr = 0;
482 mod->free_page++;
483 }
484 }
485
486 /* make sure we page-align the next queue */
487 if (addr != 0)
488 mod->free_page++;
489
490 /* save the start xmit page */
491 mod->fasttx_start = mod->free_page;
492 mod->fasttx_num = 0;
493
494 /* build a single fast fromhost queue descriptor */
495 memset(&desc, 0, sizeof(desc));
496 desc.control = DESC_VALID;
497 desc.command = 1;
498
499 /* build the fromhost queue descriptor ring in memory */
500 addr = 0;
501 for (i = 0; i < ICAN3_TX_BUFFERS; i++) {
502
503 /* set the wrap bit on the last buffer */
504 if (i == ICAN3_TX_BUFFERS - 1)
505 desc.control |= DESC_WRAP;
506
507 /* switch to the correct page */
508 ican3_set_page(mod, mod->free_page);
509
510 /* copy the descriptor to the DPM */
511 dst = mod->dpm + addr;
512 memcpy_toio(dst, &desc, sizeof(desc));
513 addr += sizeof(desc);
514
515 /* move to the next page if necessary */
516 if (addr >= DPM_PAGE_SIZE) {
517 addr = 0;
518 mod->free_page++;
519 }
520 }
521
522 spin_unlock_irqrestore(&mod->lock, flags);
523}
524
525/*
526 * ICAN3 "new-style" Host Interface Message Helpers
527 */
528
529/*
530 * LOCKING: must hold mod->lock
531 */
532static int ican3_new_send_msg(struct ican3_dev *mod, struct ican3_msg *msg)
533{
534 struct ican3_new_desc desc;
535 void __iomem *desc_addr = mod->dpm + (mod->tx_num * sizeof(desc));
536
537 /* switch to the fromhost mid queue, and read the buffer descriptor */
538 ican3_set_page(mod, QUEUE_FROMHOST_MID);
539 memcpy_fromio(&desc, desc_addr, sizeof(desc));
540
541 if (!(desc.control & DESC_VALID)) {
542 dev_dbg(mod->dev, "%s: no free buffers\n", __func__);
543 return -ENOMEM;
544 }
545
546 /* switch to the data page, copy the data */
547 ican3_set_page(mod, desc.pointer);
548 memcpy_toio(mod->dpm, msg, sizeof(*msg));
549
550 /* switch back to the descriptor, set the valid bit, write it back */
551 ican3_set_page(mod, QUEUE_FROMHOST_MID);
552 desc.control ^= DESC_VALID;
553 memcpy_toio(desc_addr, &desc, sizeof(desc));
554
555 /* update the tx number */
556 mod->tx_num = (desc.control & DESC_WRAP) ? 0 : (mod->tx_num + 1);
557 return 0;
558}
559
560/*
561 * LOCKING: must hold mod->lock
562 */
563static int ican3_new_recv_msg(struct ican3_dev *mod, struct ican3_msg *msg)
564{
565 struct ican3_new_desc desc;
566 void __iomem *desc_addr = mod->dpm + (mod->rx_num * sizeof(desc));
567
568 /* switch to the tohost queue, and read the buffer descriptor */
569 ican3_set_page(mod, QUEUE_TOHOST);
570 memcpy_fromio(&desc, desc_addr, sizeof(desc));
571
572 if (!(desc.control & DESC_VALID)) {
573 dev_dbg(mod->dev, "%s: no buffers to recv\n", __func__);
574 return -ENOMEM;
575 }
576
577 /* switch to the data page, copy the data */
578 ican3_set_page(mod, desc.pointer);
579 memcpy_fromio(msg, mod->dpm, sizeof(*msg));
580
581 /* switch back to the descriptor, toggle the valid bit, write it back */
582 ican3_set_page(mod, QUEUE_TOHOST);
583 desc.control ^= DESC_VALID;
584 memcpy_toio(desc_addr, &desc, sizeof(desc));
585
586 /* update the rx number */
587 mod->rx_num = (desc.control & DESC_WRAP) ? 0 : (mod->rx_num + 1);
588 return 0;
589}
590
591/*
592 * Message Send / Recv Helpers
593 */
594
595static int ican3_send_msg(struct ican3_dev *mod, struct ican3_msg *msg)
596{
597 unsigned long flags;
598 int ret;
599
600 spin_lock_irqsave(&mod->lock, flags);
601
602 if (mod->iftype == 0)
603 ret = ican3_old_send_msg(mod, msg);
604 else
605 ret = ican3_new_send_msg(mod, msg);
606
607 spin_unlock_irqrestore(&mod->lock, flags);
608 return ret;
609}
610
611static int ican3_recv_msg(struct ican3_dev *mod, struct ican3_msg *msg)
612{
613 unsigned long flags;
614 int ret;
615
616 spin_lock_irqsave(&mod->lock, flags);
617
618 if (mod->iftype == 0)
619 ret = ican3_old_recv_msg(mod, msg);
620 else
621 ret = ican3_new_recv_msg(mod, msg);
622
623 spin_unlock_irqrestore(&mod->lock, flags);
624 return ret;
625}
626
627/*
628 * Quick Pre-constructed Messages
629 */
630
631static int __devinit ican3_msg_connect(struct ican3_dev *mod)
632{
633 struct ican3_msg msg;
634
635 memset(&msg, 0, sizeof(msg));
636 msg.spec = MSG_CONNECTI;
637 msg.len = cpu_to_le16(0);
638
639 return ican3_send_msg(mod, &msg);
640}
641
642static int __devexit ican3_msg_disconnect(struct ican3_dev *mod)
643{
644 struct ican3_msg msg;
645
646 memset(&msg, 0, sizeof(msg));
647 msg.spec = MSG_DISCONNECT;
648 msg.len = cpu_to_le16(0);
649
650 return ican3_send_msg(mod, &msg);
651}
652
653static int __devinit ican3_msg_newhostif(struct ican3_dev *mod)
654{
655 struct ican3_msg msg;
656 int ret;
657
658 memset(&msg, 0, sizeof(msg));
659 msg.spec = MSG_NEWHOSTIF;
660 msg.len = cpu_to_le16(0);
661
662 /* If we're not using the old interface, switching seems bogus */
663 WARN_ON(mod->iftype != 0);
664
665 ret = ican3_send_msg(mod, &msg);
666 if (ret)
667 return ret;
668
669 /* mark the module as using the new host interface */
670 mod->iftype = 1;
671 return 0;
672}
673
674static int __devinit ican3_msg_fasthostif(struct ican3_dev *mod)
675{
676 struct ican3_msg msg;
677 unsigned int addr;
678
679 memset(&msg, 0, sizeof(msg));
680 msg.spec = MSG_INITFDPMQUEUE;
681 msg.len = cpu_to_le16(8);
682
683 /* write the tohost queue start address */
684 addr = DPM_PAGE_ADDR(mod->fastrx_start);
685 msg.data[0] = addr & 0xff;
686 msg.data[1] = (addr >> 8) & 0xff;
687 msg.data[2] = (addr >> 16) & 0xff;
688 msg.data[3] = (addr >> 24) & 0xff;
689
690 /* write the fromhost queue start address */
691 addr = DPM_PAGE_ADDR(mod->fasttx_start);
692 msg.data[4] = addr & 0xff;
693 msg.data[5] = (addr >> 8) & 0xff;
694 msg.data[6] = (addr >> 16) & 0xff;
695 msg.data[7] = (addr >> 24) & 0xff;
696
697 /* If we're not using the new interface yet, we cannot do this */
698 WARN_ON(mod->iftype != 1);
699
700 return ican3_send_msg(mod, &msg);
701}
702
703/*
704 * Setup the CAN filter to either accept or reject all
705 * messages from the CAN bus.
706 */
707static int __devinit ican3_set_id_filter(struct ican3_dev *mod, bool accept)
708{
709 struct ican3_msg msg;
710 int ret;
711
712 /* Standard Frame Format */
713 memset(&msg, 0, sizeof(msg));
714 msg.spec = MSG_SETAFILMASK;
715 msg.len = cpu_to_le16(5);
716 msg.data[0] = 0x00; /* IDLo LSB */
717 msg.data[1] = 0x00; /* IDLo MSB */
718 msg.data[2] = 0xff; /* IDHi LSB */
719 msg.data[3] = 0x07; /* IDHi MSB */
720
721 /* accept all frames for fast host if, or reject all frames */
722 msg.data[4] = accept ? SETAFILMASK_FASTIF : SETAFILMASK_REJECT;
723
724 ret = ican3_send_msg(mod, &msg);
725 if (ret)
726 return ret;
727
728 /* Extended Frame Format */
729 memset(&msg, 0, sizeof(msg));
730 msg.spec = MSG_SETAFILMASK;
731 msg.len = cpu_to_le16(13);
732 msg.data[0] = 0; /* MUX = 0 */
733 msg.data[1] = 0x00; /* IDLo LSB */
734 msg.data[2] = 0x00;
735 msg.data[3] = 0x00;
736 msg.data[4] = 0x20; /* IDLo MSB */
737 msg.data[5] = 0xff; /* IDHi LSB */
738 msg.data[6] = 0xff;
739 msg.data[7] = 0xff;
740 msg.data[8] = 0x3f; /* IDHi MSB */
741
742 /* accept all frames for fast host if, or reject all frames */
743 msg.data[9] = accept ? SETAFILMASK_FASTIF : SETAFILMASK_REJECT;
744
745 return ican3_send_msg(mod, &msg);
746}
747
748/*
749 * Bring the CAN bus online or offline
750 */
751static int ican3_set_bus_state(struct ican3_dev *mod, bool on)
752{
753 struct ican3_msg msg;
754
755 memset(&msg, 0, sizeof(msg));
756 msg.spec = on ? MSG_CONREQ : MSG_COFFREQ;
757 msg.len = cpu_to_le16(0);
758
759 return ican3_send_msg(mod, &msg);
760}
761
762static int ican3_set_termination(struct ican3_dev *mod, bool on)
763{
764 struct ican3_msg msg;
765
766 memset(&msg, 0, sizeof(msg));
767 msg.spec = MSG_HWCONF;
768 msg.len = cpu_to_le16(2);
769 msg.data[0] = 0x00;
770 msg.data[1] = on ? HWCONF_TERMINATE_ON : HWCONF_TERMINATE_OFF;
771
772 return ican3_send_msg(mod, &msg);
773}
774
775static int ican3_send_inquiry(struct ican3_dev *mod, u8 subspec)
776{
777 struct ican3_msg msg;
778
779 memset(&msg, 0, sizeof(msg));
780 msg.spec = MSG_INQUIRY;
781 msg.len = cpu_to_le16(2);
782 msg.data[0] = subspec;
783 msg.data[1] = 0x00;
784
785 return ican3_send_msg(mod, &msg);
786}
787
788static int ican3_set_buserror(struct ican3_dev *mod, u8 quota)
789{
790 struct ican3_msg msg;
791
792 memset(&msg, 0, sizeof(msg));
793 msg.spec = MSG_CCONFREQ;
794 msg.len = cpu_to_le16(2);
795 msg.data[0] = 0x00;
796 msg.data[1] = quota;
797
798 return ican3_send_msg(mod, &msg);
799}
800
801/*
802 * ICAN3 to Linux CAN Frame Conversion
803 */
804
805static void ican3_to_can_frame(struct ican3_dev *mod,
806 struct ican3_fast_desc *desc,
807 struct can_frame *cf)
808{
809 if ((desc->command & ICAN3_CAN_TYPE_MASK) == ICAN3_CAN_TYPE_SFF) {
810 if (desc->data[1] & ICAN3_SFF_RTR)
811 cf->can_id |= CAN_RTR_FLAG;
812
813 cf->can_id |= desc->data[0] << 3;
814 cf->can_id |= (desc->data[1] & 0xe0) >> 5;
815 cf->can_dlc = desc->data[1] & ICAN3_CAN_DLC_MASK;
816 memcpy(cf->data, &desc->data[2], sizeof(cf->data));
817 } else {
818 cf->can_dlc = desc->data[0] & ICAN3_CAN_DLC_MASK;
819 if (desc->data[0] & ICAN3_EFF_RTR)
820 cf->can_id |= CAN_RTR_FLAG;
821
822 if (desc->data[0] & ICAN3_EFF) {
823 cf->can_id |= CAN_EFF_FLAG;
824 cf->can_id |= desc->data[2] << 21; /* 28-21 */
825 cf->can_id |= desc->data[3] << 13; /* 20-13 */
826 cf->can_id |= desc->data[4] << 5; /* 12-5 */
827 cf->can_id |= (desc->data[5] & 0xf8) >> 3;
828 } else {
829 cf->can_id |= desc->data[2] << 3; /* 10-3 */
830 cf->can_id |= desc->data[3] >> 5; /* 2-0 */
831 }
832
833 memcpy(cf->data, &desc->data[6], sizeof(cf->data));
834 }
835}
836
837static void can_frame_to_ican3(struct ican3_dev *mod,
838 struct can_frame *cf,
839 struct ican3_fast_desc *desc)
840{
841 /* clear out any stale data in the descriptor */
842 memset(desc->data, 0, sizeof(desc->data));
843
844 /* we always use the extended format, with the ECHO flag set */
845 desc->command = ICAN3_CAN_TYPE_EFF;
846 desc->data[0] |= cf->can_dlc;
847 desc->data[1] |= ICAN3_ECHO;
848
849 if (cf->can_id & CAN_RTR_FLAG)
850 desc->data[0] |= ICAN3_EFF_RTR;
851
852 /* pack the id into the correct places */
853 if (cf->can_id & CAN_EFF_FLAG) {
854 desc->data[0] |= ICAN3_EFF;
855 desc->data[2] = (cf->can_id & 0x1fe00000) >> 21; /* 28-21 */
856 desc->data[3] = (cf->can_id & 0x001fe000) >> 13; /* 20-13 */
857 desc->data[4] = (cf->can_id & 0x00001fe0) >> 5; /* 12-5 */
858 desc->data[5] = (cf->can_id & 0x0000001f) << 3; /* 4-0 */
859 } else {
860 desc->data[2] = (cf->can_id & 0x7F8) >> 3; /* bits 10-3 */
861 desc->data[3] = (cf->can_id & 0x007) << 5; /* bits 2-0 */
862 }
863
864 /* copy the data bits into the descriptor */
865 memcpy(&desc->data[6], cf->data, sizeof(cf->data));
866}
867
868/*
869 * Interrupt Handling
870 */
871
872/*
873 * Handle an ID + Version message response from the firmware. We never generate
874 * this message in production code, but it is very useful when debugging to be
875 * able to display this message.
876 */
877static void ican3_handle_idvers(struct ican3_dev *mod, struct ican3_msg *msg)
878{
879 dev_dbg(mod->dev, "IDVERS response: %s\n", msg->data);
880}
881
882static void ican3_handle_msglost(struct ican3_dev *mod, struct ican3_msg *msg)
883{
884 struct net_device *dev = mod->ndev;
885 struct net_device_stats *stats = &dev->stats;
886 struct can_frame *cf;
887 struct sk_buff *skb;
888
889 /*
890 * Report that communication messages with the microcontroller firmware
891 * are being lost. These are never CAN frames, so we do not generate an
892 * error frame for userspace
893 */
894 if (msg->spec == MSG_MSGLOST) {
895 dev_err(mod->dev, "lost %d control messages\n", msg->data[0]);
896 return;
897 }
898
899 /*
900 * Oops, this indicates that we have lost messages in the fast queue,
901 * which are exclusively CAN messages. Our driver isn't reading CAN
902 * frames fast enough.
903 *
904 * We'll pretend that the SJA1000 told us that it ran out of buffer
905 * space, because there is not a better message for this.
906 */
907 skb = alloc_can_err_skb(dev, &cf);
908 if (skb) {
909 cf->can_id |= CAN_ERR_CRTL;
910 cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
911 stats->rx_errors++;
912 stats->rx_bytes += cf->can_dlc;
913 netif_rx(skb);
914 }
915}
916
917/*
918 * Handle CAN Event Indication Messages from the firmware
919 *
920 * The ICAN3 firmware provides the values of some SJA1000 registers when it
921 * generates this message. The code below is largely copied from the
922 * drivers/net/can/sja1000/sja1000.c file, and adapted as necessary
923 */
924static int ican3_handle_cevtind(struct ican3_dev *mod, struct ican3_msg *msg)
925{
926 struct net_device *dev = mod->ndev;
927 struct net_device_stats *stats = &dev->stats;
928 enum can_state state = mod->can.state;
929 u8 status, isrc, rxerr, txerr;
930 struct can_frame *cf;
931 struct sk_buff *skb;
932
933 /* we can only handle the SJA1000 part */
934 if (msg->data[1] != CEVTIND_CHIP_SJA1000) {
935 dev_err(mod->dev, "unable to handle errors on non-SJA1000\n");
936 return -ENODEV;
937 }
938
939 /* check the message length for sanity */
940 if (le16_to_cpu(msg->len) < 6) {
941 dev_err(mod->dev, "error message too short\n");
942 return -EINVAL;
943 }
944
945 skb = alloc_can_err_skb(dev, &cf);
946 if (skb == NULL)
947 return -ENOMEM;
948
949 isrc = msg->data[0];
950 status = msg->data[3];
951 rxerr = msg->data[4];
952 txerr = msg->data[5];
953
954 /* data overrun interrupt */
955 if (isrc == CEVTIND_DOI || isrc == CEVTIND_LOST) {
956 dev_dbg(mod->dev, "data overrun interrupt\n");
957 cf->can_id |= CAN_ERR_CRTL;
958 cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
959 stats->rx_over_errors++;
960 stats->rx_errors++;
961 }
962
963 /* error warning + passive interrupt */
964 if (isrc == CEVTIND_EI) {
965 dev_dbg(mod->dev, "error warning + passive interrupt\n");
966 if (status & SR_BS) {
967 state = CAN_STATE_BUS_OFF;
968 cf->can_id |= CAN_ERR_BUSOFF;
969 can_bus_off(dev);
970 } else if (status & SR_ES) {
971 if (rxerr >= 128 || txerr >= 128)
972 state = CAN_STATE_ERROR_PASSIVE;
973 else
974 state = CAN_STATE_ERROR_WARNING;
975 } else {
976 state = CAN_STATE_ERROR_ACTIVE;
977 }
978 }
979
980 /* bus error interrupt */
981 if (isrc == CEVTIND_BEI) {
982 u8 ecc = msg->data[2];
983
984 dev_dbg(mod->dev, "bus error interrupt\n");
985 mod->can.can_stats.bus_error++;
986 stats->rx_errors++;
987 cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
988
989 switch (ecc & ECC_MASK) {
990 case ECC_BIT:
991 cf->data[2] |= CAN_ERR_PROT_BIT;
992 break;
993 case ECC_FORM:
994 cf->data[2] |= CAN_ERR_PROT_FORM;
995 break;
996 case ECC_STUFF:
997 cf->data[2] |= CAN_ERR_PROT_STUFF;
998 break;
999 default:
1000 cf->data[2] |= CAN_ERR_PROT_UNSPEC;
1001 cf->data[3] = ecc & ECC_SEG;
1002 break;
1003 }
1004
1005 if ((ecc & ECC_DIR) == 0)
1006 cf->data[2] |= CAN_ERR_PROT_TX;
1007
1008 cf->data[6] = txerr;
1009 cf->data[7] = rxerr;
1010 }
1011
1012 if (state != mod->can.state && (state == CAN_STATE_ERROR_WARNING ||
1013 state == CAN_STATE_ERROR_PASSIVE)) {
1014 cf->can_id |= CAN_ERR_CRTL;
1015 if (state == CAN_STATE_ERROR_WARNING) {
1016 mod->can.can_stats.error_warning++;
1017 cf->data[1] = (txerr > rxerr) ?
1018 CAN_ERR_CRTL_TX_WARNING :
1019 CAN_ERR_CRTL_RX_WARNING;
1020 } else {
1021 mod->can.can_stats.error_passive++;
1022 cf->data[1] = (txerr > rxerr) ?
1023 CAN_ERR_CRTL_TX_PASSIVE :
1024 CAN_ERR_CRTL_RX_PASSIVE;
1025 }
1026
1027 cf->data[6] = txerr;
1028 cf->data[7] = rxerr;
1029 }
1030
1031 mod->can.state = state;
1032 stats->rx_errors++;
1033 stats->rx_bytes += cf->can_dlc;
1034 netif_rx(skb);
1035 return 0;
1036}
1037
1038static void ican3_handle_inquiry(struct ican3_dev *mod, struct ican3_msg *msg)
1039{
1040 switch (msg->data[0]) {
1041 case INQUIRY_STATUS:
1042 case INQUIRY_EXTENDED:
1043 mod->bec.rxerr = msg->data[5];
1044 mod->bec.txerr = msg->data[6];
1045 complete(&mod->buserror_comp);
1046 break;
1047 case INQUIRY_TERMINATION:
1048 mod->termination_enabled = msg->data[6] & HWCONF_TERMINATE_ON;
1049 complete(&mod->termination_comp);
1050 break;
1051 default:
1052 dev_err(mod->dev, "recieved an unknown inquiry response\n");
1053 break;
1054 }
1055}
1056
1057static void ican3_handle_unknown_message(struct ican3_dev *mod,
1058 struct ican3_msg *msg)
1059{
1060 dev_warn(mod->dev, "recieved unknown message: spec 0x%.2x length %d\n",
1061 msg->spec, le16_to_cpu(msg->len));
1062}
1063
1064/*
1065 * Handle a control message from the firmware
1066 */
1067static void ican3_handle_message(struct ican3_dev *mod, struct ican3_msg *msg)
1068{
1069 dev_dbg(mod->dev, "%s: modno %d spec 0x%.2x len %d bytes\n", __func__,
1070 mod->num, msg->spec, le16_to_cpu(msg->len));
1071
1072 switch (msg->spec) {
1073 case MSG_IDVERS:
1074 ican3_handle_idvers(mod, msg);
1075 break;
1076 case MSG_MSGLOST:
1077 case MSG_FMSGLOST:
1078 ican3_handle_msglost(mod, msg);
1079 break;
1080 case MSG_CEVTIND:
1081 ican3_handle_cevtind(mod, msg);
1082 break;
1083 case MSG_INQUIRY:
1084 ican3_handle_inquiry(mod, msg);
1085 break;
1086 default:
1087 ican3_handle_unknown_message(mod, msg);
1088 break;
1089 }
1090}
1091
1092/*
1093 * Check that there is room in the TX ring to transmit another skb
1094 *
1095 * LOCKING: must hold mod->lock
1096 */
1097static bool ican3_txok(struct ican3_dev *mod)
1098{
1099 struct ican3_fast_desc __iomem *desc;
1100 u8 control;
1101
1102 /* copy the control bits of the descriptor */
1103 ican3_set_page(mod, mod->fasttx_start + (mod->fasttx_num / 16));
1104 desc = mod->dpm + ((mod->fasttx_num % 16) * sizeof(*desc));
1105 control = ioread8(&desc->control);
1106
1107 /* if the control bits are not valid, then we have no more space */
1108 if (!(control & DESC_VALID))
1109 return false;
1110
1111 return true;
1112}
1113
1114/*
1115 * Recieve one CAN frame from the hardware
1116 *
1117 * This works like the core of a NAPI function, but is intended to be called
1118 * from workqueue context instead. This driver already needs a workqueue to
1119 * process control messages, so we use the workqueue instead of using NAPI.
1120 * This was done to simplify locking.
1121 *
1122 * CONTEXT: must be called from user context
1123 */
1124static int ican3_recv_skb(struct ican3_dev *mod)
1125{
1126 struct net_device *ndev = mod->ndev;
1127 struct net_device_stats *stats = &ndev->stats;
1128 struct ican3_fast_desc desc;
1129 void __iomem *desc_addr;
1130 struct can_frame *cf;
1131 struct sk_buff *skb;
1132 unsigned long flags;
1133
1134 spin_lock_irqsave(&mod->lock, flags);
1135
1136 /* copy the whole descriptor */
1137 ican3_set_page(mod, mod->fastrx_start + (mod->fastrx_num / 16));
1138 desc_addr = mod->dpm + ((mod->fastrx_num % 16) * sizeof(desc));
1139 memcpy_fromio(&desc, desc_addr, sizeof(desc));
1140
1141 spin_unlock_irqrestore(&mod->lock, flags);
1142
1143 /* check that we actually have a CAN frame */
1144 if (!(desc.control & DESC_VALID))
1145 return -ENOBUFS;
1146
1147 /* allocate an skb */
1148 skb = alloc_can_skb(ndev, &cf);
1149 if (unlikely(skb == NULL)) {
1150 stats->rx_dropped++;
1151 goto err_noalloc;
1152 }
1153
1154 /* convert the ICAN3 frame into Linux CAN format */
1155 ican3_to_can_frame(mod, &desc, cf);
1156
1157 /* receive the skb, update statistics */
1158 netif_receive_skb(skb);
1159 stats->rx_packets++;
1160 stats->rx_bytes += cf->can_dlc;
1161
1162err_noalloc:
1163 /* toggle the valid bit and return the descriptor to the ring */
1164 desc.control ^= DESC_VALID;
1165
1166 spin_lock_irqsave(&mod->lock, flags);
1167
1168 ican3_set_page(mod, mod->fastrx_start + (mod->fastrx_num / 16));
1169 memcpy_toio(desc_addr, &desc, 1);
1170
1171 /* update the next buffer pointer */
1172 mod->fastrx_num = (desc.control & DESC_WRAP) ? 0
1173 : (mod->fastrx_num + 1);
1174
1175 /* there are still more buffers to process */
1176 spin_unlock_irqrestore(&mod->lock, flags);
1177 return 0;
1178}
1179
1180static int ican3_napi(struct napi_struct *napi, int budget)
1181{
1182 struct ican3_dev *mod = container_of(napi, struct ican3_dev, napi);
1183 struct ican3_msg msg;
1184 unsigned long flags;
1185 int received = 0;
1186 int ret;
1187
1188 /* process all communication messages */
1189 while (true) {
1190 ret = ican3_recv_msg(mod, &msg);
1191 if (ret)
1192 break;
1193
1194 ican3_handle_message(mod, &msg);
1195 }
1196
1197 /* process all CAN frames from the fast interface */
1198 while (received < budget) {
1199 ret = ican3_recv_skb(mod);
1200 if (ret)
1201 break;
1202
1203 received++;
1204 }
1205
1206 /* We have processed all packets that the adapter had, but it
1207 * was less than our budget, stop polling */
1208 if (received < budget)
1209 napi_complete(napi);
1210
1211 spin_lock_irqsave(&mod->lock, flags);
1212
1213 /* Wake up the transmit queue if necessary */
1214 if (netif_queue_stopped(mod->ndev) && ican3_txok(mod))
1215 netif_wake_queue(mod->ndev);
1216
1217 spin_unlock_irqrestore(&mod->lock, flags);
1218
1219 /* re-enable interrupt generation */
1220 iowrite8(1 << mod->num, &mod->ctrl->int_enable);
1221 return received;
1222}
1223
1224static irqreturn_t ican3_irq(int irq, void *dev_id)
1225{
1226 struct ican3_dev *mod = dev_id;
1227 u8 stat;
1228
1229 /*
1230 * The interrupt status register on this device reports interrupts
1231 * as zeroes instead of using ones like most other devices
1232 */
1233 stat = ioread8(&mod->ctrl->int_disable) & (1 << mod->num);
1234 if (stat == (1 << mod->num))
1235 return IRQ_NONE;
1236
1237 /* clear the MODULbus interrupt from the microcontroller */
1238 ioread8(&mod->dpmctrl->interrupt);
1239
1240 /* disable interrupt generation, schedule the NAPI poller */
1241 iowrite8(1 << mod->num, &mod->ctrl->int_disable);
1242 napi_schedule(&mod->napi);
1243 return IRQ_HANDLED;
1244}
1245
1246/*
1247 * Firmware reset, startup, and shutdown
1248 */
1249
1250/*
1251 * Reset an ICAN module to its power-on state
1252 *
1253 * CONTEXT: no network device registered
1254 * LOCKING: work function disabled
1255 */
1256static int ican3_reset_module(struct ican3_dev *mod)
1257{
1258 u8 val = 1 << mod->num;
1259 unsigned long start;
1260 u8 runold, runnew;
1261
1262 /* disable interrupts so no more work is scheduled */
1263 iowrite8(1 << mod->num, &mod->ctrl->int_disable);
1264
1265 /* flush any pending work */
1266 flush_scheduled_work();
1267
1268 /* the first unallocated page in the DPM is #9 */
1269 mod->free_page = DPM_FREE_START;
1270
1271 ican3_set_page(mod, QUEUE_OLD_CONTROL);
1272 runold = ioread8(mod->dpm + TARGET_RUNNING);
1273
1274 /* reset the module */
1275 iowrite8(val, &mod->ctrl->reset_assert);
1276 iowrite8(val, &mod->ctrl->reset_deassert);
1277
1278 /* wait until the module has finished resetting and is running */
1279 start = jiffies;
1280 do {
1281 ican3_set_page(mod, QUEUE_OLD_CONTROL);
1282 runnew = ioread8(mod->dpm + TARGET_RUNNING);
1283 if (runnew == (runold ^ 0xff))
1284 return 0;
1285
1286 msleep(10);
1287 } while (time_before(jiffies, start + HZ / 4));
1288
1289 dev_err(mod->dev, "failed to reset CAN module\n");
1290 return -ETIMEDOUT;
1291}
1292
1293static void __devexit ican3_shutdown_module(struct ican3_dev *mod)
1294{
1295 ican3_msg_disconnect(mod);
1296 ican3_reset_module(mod);
1297}
1298
1299/*
1300 * Startup an ICAN module, bringing it into fast mode
1301 */
1302static int __devinit ican3_startup_module(struct ican3_dev *mod)
1303{
1304 int ret;
1305
1306 ret = ican3_reset_module(mod);
1307 if (ret) {
1308 dev_err(mod->dev, "unable to reset module\n");
1309 return ret;
1310 }
1311
1312 /* re-enable interrupts so we can send messages */
1313 iowrite8(1 << mod->num, &mod->ctrl->int_enable);
1314
1315 ret = ican3_msg_connect(mod);
1316 if (ret) {
1317 dev_err(mod->dev, "unable to connect to module\n");
1318 return ret;
1319 }
1320
1321 ican3_init_new_host_interface(mod);
1322 ret = ican3_msg_newhostif(mod);
1323 if (ret) {
1324 dev_err(mod->dev, "unable to switch to new-style interface\n");
1325 return ret;
1326 }
1327
1328 /* default to "termination on" */
1329 ret = ican3_set_termination(mod, true);
1330 if (ret) {
1331 dev_err(mod->dev, "unable to enable termination\n");
1332 return ret;
1333 }
1334
1335 /* default to "bus errors enabled" */
1336 ret = ican3_set_buserror(mod, ICAN3_BUSERR_QUOTA_MAX);
1337 if (ret) {
1338 dev_err(mod->dev, "unable to set bus-error\n");
1339 return ret;
1340 }
1341
1342 ican3_init_fast_host_interface(mod);
1343 ret = ican3_msg_fasthostif(mod);
1344 if (ret) {
1345 dev_err(mod->dev, "unable to switch to fast host interface\n");
1346 return ret;
1347 }
1348
1349 ret = ican3_set_id_filter(mod, true);
1350 if (ret) {
1351 dev_err(mod->dev, "unable to set acceptance filter\n");
1352 return ret;
1353 }
1354
1355 return 0;
1356}
1357
1358/*
1359 * CAN Network Device
1360 */
1361
1362static int ican3_open(struct net_device *ndev)
1363{
1364 struct ican3_dev *mod = netdev_priv(ndev);
1365 u8 quota;
1366 int ret;
1367
1368 /* open the CAN layer */
1369 ret = open_candev(ndev);
1370 if (ret) {
1371 dev_err(mod->dev, "unable to start CAN layer\n");
1372 return ret;
1373 }
1374
1375 /* set the bus error generation state appropriately */
1376 if (mod->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
1377 quota = ICAN3_BUSERR_QUOTA_MAX;
1378 else
1379 quota = 0;
1380
1381 ret = ican3_set_buserror(mod, quota);
1382 if (ret) {
1383 dev_err(mod->dev, "unable to set bus-error\n");
1384 close_candev(ndev);
1385 return ret;
1386 }
1387
1388 /* bring the bus online */
1389 ret = ican3_set_bus_state(mod, true);
1390 if (ret) {
1391 dev_err(mod->dev, "unable to set bus-on\n");
1392 close_candev(ndev);
1393 return ret;
1394 }
1395
1396 /* start up the network device */
1397 mod->can.state = CAN_STATE_ERROR_ACTIVE;
1398 netif_start_queue(ndev);
1399
1400 return 0;
1401}
1402
1403static int ican3_stop(struct net_device *ndev)
1404{
1405 struct ican3_dev *mod = netdev_priv(ndev);
1406 int ret;
1407
1408 /* stop the network device xmit routine */
1409 netif_stop_queue(ndev);
1410 mod->can.state = CAN_STATE_STOPPED;
1411
1412 /* bring the bus offline, stop receiving packets */
1413 ret = ican3_set_bus_state(mod, false);
1414 if (ret) {
1415 dev_err(mod->dev, "unable to set bus-off\n");
1416 return ret;
1417 }
1418
1419 /* close the CAN layer */
1420 close_candev(ndev);
1421 return 0;
1422}
1423
1424static int ican3_xmit(struct sk_buff *skb, struct net_device *ndev)
1425{
1426 struct ican3_dev *mod = netdev_priv(ndev);
1427 struct net_device_stats *stats = &ndev->stats;
1428 struct can_frame *cf = (struct can_frame *)skb->data;
1429 struct ican3_fast_desc desc;
1430 void __iomem *desc_addr;
1431 unsigned long flags;
1432
1433 spin_lock_irqsave(&mod->lock, flags);
1434
1435 /* check that we can actually transmit */
1436 if (!ican3_txok(mod)) {
1437 dev_err(mod->dev, "no free descriptors, stopping queue\n");
1438 netif_stop_queue(ndev);
1439 spin_unlock_irqrestore(&mod->lock, flags);
1440 return NETDEV_TX_BUSY;
1441 }
1442
1443 /* copy the control bits of the descriptor */
1444 ican3_set_page(mod, mod->fasttx_start + (mod->fasttx_num / 16));
1445 desc_addr = mod->dpm + ((mod->fasttx_num % 16) * sizeof(desc));
1446 memset(&desc, 0, sizeof(desc));
1447 memcpy_fromio(&desc, desc_addr, 1);
1448
1449 /* convert the Linux CAN frame into ICAN3 format */
1450 can_frame_to_ican3(mod, cf, &desc);
1451
1452 /*
1453 * the programming manual says that you must set the IVALID bit, then
1454 * interrupt, then set the valid bit. Quite weird, but it seems to be
1455 * required for this to work
1456 */
1457 desc.control |= DESC_IVALID;
1458 memcpy_toio(desc_addr, &desc, sizeof(desc));
1459
1460 /* generate a MODULbus interrupt to the microcontroller */
1461 iowrite8(0x01, &mod->dpmctrl->interrupt);
1462
1463 desc.control ^= DESC_VALID;
1464 memcpy_toio(desc_addr, &desc, sizeof(desc));
1465
1466 /* update the next buffer pointer */
1467 mod->fasttx_num = (desc.control & DESC_WRAP) ? 0
1468 : (mod->fasttx_num + 1);
1469
1470 /* update statistics */
1471 stats->tx_packets++;
1472 stats->tx_bytes += cf->can_dlc;
1473 kfree_skb(skb);
1474
1475 /*
1476 * This hardware doesn't have TX-done notifications, so we'll try and
1477 * emulate it the best we can using ECHO skbs. Get the next TX
1478 * descriptor, and see if we have room to send. If not, stop the queue.
1479 * It will be woken when the ECHO skb for the current packet is recv'd.
1480 */
1481
1482 /* copy the control bits of the descriptor */
1483 if (!ican3_txok(mod))
1484 netif_stop_queue(ndev);
1485
1486 spin_unlock_irqrestore(&mod->lock, flags);
1487 return NETDEV_TX_OK;
1488}
1489
1490static const struct net_device_ops ican3_netdev_ops = {
1491 .ndo_open = ican3_open,
1492 .ndo_stop = ican3_stop,
1493 .ndo_start_xmit = ican3_xmit,
1494};
1495
1496/*
1497 * Low-level CAN Device
1498 */
1499
1500/* This structure was stolen from drivers/net/can/sja1000/sja1000.c */
1501static struct can_bittiming_const ican3_bittiming_const = {
1502 .name = DRV_NAME,
1503 .tseg1_min = 1,
1504 .tseg1_max = 16,
1505 .tseg2_min = 1,
1506 .tseg2_max = 8,
1507 .sjw_max = 4,
1508 .brp_min = 1,
1509 .brp_max = 64,
1510 .brp_inc = 1,
1511};
1512
1513/*
1514 * This routine was stolen from drivers/net/can/sja1000/sja1000.c
1515 *
1516 * The bittiming register command for the ICAN3 just sets the bit timing
1517 * registers on the SJA1000 chip directly
1518 */
1519static int ican3_set_bittiming(struct net_device *ndev)
1520{
1521 struct ican3_dev *mod = netdev_priv(ndev);
1522 struct can_bittiming *bt = &mod->can.bittiming;
1523 struct ican3_msg msg;
1524 u8 btr0, btr1;
1525
1526 btr0 = ((bt->brp - 1) & 0x3f) | (((bt->sjw - 1) & 0x3) << 6);
1527 btr1 = ((bt->prop_seg + bt->phase_seg1 - 1) & 0xf) |
1528 (((bt->phase_seg2 - 1) & 0x7) << 4);
1529 if (mod->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
1530 btr1 |= 0x80;
1531
1532 memset(&msg, 0, sizeof(msg));
1533 msg.spec = MSG_CBTRREQ;
1534 msg.len = cpu_to_le16(4);
1535 msg.data[0] = 0x00;
1536 msg.data[1] = 0x00;
1537 msg.data[2] = btr0;
1538 msg.data[3] = btr1;
1539
1540 return ican3_send_msg(mod, &msg);
1541}
1542
1543static int ican3_set_mode(struct net_device *ndev, enum can_mode mode)
1544{
1545 struct ican3_dev *mod = netdev_priv(ndev);
1546 int ret;
1547
1548 if (mode != CAN_MODE_START)
1549 return -ENOTSUPP;
1550
1551 /* bring the bus online */
1552 ret = ican3_set_bus_state(mod, true);
1553 if (ret) {
1554 dev_err(mod->dev, "unable to set bus-on\n");
1555 return ret;
1556 }
1557
1558 /* start up the network device */
1559 mod->can.state = CAN_STATE_ERROR_ACTIVE;
1560
1561 if (netif_queue_stopped(ndev))
1562 netif_wake_queue(ndev);
1563
1564 return 0;
1565}
1566
1567static int ican3_get_berr_counter(const struct net_device *ndev,
1568 struct can_berr_counter *bec)
1569{
1570 struct ican3_dev *mod = netdev_priv(ndev);
1571 int ret;
1572
1573 ret = ican3_send_inquiry(mod, INQUIRY_STATUS);
1574 if (ret)
1575 return ret;
1576
1577 ret = wait_for_completion_timeout(&mod->buserror_comp, HZ);
1578 if (ret <= 0) {
1579 dev_info(mod->dev, "%s timed out\n", __func__);
1580 return -ETIMEDOUT;
1581 }
1582
1583 bec->rxerr = mod->bec.rxerr;
1584 bec->txerr = mod->bec.txerr;
1585 return 0;
1586}
1587
1588/*
1589 * Sysfs Attributes
1590 */
1591
1592static ssize_t ican3_sysfs_show_term(struct device *dev,
1593 struct device_attribute *attr,
1594 char *buf)
1595{
1596 struct ican3_dev *mod = netdev_priv(to_net_dev(dev));
1597 int ret;
1598
1599 ret = ican3_send_inquiry(mod, INQUIRY_TERMINATION);
1600 if (ret)
1601 return ret;
1602
1603 ret = wait_for_completion_timeout(&mod->termination_comp, HZ);
1604 if (ret <= 0) {
1605 dev_info(mod->dev, "%s timed out\n", __func__);
1606 return -ETIMEDOUT;
1607 }
1608
1609 return snprintf(buf, PAGE_SIZE, "%u\n", mod->termination_enabled);
1610}
1611
1612static ssize_t ican3_sysfs_set_term(struct device *dev,
1613 struct device_attribute *attr,
1614 const char *buf, size_t count)
1615{
1616 struct ican3_dev *mod = netdev_priv(to_net_dev(dev));
1617 unsigned long enable;
1618 int ret;
1619
1620 if (strict_strtoul(buf, 0, &enable))
1621 return -EINVAL;
1622
1623 ret = ican3_set_termination(mod, enable);
1624 if (ret)
1625 return ret;
1626
1627 return count;
1628}
1629
1630static DEVICE_ATTR(termination, S_IWUGO | S_IRUGO, ican3_sysfs_show_term,
1631 ican3_sysfs_set_term);
1632
1633static struct attribute *ican3_sysfs_attrs[] = {
1634 &dev_attr_termination.attr,
1635 NULL,
1636};
1637
1638static struct attribute_group ican3_sysfs_attr_group = {
1639 .attrs = ican3_sysfs_attrs,
1640};
1641
1642/*
1643 * PCI Subsystem
1644 */
1645
1646static int __devinit ican3_probe(struct platform_device *pdev)
1647{
1648 struct janz_platform_data *pdata;
1649 struct net_device *ndev;
1650 struct ican3_dev *mod;
1651 struct resource *res;
1652 struct device *dev;
1653 int ret;
1654
1655 pdata = pdev->dev.platform_data;
1656 if (!pdata)
1657 return -ENXIO;
1658
1659 dev_dbg(&pdev->dev, "probe: module number %d\n", pdata->modno);
1660
1661 /* save the struct device for printing */
1662 dev = &pdev->dev;
1663
1664 /* allocate the CAN device and private data */
1665 ndev = alloc_candev(sizeof(*mod), 0);
1666 if (!ndev) {
1667 dev_err(dev, "unable to allocate CANdev\n");
1668 ret = -ENOMEM;
1669 goto out_return;
1670 }
1671
1672 platform_set_drvdata(pdev, ndev);
1673 mod = netdev_priv(ndev);
1674 mod->ndev = ndev;
1675 mod->dev = &pdev->dev;
1676 mod->num = pdata->modno;
1677 netif_napi_add(ndev, &mod->napi, ican3_napi, ICAN3_RX_BUFFERS);
1678 spin_lock_init(&mod->lock);
1679 init_completion(&mod->termination_comp);
1680 init_completion(&mod->buserror_comp);
1681
1682 /* setup device-specific sysfs attributes */
1683 ndev->sysfs_groups[0] = &ican3_sysfs_attr_group;
1684
1685 /* the first unallocated page in the DPM is 9 */
1686 mod->free_page = DPM_FREE_START;
1687
1688 ndev->netdev_ops = &ican3_netdev_ops;
1689 ndev->flags |= IFF_ECHO;
1690 SET_NETDEV_DEV(ndev, &pdev->dev);
1691
1692 mod->can.clock.freq = ICAN3_CAN_CLOCK;
1693 mod->can.bittiming_const = &ican3_bittiming_const;
1694 mod->can.do_set_bittiming = ican3_set_bittiming;
1695 mod->can.do_set_mode = ican3_set_mode;
1696 mod->can.do_get_berr_counter = ican3_get_berr_counter;
1697 mod->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES
1698 | CAN_CTRLMODE_BERR_REPORTING;
1699
1700 /* find our IRQ number */
1701 mod->irq = platform_get_irq(pdev, 0);
1702 if (mod->irq < 0) {
1703 dev_err(dev, "IRQ line not found\n");
1704 ret = -ENODEV;
1705 goto out_free_ndev;
1706 }
1707
1708 ndev->irq = mod->irq;
1709
1710 /* get access to the MODULbus registers for this module */
1711 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1712 if (!res) {
1713 dev_err(dev, "MODULbus registers not found\n");
1714 ret = -ENODEV;
1715 goto out_free_ndev;
1716 }
1717
1718 mod->dpm = ioremap(res->start, resource_size(res));
1719 if (!mod->dpm) {
1720 dev_err(dev, "MODULbus registers not ioremap\n");
1721 ret = -ENOMEM;
1722 goto out_free_ndev;
1723 }
1724
1725 mod->dpmctrl = mod->dpm + DPM_PAGE_SIZE;
1726
1727 /* get access to the control registers for this module */
1728 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
1729 if (!res) {
1730 dev_err(dev, "CONTROL registers not found\n");
1731 ret = -ENODEV;
1732 goto out_iounmap_dpm;
1733 }
1734
1735 mod->ctrl = ioremap(res->start, resource_size(res));
1736 if (!mod->ctrl) {
1737 dev_err(dev, "CONTROL registers not ioremap\n");
1738 ret = -ENOMEM;
1739 goto out_iounmap_dpm;
1740 }
1741
1742 /* disable our IRQ, then hookup the IRQ handler */
1743 iowrite8(1 << mod->num, &mod->ctrl->int_disable);
1744 ret = request_irq(mod->irq, ican3_irq, IRQF_SHARED, DRV_NAME, mod);
1745 if (ret) {
1746 dev_err(dev, "unable to request IRQ\n");
1747 goto out_iounmap_ctrl;
1748 }
1749
1750 /* reset and initialize the CAN controller into fast mode */
1751 napi_enable(&mod->napi);
1752 ret = ican3_startup_module(mod);
1753 if (ret) {
1754 dev_err(dev, "%s: unable to start CANdev\n", __func__);
1755 goto out_free_irq;
1756 }
1757
1758 /* register with the Linux CAN layer */
1759 ret = register_candev(ndev);
1760 if (ret) {
1761 dev_err(dev, "%s: unable to register CANdev\n", __func__);
1762 goto out_free_irq;
1763 }
1764
1765 dev_info(dev, "module %d: registered CAN device\n", pdata->modno);
1766 return 0;
1767
1768out_free_irq:
1769 napi_disable(&mod->napi);
1770 iowrite8(1 << mod->num, &mod->ctrl->int_disable);
1771 free_irq(mod->irq, mod);
1772out_iounmap_ctrl:
1773 iounmap(mod->ctrl);
1774out_iounmap_dpm:
1775 iounmap(mod->dpm);
1776out_free_ndev:
1777 free_candev(ndev);
1778out_return:
1779 return ret;
1780}
1781
1782static int __devexit ican3_remove(struct platform_device *pdev)
1783{
1784 struct net_device *ndev = platform_get_drvdata(pdev);
1785 struct ican3_dev *mod = netdev_priv(ndev);
1786
1787 /* unregister the netdevice, stop interrupts */
1788 unregister_netdev(ndev);
1789 napi_disable(&mod->napi);
1790 iowrite8(1 << mod->num, &mod->ctrl->int_disable);
1791 free_irq(mod->irq, mod);
1792
1793 /* put the module into reset */
1794 ican3_shutdown_module(mod);
1795
1796 /* unmap all registers */
1797 iounmap(mod->ctrl);
1798 iounmap(mod->dpm);
1799
1800 free_candev(ndev);
1801
1802 return 0;
1803}
1804
1805static struct platform_driver ican3_driver = {
1806 .driver = {
1807 .name = DRV_NAME,
1808 .owner = THIS_MODULE,
1809 },
1810 .probe = ican3_probe,
1811 .remove = __devexit_p(ican3_remove),
1812};
1813
1814static int __init ican3_init(void)
1815{
1816 return platform_driver_register(&ican3_driver);
1817}
1818
1819static void __exit ican3_exit(void)
1820{
1821 platform_driver_unregister(&ican3_driver);
1822}
1823
1824MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>");
1825MODULE_DESCRIPTION("Janz MODULbus VMOD-ICAN3 Driver");
1826MODULE_LICENSE("GPL");
1827MODULE_ALIAS("platform:janz-ican3");
1828
1829module_init(ican3_init);
1830module_exit(ican3_exit);
diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index 8af8442c694a..af753936e835 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -73,7 +73,7 @@ static u32 __devinit mpc52xx_can_get_clock(struct of_device *ofdev,
73 else 73 else
74 *mscan_clksrc = MSCAN_CLKSRC_XTAL; 74 *mscan_clksrc = MSCAN_CLKSRC_XTAL;
75 75
76 freq = mpc5xxx_get_bus_frequency(ofdev->node); 76 freq = mpc5xxx_get_bus_frequency(ofdev->dev.of_node);
77 if (!freq) 77 if (!freq)
78 return 0; 78 return 0;
79 79
@@ -152,7 +152,7 @@ static u32 __devinit mpc512x_can_get_clock(struct of_device *ofdev,
152 } 152 }
153 153
154 /* Determine the MSCAN device index from the physical address */ 154 /* Determine the MSCAN device index from the physical address */
155 pval = of_get_property(ofdev->node, "reg", &plen); 155 pval = of_get_property(ofdev->dev.of_node, "reg", &plen);
156 BUG_ON(!pval || plen < sizeof(*pval)); 156 BUG_ON(!pval || plen < sizeof(*pval));
157 clockidx = (*pval & 0x80) ? 1 : 0; 157 clockidx = (*pval & 0x80) ? 1 : 0;
158 if (*pval & 0x2000) 158 if (*pval & 0x2000)
@@ -168,11 +168,11 @@ static u32 __devinit mpc512x_can_get_clock(struct of_device *ofdev,
168 */ 168 */
169 if (clock_name && !strcmp(clock_name, "ip")) { 169 if (clock_name && !strcmp(clock_name, "ip")) {
170 *mscan_clksrc = MSCAN_CLKSRC_IPS; 170 *mscan_clksrc = MSCAN_CLKSRC_IPS;
171 freq = mpc5xxx_get_bus_frequency(ofdev->node); 171 freq = mpc5xxx_get_bus_frequency(ofdev->dev.of_node);
172 } else { 172 } else {
173 *mscan_clksrc = MSCAN_CLKSRC_BUS; 173 *mscan_clksrc = MSCAN_CLKSRC_BUS;
174 174
175 pval = of_get_property(ofdev->node, 175 pval = of_get_property(ofdev->dev.of_node,
176 "fsl,mscan-clock-divider", &plen); 176 "fsl,mscan-clock-divider", &plen);
177 if (pval && plen == sizeof(*pval)) 177 if (pval && plen == sizeof(*pval))
178 clockdiv = *pval; 178 clockdiv = *pval;
@@ -251,7 +251,7 @@ static int __devinit mpc5xxx_can_probe(struct of_device *ofdev,
251 const struct of_device_id *id) 251 const struct of_device_id *id)
252{ 252{
253 struct mpc5xxx_can_data *data = (struct mpc5xxx_can_data *)id->data; 253 struct mpc5xxx_can_data *data = (struct mpc5xxx_can_data *)id->data;
254 struct device_node *np = ofdev->node; 254 struct device_node *np = ofdev->dev.of_node;
255 struct net_device *dev; 255 struct net_device *dev;
256 struct mscan_priv *priv; 256 struct mscan_priv *priv;
257 void __iomem *base; 257 void __iomem *base;
diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c
index be90d3598bca..fe925663d39a 100644
--- a/drivers/net/cnic.c
+++ b/drivers/net/cnic.c
@@ -3367,13 +3367,9 @@ static int cnic_cm_shutdown(struct cnic_dev *dev)
3367 3367
3368static void cnic_init_context(struct cnic_dev *dev, u32 cid) 3368static void cnic_init_context(struct cnic_dev *dev, u32 cid)
3369{ 3369{
3370 struct cnic_local *cp = dev->cnic_priv;
3371 u32 cid_addr; 3370 u32 cid_addr;
3372 int i; 3371 int i;
3373 3372
3374 if (CHIP_NUM(cp) == CHIP_NUM_5709)
3375 return;
3376
3377 cid_addr = GET_CID_ADDR(cid); 3373 cid_addr = GET_CID_ADDR(cid);
3378 3374
3379 for (i = 0; i < CTX_SIZE; i += 4) 3375 for (i = 0; i < CTX_SIZE; i += 4)
@@ -3530,14 +3526,11 @@ static void cnic_init_bnx2_tx_ring(struct cnic_dev *dev)
3530 3526
3531 sb_id = cp->status_blk_num; 3527 sb_id = cp->status_blk_num;
3532 tx_cid = 20; 3528 tx_cid = 20;
3533 cnic_init_context(dev, tx_cid);
3534 cnic_init_context(dev, tx_cid + 1);
3535 cp->tx_cons_ptr = &s_blk->status_tx_quick_consumer_index2; 3529 cp->tx_cons_ptr = &s_blk->status_tx_quick_consumer_index2;
3536 if (ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX) { 3530 if (ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX) {
3537 struct status_block_msix *sblk = cp->status_blk.bnx2; 3531 struct status_block_msix *sblk = cp->status_blk.bnx2;
3538 3532
3539 tx_cid = TX_TSS_CID + sb_id - 1; 3533 tx_cid = TX_TSS_CID + sb_id - 1;
3540 cnic_init_context(dev, tx_cid);
3541 CNIC_WR(dev, BNX2_TSCH_TSS_CFG, (sb_id << 24) | 3534 CNIC_WR(dev, BNX2_TSCH_TSS_CFG, (sb_id << 24) |
3542 (TX_TSS_CID << 7)); 3535 (TX_TSS_CID << 7));
3543 cp->tx_cons_ptr = &sblk->status_tx_quick_consumer_index; 3536 cp->tx_cons_ptr = &sblk->status_tx_quick_consumer_index;
@@ -3556,6 +3549,9 @@ static void cnic_init_bnx2_tx_ring(struct cnic_dev *dev)
3556 offset2 = BNX2_L2CTX_TBDR_BHADDR_HI_XI; 3549 offset2 = BNX2_L2CTX_TBDR_BHADDR_HI_XI;
3557 offset3 = BNX2_L2CTX_TBDR_BHADDR_LO_XI; 3550 offset3 = BNX2_L2CTX_TBDR_BHADDR_LO_XI;
3558 } else { 3551 } else {
3552 cnic_init_context(dev, tx_cid);
3553 cnic_init_context(dev, tx_cid + 1);
3554
3559 offset0 = BNX2_L2CTX_TYPE; 3555 offset0 = BNX2_L2CTX_TYPE;
3560 offset1 = BNX2_L2CTX_CMD_TYPE; 3556 offset1 = BNX2_L2CTX_CMD_TYPE;
3561 offset2 = BNX2_L2CTX_TBDR_BHADDR_HI; 3557 offset2 = BNX2_L2CTX_TBDR_BHADDR_HI;
diff --git a/drivers/net/cnic_if.h b/drivers/net/cnic_if.h
index 110c62072e6f..0c55177db046 100644
--- a/drivers/net/cnic_if.h
+++ b/drivers/net/cnic_if.h
@@ -12,8 +12,8 @@
12#ifndef CNIC_IF_H 12#ifndef CNIC_IF_H
13#define CNIC_IF_H 13#define CNIC_IF_H
14 14
15#define CNIC_MODULE_VERSION "2.1.1" 15#define CNIC_MODULE_VERSION "2.1.2"
16#define CNIC_MODULE_RELDATE "Feb 22, 2010" 16#define CNIC_MODULE_RELDATE "May 26, 2010"
17 17
18#define CNIC_ULP_RDMA 0 18#define CNIC_ULP_RDMA 0
19#define CNIC_ULP_ISCSI 1 19#define CNIC_ULP_ISCSI 1
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 24507f3b8b17..57a7e41da69e 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -2554,7 +2554,7 @@ static void e1000_init_manageability_pt(struct e1000_adapter *adapter)
2554 mdef = er32(MDEF(i)); 2554 mdef = er32(MDEF(i));
2555 2555
2556 /* Ignore filters with anything other than IPMI ports */ 2556 /* Ignore filters with anything other than IPMI ports */
2557 if (mdef & !(E1000_MDEF_PORT_623 | E1000_MDEF_PORT_664)) 2557 if (mdef & ~(E1000_MDEF_PORT_623 | E1000_MDEF_PORT_664))
2558 continue; 2558 continue;
2559 2559
2560 /* Enable this decision filter in MANC2H */ 2560 /* Enable this decision filter in MANC2H */
diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h
index 85f2a2e7030a..45e86d1e5b1b 100644
--- a/drivers/net/enic/enic.h
+++ b/drivers/net/enic/enic.h
@@ -74,7 +74,14 @@ struct enic_msix_entry {
74 void *devid; 74 void *devid;
75}; 75};
76 76
77#define ENIC_SET_APPLIED (1 << 0)
78#define ENIC_SET_REQUEST (1 << 1)
79#define ENIC_SET_NAME (1 << 2)
80#define ENIC_SET_INSTANCE (1 << 3)
81#define ENIC_SET_HOST (1 << 4)
82
77struct enic_port_profile { 83struct enic_port_profile {
84 u32 set;
78 u8 request; 85 u8 request;
79 char name[PORT_PROFILE_MAX]; 86 char name[PORT_PROFILE_MAX];
80 u8 instance_uuid[PORT_UUID_MAX]; 87 u8 instance_uuid[PORT_UUID_MAX];
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c
index 6586b5c7e4b6..bc7d6b96de3d 100644
--- a/drivers/net/enic/enic_main.c
+++ b/drivers/net/enic/enic_main.c
@@ -1029,8 +1029,7 @@ static int enic_dev_init_done(struct enic *enic, int *done, int *error)
1029 return err; 1029 return err;
1030} 1030}
1031 1031
1032static int enic_set_port_profile(struct enic *enic, u8 request, u8 *mac, 1032static int enic_set_port_profile(struct enic *enic, u8 *mac)
1033 char *name, u8 *instance_uuid, u8 *host_uuid)
1034{ 1033{
1035 struct vic_provinfo *vp; 1034 struct vic_provinfo *vp;
1036 u8 oui[3] = VIC_PROVINFO_CISCO_OUI; 1035 u8 oui[3] = VIC_PROVINFO_CISCO_OUI;
@@ -1040,97 +1039,112 @@ static int enic_set_port_profile(struct enic *enic, u8 request, u8 *mac,
1040 "%02X%02X-%02X%02X%02X%02X%0X%02X"; 1039 "%02X%02X-%02X%02X%02X%02X%0X%02X";
1041 int err; 1040 int err;
1042 1041
1043 if (!name) 1042 err = enic_vnic_dev_deinit(enic);
1044 return -EINVAL; 1043 if (err)
1044 return err;
1045 1045
1046 if (!is_valid_ether_addr(mac)) 1046 switch (enic->pp.request) {
1047 return -EADDRNOTAVAIL;
1048 1047
1049 vp = vic_provinfo_alloc(GFP_KERNEL, oui, VIC_PROVINFO_LINUX_TYPE); 1048 case PORT_REQUEST_ASSOCIATE:
1050 if (!vp)
1051 return -ENOMEM;
1052 1049
1053 vic_provinfo_add_tlv(vp, 1050 if (!(enic->pp.set & ENIC_SET_NAME) || !strlen(enic->pp.name))
1054 VIC_LINUX_PROV_TLV_PORT_PROFILE_NAME_STR, 1051 return -EINVAL;
1055 strlen(name) + 1, name);
1056
1057 vic_provinfo_add_tlv(vp,
1058 VIC_LINUX_PROV_TLV_CLIENT_MAC_ADDR,
1059 ETH_ALEN, mac);
1060
1061 if (instance_uuid) {
1062 uuid = instance_uuid;
1063 sprintf(uuid_str, uuid_fmt,
1064 uuid[0], uuid[1], uuid[2], uuid[3],
1065 uuid[4], uuid[5], uuid[6], uuid[7],
1066 uuid[8], uuid[9], uuid[10], uuid[11],
1067 uuid[12], uuid[13], uuid[14], uuid[15]);
1068 vic_provinfo_add_tlv(vp,
1069 VIC_LINUX_PROV_TLV_CLIENT_UUID_STR,
1070 sizeof(uuid_str), uuid_str);
1071 }
1072 1052
1073 if (host_uuid) { 1053 if (!is_valid_ether_addr(mac))
1074 uuid = host_uuid; 1054 return -EADDRNOTAVAIL;
1075 sprintf(uuid_str, uuid_fmt,
1076 uuid[0], uuid[1], uuid[2], uuid[3],
1077 uuid[4], uuid[5], uuid[6], uuid[7],
1078 uuid[8], uuid[9], uuid[10], uuid[11],
1079 uuid[12], uuid[13], uuid[14], uuid[15]);
1080 vic_provinfo_add_tlv(vp,
1081 VIC_LINUX_PROV_TLV_HOST_UUID_STR,
1082 sizeof(uuid_str), uuid_str);
1083 }
1084 1055
1085 err = enic_vnic_dev_deinit(enic); 1056 vp = vic_provinfo_alloc(GFP_KERNEL, oui,
1086 if (err) 1057 VIC_PROVINFO_LINUX_TYPE);
1087 goto err_out; 1058 if (!vp)
1059 return -ENOMEM;
1088 1060
1089 memset(&enic->pp, 0, sizeof(enic->pp)); 1061 vic_provinfo_add_tlv(vp,
1062 VIC_LINUX_PROV_TLV_PORT_PROFILE_NAME_STR,
1063 strlen(enic->pp.name) + 1, enic->pp.name);
1090 1064
1091 err = enic_dev_init_prov(enic, vp); 1065 vic_provinfo_add_tlv(vp,
1092 if (err) 1066 VIC_LINUX_PROV_TLV_CLIENT_MAC_ADDR,
1093 goto err_out; 1067 ETH_ALEN, mac);
1068
1069 if (enic->pp.set & ENIC_SET_INSTANCE) {
1070 uuid = enic->pp.instance_uuid;
1071 sprintf(uuid_str, uuid_fmt,
1072 uuid[0], uuid[1], uuid[2], uuid[3],
1073 uuid[4], uuid[5], uuid[6], uuid[7],
1074 uuid[8], uuid[9], uuid[10], uuid[11],
1075 uuid[12], uuid[13], uuid[14], uuid[15]);
1076 vic_provinfo_add_tlv(vp,
1077 VIC_LINUX_PROV_TLV_CLIENT_UUID_STR,
1078 sizeof(uuid_str), uuid_str);
1079 }
1094 1080
1095 enic->pp.request = request; 1081 if (enic->pp.set & ENIC_SET_HOST) {
1096 memcpy(enic->pp.name, name, PORT_PROFILE_MAX); 1082 uuid = enic->pp.host_uuid;
1097 if (instance_uuid) 1083 sprintf(uuid_str, uuid_fmt,
1098 memcpy(enic->pp.instance_uuid, 1084 uuid[0], uuid[1], uuid[2], uuid[3],
1099 instance_uuid, PORT_UUID_MAX); 1085 uuid[4], uuid[5], uuid[6], uuid[7],
1100 if (host_uuid) 1086 uuid[8], uuid[9], uuid[10], uuid[11],
1101 memcpy(enic->pp.host_uuid, 1087 uuid[12], uuid[13], uuid[14], uuid[15]);
1102 host_uuid, PORT_UUID_MAX); 1088 vic_provinfo_add_tlv(vp,
1089 VIC_LINUX_PROV_TLV_HOST_UUID_STR,
1090 sizeof(uuid_str), uuid_str);
1091 }
1103 1092
1104err_out: 1093 err = enic_dev_init_prov(enic, vp);
1105 vic_provinfo_free(vp); 1094 vic_provinfo_free(vp);
1095 if (err)
1096 return err;
1097 break;
1106 1098
1107 return err; 1099 case PORT_REQUEST_DISASSOCIATE:
1108} 1100 break;
1109 1101
1110static int enic_unset_port_profile(struct enic *enic) 1102 default:
1111{ 1103 return -EINVAL;
1112 memset(&enic->pp, 0, sizeof(enic->pp)); 1104 }
1113 return enic_vnic_dev_deinit(enic); 1105
1106 enic->pp.set |= ENIC_SET_APPLIED;
1107 return 0;
1114} 1108}
1115 1109
1116static int enic_set_vf_port(struct net_device *netdev, int vf, 1110static int enic_set_vf_port(struct net_device *netdev, int vf,
1117 struct nlattr *port[]) 1111 struct nlattr *port[])
1118{ 1112{
1119 struct enic *enic = netdev_priv(netdev); 1113 struct enic *enic = netdev_priv(netdev);
1120 char *name = NULL; 1114
1121 u8 *instance_uuid = NULL; 1115 memset(&enic->pp, 0, sizeof(enic->pp));
1122 u8 *host_uuid = NULL; 1116
1123 u8 request = PORT_REQUEST_DISASSOCIATE; 1117 if (port[IFLA_PORT_REQUEST]) {
1118 enic->pp.set |= ENIC_SET_REQUEST;
1119 enic->pp.request = nla_get_u8(port[IFLA_PORT_REQUEST]);
1120 }
1121
1122 if (port[IFLA_PORT_PROFILE]) {
1123 enic->pp.set |= ENIC_SET_NAME;
1124 memcpy(enic->pp.name, nla_data(port[IFLA_PORT_PROFILE]),
1125 PORT_PROFILE_MAX);
1126 }
1127
1128 if (port[IFLA_PORT_INSTANCE_UUID]) {
1129 enic->pp.set |= ENIC_SET_INSTANCE;
1130 memcpy(enic->pp.instance_uuid,
1131 nla_data(port[IFLA_PORT_INSTANCE_UUID]), PORT_UUID_MAX);
1132 }
1133
1134 if (port[IFLA_PORT_HOST_UUID]) {
1135 enic->pp.set |= ENIC_SET_HOST;
1136 memcpy(enic->pp.host_uuid,
1137 nla_data(port[IFLA_PORT_HOST_UUID]), PORT_UUID_MAX);
1138 }
1124 1139
1125 /* don't support VFs, yet */ 1140 /* don't support VFs, yet */
1126 if (vf != PORT_SELF_VF) 1141 if (vf != PORT_SELF_VF)
1127 return -EOPNOTSUPP; 1142 return -EOPNOTSUPP;
1128 1143
1129 if (port[IFLA_PORT_REQUEST]) 1144 if (!(enic->pp.set & ENIC_SET_REQUEST))
1130 request = nla_get_u8(port[IFLA_PORT_REQUEST]); 1145 return -EOPNOTSUPP;
1131 1146
1132 switch (request) { 1147 if (enic->pp.request == PORT_REQUEST_ASSOCIATE) {
1133 case PORT_REQUEST_ASSOCIATE:
1134 1148
1135 /* If the interface mac addr hasn't been assigned, 1149 /* If the interface mac addr hasn't been assigned,
1136 * assign a random mac addr before setting port- 1150 * assign a random mac addr before setting port-
@@ -1139,30 +1153,9 @@ static int enic_set_vf_port(struct net_device *netdev, int vf,
1139 1153
1140 if (is_zero_ether_addr(netdev->dev_addr)) 1154 if (is_zero_ether_addr(netdev->dev_addr))
1141 random_ether_addr(netdev->dev_addr); 1155 random_ether_addr(netdev->dev_addr);
1142
1143 if (port[IFLA_PORT_PROFILE])
1144 name = nla_data(port[IFLA_PORT_PROFILE]);
1145
1146 if (port[IFLA_PORT_INSTANCE_UUID])
1147 instance_uuid =
1148 nla_data(port[IFLA_PORT_INSTANCE_UUID]);
1149
1150 if (port[IFLA_PORT_HOST_UUID])
1151 host_uuid = nla_data(port[IFLA_PORT_HOST_UUID]);
1152
1153 return enic_set_port_profile(enic, request,
1154 netdev->dev_addr, name,
1155 instance_uuid, host_uuid);
1156
1157 case PORT_REQUEST_DISASSOCIATE:
1158
1159 return enic_unset_port_profile(enic);
1160
1161 default:
1162 break;
1163 } 1156 }
1164 1157
1165 return -EOPNOTSUPP; 1158 return enic_set_port_profile(enic, netdev->dev_addr);
1166} 1159}
1167 1160
1168static int enic_get_vf_port(struct net_device *netdev, int vf, 1161static 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,
1172 int err, error, done; 1165 int err, error, done;
1173 u16 response = PORT_PROFILE_RESPONSE_SUCCESS; 1166 u16 response = PORT_PROFILE_RESPONSE_SUCCESS;
1174 1167
1175 /* don't support VFs, yet */ 1168 if (!(enic->pp.set & ENIC_SET_APPLIED))
1176 if (vf != PORT_SELF_VF) 1169 return -ENODATA;
1177 return -EOPNOTSUPP;
1178 1170
1179 err = enic_dev_init_done(enic, &done, &error); 1171 err = enic_dev_init_done(enic, &done, &error);
1180
1181 if (err) 1172 if (err)
1182 return err; 1173 error = err;
1183 1174
1184 switch (error) { 1175 switch (error) {
1185 case ERR_SUCCESS: 1176 case ERR_SUCCESS:
@@ -1202,12 +1193,15 @@ static int enic_get_vf_port(struct net_device *netdev, int vf,
1202 1193
1203 NLA_PUT_U16(skb, IFLA_PORT_REQUEST, enic->pp.request); 1194 NLA_PUT_U16(skb, IFLA_PORT_REQUEST, enic->pp.request);
1204 NLA_PUT_U16(skb, IFLA_PORT_RESPONSE, response); 1195 NLA_PUT_U16(skb, IFLA_PORT_RESPONSE, response);
1205 NLA_PUT(skb, IFLA_PORT_PROFILE, PORT_PROFILE_MAX, 1196 if (enic->pp.set & ENIC_SET_NAME)
1206 enic->pp.name); 1197 NLA_PUT(skb, IFLA_PORT_PROFILE, PORT_PROFILE_MAX,
1207 NLA_PUT(skb, IFLA_PORT_INSTANCE_UUID, PORT_UUID_MAX, 1198 enic->pp.name);
1208 enic->pp.instance_uuid); 1199 if (enic->pp.set & ENIC_SET_INSTANCE)
1209 NLA_PUT(skb, IFLA_PORT_HOST_UUID, PORT_UUID_MAX, 1200 NLA_PUT(skb, IFLA_PORT_INSTANCE_UUID, PORT_UUID_MAX,
1210 enic->pp.host_uuid); 1201 enic->pp.instance_uuid);
1202 if (enic->pp.set & ENIC_SET_HOST)
1203 NLA_PUT(skb, IFLA_PORT_HOST_UUID, PORT_UUID_MAX,
1204 enic->pp.host_uuid);
1211 1205
1212 return 0; 1206 return 0;
1213 1207
diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c
index 6838dfc9ef23..4c274657283c 100644
--- a/drivers/net/epic100.c
+++ b/drivers/net/epic100.c
@@ -87,6 +87,7 @@ static int rx_copybreak;
87#include <linux/bitops.h> 87#include <linux/bitops.h>
88#include <asm/io.h> 88#include <asm/io.h>
89#include <asm/uaccess.h> 89#include <asm/uaccess.h>
90#include <asm/byteorder.h>
90 91
91/* These identify the driver base version and may not be removed. */ 92/* These identify the driver base version and may not be removed. */
92static char version[] __devinitdata = 93static char version[] __devinitdata =
@@ -230,7 +231,7 @@ static const u16 media2miictl[16] = {
230 * The EPIC100 Rx and Tx buffer descriptors. Note that these 231 * The EPIC100 Rx and Tx buffer descriptors. Note that these
231 * really ARE host-endian; it's not a misannotation. We tell 232 * really ARE host-endian; it's not a misannotation. We tell
232 * the card to byteswap them internally on big-endian hosts - 233 * the card to byteswap them internally on big-endian hosts -
233 * look for #ifdef CONFIG_BIG_ENDIAN in epic_open(). 234 * look for #ifdef __BIG_ENDIAN in epic_open().
234 */ 235 */
235 236
236struct epic_tx_desc { 237struct epic_tx_desc {
@@ -690,7 +691,7 @@ static int epic_open(struct net_device *dev)
690 outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL); 691 outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
691 692
692 /* Tell the chip to byteswap descriptors on big-endian hosts */ 693 /* Tell the chip to byteswap descriptors on big-endian hosts */
693#ifdef CONFIG_BIG_ENDIAN 694#ifdef __BIG_ENDIAN
694 outl(0x4432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL); 695 outl(0x4432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
695 inl(ioaddr + GENCTL); 696 inl(ioaddr + GENCTL);
696 outl(0x0432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL); 697 outl(0x0432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
@@ -806,7 +807,7 @@ static void epic_restart(struct net_device *dev)
806 for (i = 16; i > 0; i--) 807 for (i = 16; i > 0; i--)
807 outl(0x0008, ioaddr + TEST1); 808 outl(0x0008, ioaddr + TEST1);
808 809
809#ifdef CONFIG_BIG_ENDIAN 810#ifdef __BIG_ENDIAN
810 outl(0x0432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL); 811 outl(0x0432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
811#else 812#else
812 outl(0x0412 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL); 813 outl(0x0412 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 326465ffbb23..edfff92a6d8e 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -681,6 +681,8 @@ static int fec_enet_mii_probe(struct net_device *dev)
681 struct phy_device *phy_dev = NULL; 681 struct phy_device *phy_dev = NULL;
682 int phy_addr; 682 int phy_addr;
683 683
684 fep->phy_dev = NULL;
685
684 /* find the first phy */ 686 /* find the first phy */
685 for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { 687 for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
686 if (fep->mii_bus->phy_map[phy_addr]) { 688 if (fep->mii_bus->phy_map[phy_addr]) {
@@ -711,6 +713,11 @@ static int fec_enet_mii_probe(struct net_device *dev)
711 fep->link = 0; 713 fep->link = 0;
712 fep->full_duplex = 0; 714 fep->full_duplex = 0;
713 715
716 printk(KERN_INFO "%s: Freescale FEC PHY driver [%s] "
717 "(mii_bus:phy_addr=%s, irq=%d)\n", dev->name,
718 fep->phy_dev->drv->name, dev_name(&fep->phy_dev->dev),
719 fep->phy_dev->irq);
720
714 return 0; 721 return 0;
715} 722}
716 723
@@ -756,13 +763,8 @@ static int fec_enet_mii_init(struct platform_device *pdev)
756 if (mdiobus_register(fep->mii_bus)) 763 if (mdiobus_register(fep->mii_bus))
757 goto err_out_free_mdio_irq; 764 goto err_out_free_mdio_irq;
758 765
759 if (fec_enet_mii_probe(dev) != 0)
760 goto err_out_unregister_bus;
761
762 return 0; 766 return 0;
763 767
764err_out_unregister_bus:
765 mdiobus_unregister(fep->mii_bus);
766err_out_free_mdio_irq: 768err_out_free_mdio_irq:
767 kfree(fep->mii_bus->irq); 769 kfree(fep->mii_bus->irq);
768err_out_free_mdiobus: 770err_out_free_mdiobus:
@@ -915,7 +917,12 @@ fec_enet_open(struct net_device *dev)
915 if (ret) 917 if (ret)
916 return ret; 918 return ret;
917 919
918 /* schedule a link state check */ 920 /* Probe and connect to PHY when open the interface */
921 ret = fec_enet_mii_probe(dev);
922 if (ret) {
923 fec_enet_free_buffers(dev);
924 return ret;
925 }
919 phy_start(fep->phy_dev); 926 phy_start(fep->phy_dev);
920 netif_start_queue(dev); 927 netif_start_queue(dev);
921 fep->opened = 1; 928 fep->opened = 1;
@@ -929,10 +936,12 @@ fec_enet_close(struct net_device *dev)
929 936
930 /* Don't know what to do yet. */ 937 /* Don't know what to do yet. */
931 fep->opened = 0; 938 fep->opened = 0;
932 phy_stop(fep->phy_dev);
933 netif_stop_queue(dev); 939 netif_stop_queue(dev);
934 fec_stop(dev); 940 fec_stop(dev);
935 941
942 if (fep->phy_dev)
943 phy_disconnect(fep->phy_dev);
944
936 fec_enet_free_buffers(dev); 945 fec_enet_free_buffers(dev);
937 946
938 return 0; 947 return 0;
@@ -1316,11 +1325,6 @@ fec_probe(struct platform_device *pdev)
1316 if (ret) 1325 if (ret)
1317 goto failed_register; 1326 goto failed_register;
1318 1327
1319 printk(KERN_INFO "%s: Freescale FEC PHY driver [%s] "
1320 "(mii_bus:phy_addr=%s, irq=%d)\n", ndev->name,
1321 fep->phy_dev->drv->name, dev_name(&fep->phy_dev->dev),
1322 fep->phy_dev->irq);
1323
1324 return 0; 1328 return 0;
1325 1329
1326failed_register: 1330failed_register:
@@ -1369,10 +1373,9 @@ fec_suspend(struct platform_device *dev, pm_message_t state)
1369 1373
1370 if (ndev) { 1374 if (ndev) {
1371 fep = netdev_priv(ndev); 1375 fep = netdev_priv(ndev);
1372 if (netif_running(ndev)) { 1376 if (netif_running(ndev))
1373 netif_device_detach(ndev); 1377 fec_enet_close(ndev);
1374 fec_stop(ndev); 1378 clk_disable(fep->clk);
1375 }
1376 } 1379 }
1377 return 0; 1380 return 0;
1378} 1381}
@@ -1381,12 +1384,13 @@ static int
1381fec_resume(struct platform_device *dev) 1384fec_resume(struct platform_device *dev)
1382{ 1385{
1383 struct net_device *ndev = platform_get_drvdata(dev); 1386 struct net_device *ndev = platform_get_drvdata(dev);
1387 struct fec_enet_private *fep;
1384 1388
1385 if (ndev) { 1389 if (ndev) {
1386 if (netif_running(ndev)) { 1390 fep = netdev_priv(ndev);
1387 fec_enet_init(ndev, 0); 1391 clk_enable(fep->clk);
1388 netif_device_attach(ndev); 1392 if (netif_running(ndev))
1389 } 1393 fec_enet_open(ndev);
1390 } 1394 }
1391 return 0; 1395 return 0;
1392} 1396}
diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c
index 5d45084b287d..48e91b6242ce 100644
--- a/drivers/net/fs_enet/mac-fcc.c
+++ b/drivers/net/fs_enet/mac-fcc.c
@@ -504,17 +504,54 @@ static int get_regs_len(struct net_device *dev)
504} 504}
505 505
506/* Some transmit errors cause the transmitter to shut 506/* Some transmit errors cause the transmitter to shut
507 * down. We now issue a restart transmit. Since the 507 * down. We now issue a restart transmit.
508 * errors close the BD and update the pointers, the restart 508 * Also, to workaround 8260 device erratum CPM37, we must
509 * _should_ pick up without having to reset any of our 509 * disable and then re-enable the transmitterfollowing a
510 * pointers either. Also, To workaround 8260 device erratum 510 * Late Collision, Underrun, or Retry Limit error.
511 * CPM37, we must disable and then re-enable the transmitter 511 * In addition, tbptr may point beyond BDs beyond still marked
512 * following a Late Collision, Underrun, or Retry Limit error. 512 * as ready due to internal pipelining, so we need to look back
513 * through the BDs and adjust tbptr to point to the last BD
514 * marked as ready. This may result in some buffers being
515 * retransmitted.
513 */ 516 */
514static void tx_restart(struct net_device *dev) 517static void tx_restart(struct net_device *dev)
515{ 518{
516 struct fs_enet_private *fep = netdev_priv(dev); 519 struct fs_enet_private *fep = netdev_priv(dev);
517 fcc_t __iomem *fccp = fep->fcc.fccp; 520 fcc_t __iomem *fccp = fep->fcc.fccp;
521 const struct fs_platform_info *fpi = fep->fpi;
522 fcc_enet_t __iomem *ep = fep->fcc.ep;
523 cbd_t __iomem *curr_tbptr;
524 cbd_t __iomem *recheck_bd;
525 cbd_t __iomem *prev_bd;
526 cbd_t __iomem *last_tx_bd;
527
528 last_tx_bd = fep->tx_bd_base + (fpi->tx_ring * sizeof(cbd_t));
529
530 /* get the current bd held in TBPTR and scan back from this point */
531 recheck_bd = curr_tbptr = (cbd_t __iomem *)
532 ((R32(ep, fen_genfcc.fcc_tbptr) - fep->ring_mem_addr) +
533 fep->ring_base);
534
535 prev_bd = (recheck_bd == fep->tx_bd_base) ? last_tx_bd : recheck_bd - 1;
536
537 /* Move through the bds in reverse, look for the earliest buffer
538 * that is not ready. Adjust TBPTR to the following buffer */
539 while ((CBDR_SC(prev_bd) & BD_ENET_TX_READY) != 0) {
540 /* Go back one buffer */
541 recheck_bd = prev_bd;
542
543 /* update the previous buffer */
544 prev_bd = (prev_bd == fep->tx_bd_base) ? last_tx_bd : prev_bd - 1;
545
546 /* We should never see all bds marked as ready, check anyway */
547 if (recheck_bd == curr_tbptr)
548 break;
549 }
550 /* Now update the TBPTR and dirty flag to the current buffer */
551 W32(ep, fen_genfcc.fcc_tbptr,
552 (uint) (((void *)recheck_bd - fep->ring_base) +
553 fep->ring_mem_addr));
554 fep->dirty_tx = recheck_bd;
518 555
519 C32(fccp, fcc_gfmr, FCC_GFMR_ENT); 556 C32(fccp, fcc_gfmr, FCC_GFMR_ENT);
520 udelay(10); 557 udelay(10);
diff --git a/drivers/net/fs_enet/mii-bitbang.c b/drivers/net/fs_enet/mii-bitbang.c
index 0f90685d3d19..3607340f3da7 100644
--- a/drivers/net/fs_enet/mii-bitbang.c
+++ b/drivers/net/fs_enet/mii-bitbang.c
@@ -169,7 +169,7 @@ static int __devinit fs_enet_mdio_probe(struct of_device *ofdev,
169 169
170 new_bus->name = "CPM2 Bitbanged MII", 170 new_bus->name = "CPM2 Bitbanged MII",
171 171
172 ret = fs_mii_bitbang_init(new_bus, ofdev->node); 172 ret = fs_mii_bitbang_init(new_bus, ofdev->dev.of_node);
173 if (ret) 173 if (ret)
174 goto out_free_bus; 174 goto out_free_bus;
175 175
@@ -181,7 +181,7 @@ static int __devinit fs_enet_mdio_probe(struct of_device *ofdev,
181 new_bus->parent = &ofdev->dev; 181 new_bus->parent = &ofdev->dev;
182 dev_set_drvdata(&ofdev->dev, new_bus); 182 dev_set_drvdata(&ofdev->dev, new_bus);
183 183
184 ret = of_mdiobus_register(new_bus, ofdev->node); 184 ret = of_mdiobus_register(new_bus, ofdev->dev.of_node);
185 if (ret) 185 if (ret)
186 goto out_free_irqs; 186 goto out_free_irqs;
187 187
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 1830f3199cb5..46c69cd06553 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -747,8 +747,7 @@ static int gfar_of_init(struct of_device *ofdev, struct net_device **pdev)
747 FSL_GIANFAR_DEV_HAS_CSUM | 747 FSL_GIANFAR_DEV_HAS_CSUM |
748 FSL_GIANFAR_DEV_HAS_VLAN | 748 FSL_GIANFAR_DEV_HAS_VLAN |
749 FSL_GIANFAR_DEV_HAS_MAGIC_PACKET | 749 FSL_GIANFAR_DEV_HAS_MAGIC_PACKET |
750 FSL_GIANFAR_DEV_HAS_EXTENDED_HASH | 750 FSL_GIANFAR_DEV_HAS_EXTENDED_HASH;
751 FSL_GIANFAR_DEV_HAS_TIMER;
752 751
753 ctype = of_get_property(np, "phy-connection-type", NULL); 752 ctype = of_get_property(np, "phy-connection-type", NULL);
754 753
diff --git a/drivers/net/greth.c b/drivers/net/greth.c
index f37a4c143ddd..3a029d02c2b4 100644
--- a/drivers/net/greth.c
+++ b/drivers/net/greth.c
@@ -1607,14 +1607,13 @@ static struct of_device_id greth_of_match[] = {
1607MODULE_DEVICE_TABLE(of, greth_of_match); 1607MODULE_DEVICE_TABLE(of, greth_of_match);
1608 1608
1609static struct of_platform_driver greth_of_driver = { 1609static struct of_platform_driver greth_of_driver = {
1610 .name = "grlib-greth", 1610 .driver = {
1611 .match_table = greth_of_match, 1611 .name = "grlib-greth",
1612 .owner = THIS_MODULE,
1613 .of_match_table = greth_of_match,
1614 },
1612 .probe = greth_of_probe, 1615 .probe = greth_of_probe,
1613 .remove = __devexit_p(greth_of_remove), 1616 .remove = __devexit_p(greth_of_remove),
1614 .driver = {
1615 .owner = THIS_MODULE,
1616 .name = "grlib-greth",
1617 },
1618}; 1617};
1619 1618
1620static int __init greth_init(void) 1619static int __init greth_init(void)
diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c
index 694132e04af6..4e7d1d0a2340 100644
--- a/drivers/net/hamradio/yam.c
+++ b/drivers/net/hamradio/yam.c
@@ -1151,8 +1151,7 @@ static int __init yam_init_driver(void)
1151 dev = alloc_netdev(sizeof(struct yam_port), name, 1151 dev = alloc_netdev(sizeof(struct yam_port), name,
1152 yam_setup); 1152 yam_setup);
1153 if (!dev) { 1153 if (!dev) {
1154 printk(KERN_ERR "yam: cannot allocate net device %s\n", 1154 pr_err("yam: cannot allocate net device\n");
1155 dev->name);
1156 err = -ENOMEM; 1155 err = -ENOMEM;
1157 goto error; 1156 goto error;
1158 } 1157 }
diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c
index 1159d9138f05..9595b1bfb8dd 100644
--- a/drivers/net/ixgbe/ixgbe_common.c
+++ b/drivers/net/ixgbe/ixgbe_common.c
@@ -1188,6 +1188,7 @@ s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq,
1188 IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); 1188 IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
1189 } else { 1189 } else {
1190 hw_dbg(hw, "RAR index %d is out of range.\n", index); 1190 hw_dbg(hw, "RAR index %d is out of range.\n", index);
1191 return IXGBE_ERR_RAR_INDEX;
1191 } 1192 }
1192 1193
1193 return 0; 1194 return 0;
@@ -1219,6 +1220,7 @@ s32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index)
1219 IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); 1220 IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
1220 } else { 1221 } else {
1221 hw_dbg(hw, "RAR index %d is out of range.\n", index); 1222 hw_dbg(hw, "RAR index %d is out of range.\n", index);
1223 return IXGBE_ERR_RAR_INDEX;
1222 } 1224 }
1223 1225
1224 /* clear VMDq pool/queue selection for this RAR */ 1226 /* clear VMDq pool/queue selection for this RAR */
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index d571d101de08..b2af2f67f604 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -642,7 +642,7 @@ static inline bool ixgbe_tx_xon_state(struct ixgbe_adapter *adapter,
642 u32 txoff = IXGBE_TFCS_TXOFF; 642 u32 txoff = IXGBE_TFCS_TXOFF;
643 643
644#ifdef CONFIG_IXGBE_DCB 644#ifdef CONFIG_IXGBE_DCB
645 if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { 645 if (adapter->dcb_cfg.pfc_mode_enable) {
646 int tc; 646 int tc;
647 int reg_idx = tx_ring->reg_idx; 647 int reg_idx = tx_ring->reg_idx;
648 int dcb_i = adapter->ring_feature[RING_F_DCB].indices; 648 int dcb_i = adapter->ring_feature[RING_F_DCB].indices;
diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h
index 2eb6e151016c..cdd1998f18c7 100644
--- a/drivers/net/ixgbe/ixgbe_type.h
+++ b/drivers/net/ixgbe/ixgbe_type.h
@@ -2609,6 +2609,7 @@ struct ixgbe_info {
2609#define IXGBE_ERR_EEPROM_VERSION -24 2609#define IXGBE_ERR_EEPROM_VERSION -24
2610#define IXGBE_ERR_NO_SPACE -25 2610#define IXGBE_ERR_NO_SPACE -25
2611#define IXGBE_ERR_OVERTEMP -26 2611#define IXGBE_ERR_OVERTEMP -26
2612#define IXGBE_ERR_RAR_INDEX -27
2612#define IXGBE_NOT_IMPLEMENTED 0x7FFFFFFF 2613#define IXGBE_NOT_IMPLEMENTED 0x7FFFFFFF
2613 2614
2614#endif /* _IXGBE_TYPE_H_ */ 2615#endif /* _IXGBE_TYPE_H_ */
diff --git a/drivers/net/korina.c b/drivers/net/korina.c
index 26bf1b76b997..c7a9bef4dfb0 100644
--- a/drivers/net/korina.c
+++ b/drivers/net/korina.c
@@ -135,6 +135,7 @@ struct korina_private {
135 struct napi_struct napi; 135 struct napi_struct napi;
136 struct timer_list media_check_timer; 136 struct timer_list media_check_timer;
137 struct mii_if_info mii_if; 137 struct mii_if_info mii_if;
138 struct work_struct restart_task;
138 struct net_device *dev; 139 struct net_device *dev;
139 int phy_addr; 140 int phy_addr;
140}; 141};
@@ -375,7 +376,7 @@ static int korina_rx(struct net_device *dev, int limit)
375 if (devcs & ETH_RX_LE) 376 if (devcs & ETH_RX_LE)
376 dev->stats.rx_length_errors++; 377 dev->stats.rx_length_errors++;
377 if (devcs & ETH_RX_OVR) 378 if (devcs & ETH_RX_OVR)
378 dev->stats.rx_over_errors++; 379 dev->stats.rx_fifo_errors++;
379 if (devcs & ETH_RX_CV) 380 if (devcs & ETH_RX_CV)
380 dev->stats.rx_frame_errors++; 381 dev->stats.rx_frame_errors++;
381 if (devcs & ETH_RX_CES) 382 if (devcs & ETH_RX_CES)
@@ -764,10 +765,9 @@ static int korina_alloc_ring(struct net_device *dev)
764 765
765 /* Initialize the receive descriptors */ 766 /* Initialize the receive descriptors */
766 for (i = 0; i < KORINA_NUM_RDS; i++) { 767 for (i = 0; i < KORINA_NUM_RDS; i++) {
767 skb = dev_alloc_skb(KORINA_RBSIZE + 2); 768 skb = netdev_alloc_skb_ip_align(dev, KORINA_RBSIZE);
768 if (!skb) 769 if (!skb)
769 return -ENOMEM; 770 return -ENOMEM;
770 skb_reserve(skb, 2);
771 lp->rx_skb[i] = skb; 771 lp->rx_skb[i] = skb;
772 lp->rd_ring[i].control = DMA_DESC_IOD | 772 lp->rd_ring[i].control = DMA_DESC_IOD |
773 DMA_COUNT(KORINA_RBSIZE); 773 DMA_COUNT(KORINA_RBSIZE);
@@ -890,12 +890,12 @@ static int korina_init(struct net_device *dev)
890 890
891/* 891/*
892 * Restart the RC32434 ethernet controller. 892 * Restart the RC32434 ethernet controller.
893 * FIXME: check the return status where we call it
894 */ 893 */
895static int korina_restart(struct net_device *dev) 894static void korina_restart_task(struct work_struct *work)
896{ 895{
897 struct korina_private *lp = netdev_priv(dev); 896 struct korina_private *lp = container_of(work,
898 int ret; 897 struct korina_private, restart_task);
898 struct net_device *dev = lp->dev;
899 899
900 /* 900 /*
901 * Disable interrupts 901 * Disable interrupts
@@ -916,10 +916,9 @@ static int korina_restart(struct net_device *dev)
916 916
917 napi_disable(&lp->napi); 917 napi_disable(&lp->napi);
918 918
919 ret = korina_init(dev); 919 if (korina_init(dev) < 0) {
920 if (ret < 0) {
921 printk(KERN_ERR "%s: cannot restart device\n", dev->name); 920 printk(KERN_ERR "%s: cannot restart device\n", dev->name);
922 return ret; 921 return;
923 } 922 }
924 korina_multicast_list(dev); 923 korina_multicast_list(dev);
925 924
@@ -927,8 +926,6 @@ static int korina_restart(struct net_device *dev)
927 enable_irq(lp->ovr_irq); 926 enable_irq(lp->ovr_irq);
928 enable_irq(lp->tx_irq); 927 enable_irq(lp->tx_irq);
929 enable_irq(lp->rx_irq); 928 enable_irq(lp->rx_irq);
930
931 return ret;
932} 929}
933 930
934static void korina_clear_and_restart(struct net_device *dev, u32 value) 931static 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)
937 934
938 netif_stop_queue(dev); 935 netif_stop_queue(dev);
939 writel(value, &lp->eth_regs->ethintfc); 936 writel(value, &lp->eth_regs->ethintfc);
940 korina_restart(dev); 937 schedule_work(&lp->restart_task);
941} 938}
942 939
943/* Ethernet Tx Underflow interrupt */ 940/* Ethernet Tx Underflow interrupt */
@@ -962,11 +959,8 @@ static irqreturn_t korina_und_interrupt(int irq, void *dev_id)
962static void korina_tx_timeout(struct net_device *dev) 959static void korina_tx_timeout(struct net_device *dev)
963{ 960{
964 struct korina_private *lp = netdev_priv(dev); 961 struct korina_private *lp = netdev_priv(dev);
965 unsigned long flags;
966 962
967 spin_lock_irqsave(&lp->lock, flags); 963 schedule_work(&lp->restart_task);
968 korina_restart(dev);
969 spin_unlock_irqrestore(&lp->lock, flags);
970} 964}
971 965
972/* Ethernet Rx Overflow interrupt */ 966/* Ethernet Rx Overflow interrupt */
@@ -1086,6 +1080,8 @@ static int korina_close(struct net_device *dev)
1086 1080
1087 napi_disable(&lp->napi); 1081 napi_disable(&lp->napi);
1088 1082
1083 cancel_work_sync(&lp->restart_task);
1084
1089 free_irq(lp->rx_irq, dev); 1085 free_irq(lp->rx_irq, dev);
1090 free_irq(lp->tx_irq, dev); 1086 free_irq(lp->tx_irq, dev);
1091 free_irq(lp->ovr_irq, dev); 1087 free_irq(lp->ovr_irq, dev);
@@ -1198,6 +1194,8 @@ static int korina_probe(struct platform_device *pdev)
1198 } 1194 }
1199 setup_timer(&lp->media_check_timer, korina_poll_media, (unsigned long) dev); 1195 setup_timer(&lp->media_check_timer, korina_poll_media, (unsigned long) dev);
1200 1196
1197 INIT_WORK(&lp->restart_task, korina_restart_task);
1198
1201 printk(KERN_INFO "%s: " DRV_NAME "-" DRV_VERSION " " DRV_RELDATE "\n", 1199 printk(KERN_INFO "%s: " DRV_NAME "-" DRV_VERSION " " DRV_RELDATE "\n",
1202 dev->name); 1200 dev->name);
1203out: 1201out:
diff --git a/drivers/net/ksz884x.c b/drivers/net/ksz884x.c
index c80ca64277b2..7805bbf1d53a 100644
--- a/drivers/net/ksz884x.c
+++ b/drivers/net/ksz884x.c
@@ -4854,7 +4854,7 @@ static inline void copy_old_skb(struct sk_buff *old, struct sk_buff *skb)
4854 * 4854 *
4855 * Return 0 if successful; otherwise an error code indicating failure. 4855 * Return 0 if successful; otherwise an error code indicating failure.
4856 */ 4856 */
4857static int netdev_tx(struct sk_buff *skb, struct net_device *dev) 4857static netdev_tx_t netdev_tx(struct sk_buff *skb, struct net_device *dev)
4858{ 4858{
4859 struct dev_priv *priv = netdev_priv(dev); 4859 struct dev_priv *priv = netdev_priv(dev);
4860 struct dev_info *hw_priv = priv->adapter; 4860 struct dev_info *hw_priv = priv->adapter;
@@ -6863,6 +6863,7 @@ static const struct net_device_ops netdev_ops = {
6863 .ndo_tx_timeout = netdev_tx_timeout, 6863 .ndo_tx_timeout = netdev_tx_timeout,
6864 .ndo_change_mtu = netdev_change_mtu, 6864 .ndo_change_mtu = netdev_change_mtu,
6865 .ndo_set_mac_address = netdev_set_mac_address, 6865 .ndo_set_mac_address = netdev_set_mac_address,
6866 .ndo_validate_addr = eth_validate_addr,
6866 .ndo_do_ioctl = netdev_ioctl, 6867 .ndo_do_ioctl = netdev_ioctl,
6867 .ndo_set_rx_mode = netdev_set_rx_mode, 6868 .ndo_set_rx_mode = netdev_set_rx_mode,
6868#ifdef CONFIG_NET_POLL_CONTROLLER 6869#ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/ll_temac.h b/drivers/net/ll_temac.h
index c03358434acb..522abe2ff25a 100644
--- a/drivers/net/ll_temac.h
+++ b/drivers/net/ll_temac.h
@@ -295,6 +295,10 @@ This option defaults to enabled (set) */
295 295
296#define MULTICAST_CAM_TABLE_NUM 4 296#define MULTICAST_CAM_TABLE_NUM 4
297 297
298/* TEMAC Synthesis features */
299#define TEMAC_FEATURE_RX_CSUM (1 << 0)
300#define TEMAC_FEATURE_TX_CSUM (1 << 1)
301
298/* TX/RX CURDESC_PTR points to first descriptor */ 302/* TX/RX CURDESC_PTR points to first descriptor */
299/* TX/RX TAILDESC_PTR points to last descriptor in linked list */ 303/* TX/RX TAILDESC_PTR points to last descriptor in linked list */
300 304
@@ -353,6 +357,7 @@ struct temac_local {
353 struct mutex indirect_mutex; 357 struct mutex indirect_mutex;
354 u32 options; /* Current options word */ 358 u32 options; /* Current options word */
355 int last_link; 359 int last_link;
360 unsigned int temac_features;
356 361
357 /* Buffer descriptors */ 362 /* Buffer descriptors */
358 struct cdmac_bd *tx_bd_v; 363 struct cdmac_bd *tx_bd_v;
diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c
index fa7620e28404..52dcc8495647 100644
--- a/drivers/net/ll_temac_main.c
+++ b/drivers/net/ll_temac_main.c
@@ -245,7 +245,7 @@ static int temac_dma_bd_init(struct net_device *ndev)
245 CHNL_CTRL_IRQ_COAL_EN); 245 CHNL_CTRL_IRQ_COAL_EN);
246 /* 0x10220483 */ 246 /* 0x10220483 */
247 /* 0x00100483 */ 247 /* 0x00100483 */
248 lp->dma_out(lp, RX_CHNL_CTRL, 0xff010000 | 248 lp->dma_out(lp, RX_CHNL_CTRL, 0xff070000 |
249 CHNL_CTRL_IRQ_EN | 249 CHNL_CTRL_IRQ_EN |
250 CHNL_CTRL_IRQ_DLY_EN | 250 CHNL_CTRL_IRQ_DLY_EN |
251 CHNL_CTRL_IRQ_COAL_EN | 251 CHNL_CTRL_IRQ_COAL_EN |
@@ -574,6 +574,10 @@ static void temac_start_xmit_done(struct net_device *ndev)
574 if (cur_p->app4) 574 if (cur_p->app4)
575 dev_kfree_skb_irq((struct sk_buff *)cur_p->app4); 575 dev_kfree_skb_irq((struct sk_buff *)cur_p->app4);
576 cur_p->app0 = 0; 576 cur_p->app0 = 0;
577 cur_p->app1 = 0;
578 cur_p->app2 = 0;
579 cur_p->app3 = 0;
580 cur_p->app4 = 0;
577 581
578 ndev->stats.tx_packets++; 582 ndev->stats.tx_packets++;
579 ndev->stats.tx_bytes += cur_p->len; 583 ndev->stats.tx_bytes += cur_p->len;
@@ -589,6 +593,29 @@ static void temac_start_xmit_done(struct net_device *ndev)
589 netif_wake_queue(ndev); 593 netif_wake_queue(ndev);
590} 594}
591 595
596static inline int temac_check_tx_bd_space(struct temac_local *lp, int num_frag)
597{
598 struct cdmac_bd *cur_p;
599 int tail;
600
601 tail = lp->tx_bd_tail;
602 cur_p = &lp->tx_bd_v[tail];
603
604 do {
605 if (cur_p->app0)
606 return NETDEV_TX_BUSY;
607
608 tail++;
609 if (tail >= TX_BD_NUM)
610 tail = 0;
611
612 cur_p = &lp->tx_bd_v[tail];
613 num_frag--;
614 } while (num_frag >= 0);
615
616 return 0;
617}
618
592static int temac_start_xmit(struct sk_buff *skb, struct net_device *ndev) 619static int temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
593{ 620{
594 struct temac_local *lp = netdev_priv(ndev); 621 struct temac_local *lp = netdev_priv(ndev);
@@ -603,7 +630,7 @@ static int temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
603 start_p = lp->tx_bd_p + sizeof(*lp->tx_bd_v) * lp->tx_bd_tail; 630 start_p = lp->tx_bd_p + sizeof(*lp->tx_bd_v) * lp->tx_bd_tail;
604 cur_p = &lp->tx_bd_v[lp->tx_bd_tail]; 631 cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
605 632
606 if (cur_p->app0 & STS_CTRL_APP0_CMPLT) { 633 if (temac_check_tx_bd_space(lp, num_frag)) {
607 if (!netif_queue_stopped(ndev)) { 634 if (!netif_queue_stopped(ndev)) {
608 netif_stop_queue(ndev); 635 netif_stop_queue(ndev);
609 return NETDEV_TX_BUSY; 636 return NETDEV_TX_BUSY;
@@ -613,29 +640,14 @@ static int temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
613 640
614 cur_p->app0 = 0; 641 cur_p->app0 = 0;
615 if (skb->ip_summed == CHECKSUM_PARTIAL) { 642 if (skb->ip_summed == CHECKSUM_PARTIAL) {
616 const struct iphdr *ip = ip_hdr(skb); 643 unsigned int csum_start_off = skb_transport_offset(skb);
617 int length = 0, start = 0, insert = 0; 644 unsigned int csum_index_off = csum_start_off + skb->csum_offset;
618 645
619 switch (ip->protocol) { 646 cur_p->app0 |= 1; /* TX Checksum Enabled */
620 case IPPROTO_TCP: 647 cur_p->app1 = (csum_start_off << 16) | csum_index_off;
621 start = sizeof(struct iphdr) + ETH_HLEN; 648 cur_p->app2 = 0; /* initial checksum seed */
622 insert = sizeof(struct iphdr) + ETH_HLEN + 16;
623 length = ip->tot_len - sizeof(struct iphdr);
624 break;
625 case IPPROTO_UDP:
626 start = sizeof(struct iphdr) + ETH_HLEN;
627 insert = sizeof(struct iphdr) + ETH_HLEN + 6;
628 length = ip->tot_len - sizeof(struct iphdr);
629 break;
630 default:
631 break;
632 }
633 cur_p->app1 = ((start << 16) | insert);
634 cur_p->app2 = csum_tcpudp_magic(ip->saddr, ip->daddr,
635 length, ip->protocol, 0);
636 skb->data[insert] = 0;
637 skb->data[insert + 1] = 0;
638 } 649 }
650
639 cur_p->app0 |= STS_CTRL_APP0_SOP; 651 cur_p->app0 |= STS_CTRL_APP0_SOP;
640 cur_p->len = skb_headlen(skb); 652 cur_p->len = skb_headlen(skb);
641 cur_p->phys = dma_map_single(ndev->dev.parent, skb->data, skb->len, 653 cur_p->phys = dma_map_single(ndev->dev.parent, skb->data, skb->len,
@@ -699,6 +711,15 @@ static void ll_temac_recv(struct net_device *ndev)
699 skb->protocol = eth_type_trans(skb, ndev); 711 skb->protocol = eth_type_trans(skb, ndev);
700 skb->ip_summed = CHECKSUM_NONE; 712 skb->ip_summed = CHECKSUM_NONE;
701 713
714 /* if we're doing rx csum offload, set it up */
715 if (((lp->temac_features & TEMAC_FEATURE_RX_CSUM) != 0) &&
716 (skb->protocol == __constant_htons(ETH_P_IP)) &&
717 (skb->len > 64)) {
718
719 skb->csum = cur_p->app3 & 0xFFFF;
720 skb->ip_summed = CHECKSUM_COMPLETE;
721 }
722
702 netif_rx(skb); 723 netif_rx(skb);
703 724
704 ndev->stats.rx_packets++; 725 ndev->stats.rx_packets++;
@@ -883,6 +904,7 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
883 struct temac_local *lp; 904 struct temac_local *lp;
884 struct net_device *ndev; 905 struct net_device *ndev;
885 const void *addr; 906 const void *addr;
907 __be32 *p;
886 int size, rc = 0; 908 int size, rc = 0;
887 909
888 /* Init network device structure */ 910 /* Init network device structure */
@@ -926,6 +948,18 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
926 goto nodev; 948 goto nodev;
927 } 949 }
928 950
951 /* Setup checksum offload, but default to off if not specified */
952 lp->temac_features = 0;
953 p = (__be32 *)of_get_property(op->dev.of_node, "xlnx,txcsum", NULL);
954 if (p && be32_to_cpu(*p)) {
955 lp->temac_features |= TEMAC_FEATURE_TX_CSUM;
956 /* Can checksum TCP/UDP over IPv4. */
957 ndev->features |= NETIF_F_IP_CSUM;
958 }
959 p = (__be32 *)of_get_property(op->dev.of_node, "xlnx,rxcsum", NULL);
960 if (p && be32_to_cpu(*p))
961 lp->temac_features |= TEMAC_FEATURE_RX_CSUM;
962
929 /* Find the DMA node, map the DMA registers, and decode the DMA IRQs */ 963 /* Find the DMA node, map the DMA registers, and decode the DMA IRQs */
930 np = of_parse_phandle(op->dev.of_node, "llink-connected", 0); 964 np = of_parse_phandle(op->dev.of_node, "llink-connected", 0);
931 if (!np) { 965 if (!np) {
@@ -950,7 +984,7 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
950 984
951 lp->rx_irq = irq_of_parse_and_map(np, 0); 985 lp->rx_irq = irq_of_parse_and_map(np, 0);
952 lp->tx_irq = irq_of_parse_and_map(np, 1); 986 lp->tx_irq = irq_of_parse_and_map(np, 1);
953 if (!lp->rx_irq || !lp->tx_irq) { 987 if ((lp->rx_irq == NO_IRQ) || (lp->tx_irq == NO_IRQ)) {
954 dev_err(&op->dev, "could not determine irqs\n"); 988 dev_err(&op->dev, "could not determine irqs\n");
955 rc = -ENOMEM; 989 rc = -ENOMEM;
956 goto nodev; 990 goto nodev;
diff --git a/drivers/net/mace.c b/drivers/net/mace.c
index b6855a6476f8..1c5221f79d6f 100644
--- a/drivers/net/mace.c
+++ b/drivers/net/mace.c
@@ -997,8 +997,11 @@ MODULE_DEVICE_TABLE (of, mace_match);
997 997
998static struct macio_driver mace_driver = 998static struct macio_driver mace_driver =
999{ 999{
1000 .name = "mace", 1000 .driver = {
1001 .match_table = mace_match, 1001 .name = "mace",
1002 .owner = THIS_MODULE,
1003 .of_match_table = mace_match,
1004 },
1002 .probe = mace_probe, 1005 .probe = mace_probe,
1003 .remove = mace_remove, 1006 .remove = mace_remove,
1004}; 1007};
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index 7b6fe89f9db0..64e6a84bbbbe 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -322,6 +322,7 @@ static int smc91c92_probe(struct pcmcia_device *link)
322 return -ENOMEM; 322 return -ENOMEM;
323 smc = netdev_priv(dev); 323 smc = netdev_priv(dev);
324 smc->p_dev = link; 324 smc->p_dev = link;
325 link->priv = dev;
325 326
326 spin_lock_init(&smc->lock); 327 spin_lock_init(&smc->lock);
327 link->io.NumPorts1 = 16; 328 link->io.NumPorts1 = 16;
diff --git a/drivers/net/phy/lxt.c b/drivers/net/phy/lxt.c
index 8ee929b796d8..dbd003453737 100644
--- a/drivers/net/phy/lxt.c
+++ b/drivers/net/phy/lxt.c
@@ -53,6 +53,9 @@
53 53
54#define MII_LXT971_ISR 19 /* Interrupt Status Register */ 54#define MII_LXT971_ISR 19 /* Interrupt Status Register */
55 55
56/* register definitions for the 973 */
57#define MII_LXT973_PCR 16 /* Port Configuration Register */
58#define PCR_FIBER_SELECT 1
56 59
57MODULE_DESCRIPTION("Intel LXT PHY driver"); 60MODULE_DESCRIPTION("Intel LXT PHY driver");
58MODULE_AUTHOR("Andy Fleming"); 61MODULE_AUTHOR("Andy Fleming");
@@ -119,6 +122,33 @@ static int lxt971_config_intr(struct phy_device *phydev)
119 return err; 122 return err;
120} 123}
121 124
125static int lxt973_probe(struct phy_device *phydev)
126{
127 int val = phy_read(phydev, MII_LXT973_PCR);
128
129 if (val & PCR_FIBER_SELECT) {
130 /*
131 * If fiber is selected, then the only correct setting
132 * is 100Mbps, full duplex, and auto negotiation off.
133 */
134 val = phy_read(phydev, MII_BMCR);
135 val |= (BMCR_SPEED100 | BMCR_FULLDPLX);
136 val &= ~BMCR_ANENABLE;
137 phy_write(phydev, MII_BMCR, val);
138 /* Remember that the port is in fiber mode. */
139 phydev->priv = lxt973_probe;
140 } else {
141 phydev->priv = NULL;
142 }
143 return 0;
144}
145
146static int lxt973_config_aneg(struct phy_device *phydev)
147{
148 /* Do nothing if port is in fiber mode. */
149 return phydev->priv ? 0 : genphy_config_aneg(phydev);
150}
151
122static struct phy_driver lxt970_driver = { 152static struct phy_driver lxt970_driver = {
123 .phy_id = 0x78100000, 153 .phy_id = 0x78100000,
124 .name = "LXT970", 154 .name = "LXT970",
@@ -146,6 +176,18 @@ static struct phy_driver lxt971_driver = {
146 .driver = { .owner = THIS_MODULE,}, 176 .driver = { .owner = THIS_MODULE,},
147}; 177};
148 178
179static struct phy_driver lxt973_driver = {
180 .phy_id = 0x00137a10,
181 .name = "LXT973",
182 .phy_id_mask = 0xfffffff0,
183 .features = PHY_BASIC_FEATURES,
184 .flags = 0,
185 .probe = lxt973_probe,
186 .config_aneg = lxt973_config_aneg,
187 .read_status = genphy_read_status,
188 .driver = { .owner = THIS_MODULE,},
189};
190
149static int __init lxt_init(void) 191static int __init lxt_init(void)
150{ 192{
151 int ret; 193 int ret;
@@ -157,9 +199,15 @@ static int __init lxt_init(void)
157 ret = phy_driver_register(&lxt971_driver); 199 ret = phy_driver_register(&lxt971_driver);
158 if (ret) 200 if (ret)
159 goto err2; 201 goto err2;
202
203 ret = phy_driver_register(&lxt973_driver);
204 if (ret)
205 goto err3;
160 return 0; 206 return 0;
161 207
162 err2: 208 err3:
209 phy_driver_unregister(&lxt971_driver);
210 err2:
163 phy_driver_unregister(&lxt970_driver); 211 phy_driver_unregister(&lxt970_driver);
164 err1: 212 err1:
165 return ret; 213 return ret;
@@ -169,6 +217,7 @@ static void __exit lxt_exit(void)
169{ 217{
170 phy_driver_unregister(&lxt970_driver); 218 phy_driver_unregister(&lxt970_driver);
171 phy_driver_unregister(&lxt971_driver); 219 phy_driver_unregister(&lxt971_driver);
220 phy_driver_unregister(&lxt973_driver);
172} 221}
173 222
174module_init(lxt_init); 223module_init(lxt_init);
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index c5f8eb102bf7..1b2c29150202 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -1422,7 +1422,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
1422 flen = len; 1422 flen = len;
1423 if (nfree > 0) { 1423 if (nfree > 0) {
1424 if (pch->speed == 0) { 1424 if (pch->speed == 0) {
1425 flen = totlen/nfree; 1425 flen = len/nfree;
1426 if (nbigger > 0) { 1426 if (nbigger > 0) {
1427 flen++; 1427 flen++;
1428 nbigger--; 1428 nbigger--;
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 217e709bda3e..96b6cfbf0a3a 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -559,6 +559,11 @@ static void mdio_write(void __iomem *ioaddr, int reg_addr, int value)
559 break; 559 break;
560 udelay(25); 560 udelay(25);
561 } 561 }
562 /*
563 * According to hardware specs a 20us delay is required after write
564 * complete indication, but before sending next command.
565 */
566 udelay(20);
562} 567}
563 568
564static int mdio_read(void __iomem *ioaddr, int reg_addr) 569static int mdio_read(void __iomem *ioaddr, int reg_addr)
@@ -578,6 +583,12 @@ static int mdio_read(void __iomem *ioaddr, int reg_addr)
578 } 583 }
579 udelay(25); 584 udelay(25);
580 } 585 }
586 /*
587 * According to hardware specs a 20us delay is required after read
588 * complete indication, but before sending next command.
589 */
590 udelay(20);
591
581 return value; 592 return value;
582} 593}
583 594
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index 2e6fd89f2a72..4762c91cb587 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -830,7 +830,7 @@ static inline const char *efx_dev_name(struct efx_nic *efx)
830 830
831static inline unsigned int efx_port_num(struct efx_nic *efx) 831static inline unsigned int efx_port_num(struct efx_nic *efx)
832{ 832{
833 return PCI_FUNC(efx->pci_dev->devfn); 833 return efx->net_dev->dev_id;
834} 834}
835 835
836/** 836/**
diff --git a/drivers/net/sfc/siena.c b/drivers/net/sfc/siena.c
index 727b4228e081..f2b1e6180753 100644
--- a/drivers/net/sfc/siena.c
+++ b/drivers/net/sfc/siena.c
@@ -206,6 +206,7 @@ static int siena_probe_nic(struct efx_nic *efx)
206{ 206{
207 struct siena_nic_data *nic_data; 207 struct siena_nic_data *nic_data;
208 bool already_attached = 0; 208 bool already_attached = 0;
209 efx_oword_t reg;
209 int rc; 210 int rc;
210 211
211 /* Allocate storage for hardware specific data */ 212 /* Allocate storage for hardware specific data */
@@ -220,6 +221,9 @@ static int siena_probe_nic(struct efx_nic *efx)
220 goto fail1; 221 goto fail1;
221 } 222 }
222 223
224 efx_reado(efx, &reg, FR_AZ_CS_DEBUG);
225 efx->net_dev->dev_id = EFX_OWORD_FIELD(reg, FRF_CZ_CS_PORT_NUM) - 1;
226
223 efx_mcdi_init(efx); 227 efx_mcdi_init(efx);
224 228
225 /* Recover from a failed assertion before probing */ 229 /* Recover from a failed assertion before probing */
diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c
index 20ab16192325..737df6032bbc 100644
--- a/drivers/net/tehuti.c
+++ b/drivers/net/tehuti.c
@@ -646,7 +646,7 @@ static int bdx_ioctl_priv(struct net_device *ndev, struct ifreq *ifr, int cmd)
646 error = copy_from_user(data, ifr->ifr_data, sizeof(data)); 646 error = copy_from_user(data, ifr->ifr_data, sizeof(data));
647 if (error) { 647 if (error) {
648 pr_err("cant copy from user\n"); 648 pr_err("cant copy from user\n");
649 RET(error); 649 RET(-EFAULT);
650 } 650 }
651 DBG("%d 0x%x 0x%x\n", data[0], data[1], data[2]); 651 DBG("%d 0x%x 0x%x\n", data[0], data[1], data[2]);
652 } 652 }
@@ -665,7 +665,7 @@ static int bdx_ioctl_priv(struct net_device *ndev, struct ifreq *ifr, int cmd)
665 data[2]); 665 data[2]);
666 error = copy_to_user(ifr->ifr_data, data, sizeof(data)); 666 error = copy_to_user(ifr->ifr_data, data, sizeof(data));
667 if (error) 667 if (error)
668 RET(error); 668 RET(-EFAULT);
669 break; 669 break;
670 670
671 case BDX_OP_WRITE: 671 case BDX_OP_WRITE:
diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c
index 1f802e90474c..9516f382a6ba 100644
--- a/drivers/net/usb/asix.c
+++ b/drivers/net/usb/asix.c
@@ -344,7 +344,7 @@ static int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
344 return 2; 344 return 2;
345 } 345 }
346 346
347 if (size > ETH_FRAME_LEN) { 347 if (size > dev->net->mtu + ETH_HLEN) {
348 netdev_err(dev->net, "asix_rx_fixup() Bad RX Length %d\n", 348 netdev_err(dev->net, "asix_rx_fixup() Bad RX Length %d\n",
349 size); 349 size);
350 return 0; 350 return 0;
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 78eb3190b9b1..1edb7a61983c 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -340,7 +340,7 @@ static int add_recvbuf_small(struct virtnet_info *vi, gfp_t gfp)
340 340
341 skb_to_sgvec(skb, vi->rx_sg + 1, 0, skb->len); 341 skb_to_sgvec(skb, vi->rx_sg + 1, 0, skb->len);
342 342
343 err = virtqueue_add_buf(vi->rvq, vi->rx_sg, 0, 2, skb); 343 err = virtqueue_add_buf_gfp(vi->rvq, vi->rx_sg, 0, 2, skb, gfp);
344 if (err < 0) 344 if (err < 0)
345 dev_kfree_skb(skb); 345 dev_kfree_skb(skb);
346 346
@@ -385,8 +385,8 @@ static int add_recvbuf_big(struct virtnet_info *vi, gfp_t gfp)
385 385
386 /* chain first in list head */ 386 /* chain first in list head */
387 first->private = (unsigned long)list; 387 first->private = (unsigned long)list;
388 err = virtqueue_add_buf(vi->rvq, vi->rx_sg, 0, MAX_SKB_FRAGS + 2, 388 err = virtqueue_add_buf_gfp(vi->rvq, vi->rx_sg, 0, MAX_SKB_FRAGS + 2,
389 first); 389 first, gfp);
390 if (err < 0) 390 if (err < 0)
391 give_pages(vi, first); 391 give_pages(vi, first);
392 392
@@ -404,7 +404,7 @@ static int add_recvbuf_mergeable(struct virtnet_info *vi, gfp_t gfp)
404 404
405 sg_init_one(vi->rx_sg, page_address(page), PAGE_SIZE); 405 sg_init_one(vi->rx_sg, page_address(page), PAGE_SIZE);
406 406
407 err = virtqueue_add_buf(vi->rvq, vi->rx_sg, 0, 1, page); 407 err = virtqueue_add_buf_gfp(vi->rvq, vi->rx_sg, 0, 1, page, gfp);
408 if (err < 0) 408 if (err < 0)
409 give_pages(vi, page); 409 give_pages(vi, page);
410 410
diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c
index 166e77dfffda..e47f5a986b1c 100644
--- a/drivers/net/wan/x25_asy.c
+++ b/drivers/net/wan/x25_asy.c
@@ -37,8 +37,6 @@
37#include <net/x25device.h> 37#include <net/x25device.h>
38#include "x25_asy.h" 38#include "x25_asy.h"
39 39
40#include <net/x25device.h>
41
42static struct net_device **x25_asy_devs; 40static struct net_device **x25_asy_devs;
43static int x25_asy_maxdev = SL_NRUNIT; 41static int x25_asy_maxdev = SL_NRUNIT;
44 42
diff --git a/drivers/net/wimax/i2400m/fw.c b/drivers/net/wimax/i2400m/fw.c
index 3f283bff0ff7..11491354e5b5 100644
--- a/drivers/net/wimax/i2400m/fw.c
+++ b/drivers/net/wimax/i2400m/fw.c
@@ -1192,7 +1192,7 @@ int i2400m_fw_hdr_check(struct i2400m *i2400m,
1192 unsigned module_type, header_len, major_version, minor_version, 1192 unsigned module_type, header_len, major_version, minor_version,
1193 module_id, module_vendor, date, size; 1193 module_id, module_vendor, date, size;
1194 1194
1195 module_type = bcf_hdr->module_type; 1195 module_type = le32_to_cpu(bcf_hdr->module_type);
1196 header_len = sizeof(u32) * le32_to_cpu(bcf_hdr->header_len); 1196 header_len = sizeof(u32) * le32_to_cpu(bcf_hdr->header_len);
1197 major_version = (le32_to_cpu(bcf_hdr->header_version) & 0xffff0000) 1197 major_version = (le32_to_cpu(bcf_hdr->header_version) & 0xffff0000)
1198 >> 16; 1198 >> 16;
diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c
index 82ab532a4923..a93dc18a45c3 100644
--- a/drivers/net/wireless/ath/ar9170/usb.c
+++ b/drivers/net/wireless/ath/ar9170/usb.c
@@ -739,17 +739,27 @@ err_out:
739static void ar9170_usb_firmware_failed(struct ar9170_usb *aru) 739static void ar9170_usb_firmware_failed(struct ar9170_usb *aru)
740{ 740{
741 struct device *parent = aru->udev->dev.parent; 741 struct device *parent = aru->udev->dev.parent;
742 struct usb_device *udev;
743
744 /*
745 * Store a copy of the usb_device pointer locally.
746 * This is because device_release_driver initiates
747 * ar9170_usb_disconnect, which in turn frees our
748 * driver context (aru).
749 */
750 udev = aru->udev;
742 751
743 complete(&aru->firmware_loading_complete); 752 complete(&aru->firmware_loading_complete);
744 753
745 /* unbind anything failed */ 754 /* unbind anything failed */
746 if (parent) 755 if (parent)
747 device_lock(parent); 756 device_lock(parent);
748 device_release_driver(&aru->udev->dev); 757
758 device_release_driver(&udev->dev);
749 if (parent) 759 if (parent)
750 device_unlock(parent); 760 device_unlock(parent);
751 761
752 usb_put_dev(aru->udev); 762 usb_put_dev(udev);
753} 763}
754 764
755static void ar9170_usb_firmware_finish(const struct firmware *fw, void *context) 765static void ar9170_usb_firmware_finish(const struct firmware *fw, void *context)
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index cc6d41dec332..648972df369d 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -195,7 +195,7 @@ static const struct ieee80211_rate ath5k_rates[] = {
195static int __devinit ath5k_pci_probe(struct pci_dev *pdev, 195static int __devinit ath5k_pci_probe(struct pci_dev *pdev,
196 const struct pci_device_id *id); 196 const struct pci_device_id *id);
197static void __devexit ath5k_pci_remove(struct pci_dev *pdev); 197static void __devexit ath5k_pci_remove(struct pci_dev *pdev);
198#ifdef CONFIG_PM 198#ifdef CONFIG_PM_SLEEP
199static int ath5k_pci_suspend(struct device *dev); 199static int ath5k_pci_suspend(struct device *dev);
200static int ath5k_pci_resume(struct device *dev); 200static int ath5k_pci_resume(struct device *dev);
201 201
@@ -203,7 +203,7 @@ static SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume);
203#define ATH5K_PM_OPS (&ath5k_pm_ops) 203#define ATH5K_PM_OPS (&ath5k_pm_ops)
204#else 204#else
205#define ATH5K_PM_OPS NULL 205#define ATH5K_PM_OPS NULL
206#endif /* CONFIG_PM */ 206#endif /* CONFIG_PM_SLEEP */
207 207
208static struct pci_driver ath5k_pci_driver = { 208static struct pci_driver ath5k_pci_driver = {
209 .name = KBUILD_MODNAME, 209 .name = KBUILD_MODNAME,
@@ -222,7 +222,6 @@ static int ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
222static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, 222static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
223 struct ath5k_txq *txq); 223 struct ath5k_txq *txq);
224static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan); 224static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan);
225static int ath5k_reset_wake(struct ath5k_softc *sc);
226static int ath5k_start(struct ieee80211_hw *hw); 225static int ath5k_start(struct ieee80211_hw *hw);
227static void ath5k_stop(struct ieee80211_hw *hw); 226static void ath5k_stop(struct ieee80211_hw *hw);
228static int ath5k_add_interface(struct ieee80211_hw *hw, 227static int ath5k_add_interface(struct ieee80211_hw *hw,
@@ -709,7 +708,7 @@ ath5k_pci_remove(struct pci_dev *pdev)
709 ieee80211_free_hw(hw); 708 ieee80211_free_hw(hw);
710} 709}
711 710
712#ifdef CONFIG_PM 711#ifdef CONFIG_PM_SLEEP
713static int ath5k_pci_suspend(struct device *dev) 712static int ath5k_pci_suspend(struct device *dev)
714{ 713{
715 struct ieee80211_hw *hw = pci_get_drvdata(to_pci_dev(dev)); 714 struct ieee80211_hw *hw = pci_get_drvdata(to_pci_dev(dev));
@@ -735,7 +734,7 @@ static int ath5k_pci_resume(struct device *dev)
735 ath5k_led_enable(sc); 734 ath5k_led_enable(sc);
736 return 0; 735 return 0;
737} 736}
738#endif /* CONFIG_PM */ 737#endif /* CONFIG_PM_SLEEP */
739 738
740 739
741/***********************\ 740/***********************\
@@ -2770,7 +2769,7 @@ ath5k_tasklet_reset(unsigned long data)
2770{ 2769{
2771 struct ath5k_softc *sc = (void *)data; 2770 struct ath5k_softc *sc = (void *)data;
2772 2771
2773 ath5k_reset_wake(sc); 2772 ath5k_reset(sc, sc->curchan);
2774} 2773}
2775 2774
2776/* 2775/*
@@ -2941,23 +2940,13 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan)
2941 ath5k_beacon_config(sc); 2940 ath5k_beacon_config(sc);
2942 /* intrs are enabled by ath5k_beacon_config */ 2941 /* intrs are enabled by ath5k_beacon_config */
2943 2942
2943 ieee80211_wake_queues(sc->hw);
2944
2944 return 0; 2945 return 0;
2945err: 2946err:
2946 return ret; 2947 return ret;
2947} 2948}
2948 2949
2949static int
2950ath5k_reset_wake(struct ath5k_softc *sc)
2951{
2952 int ret;
2953
2954 ret = ath5k_reset(sc, sc->curchan);
2955 if (!ret)
2956 ieee80211_wake_queues(sc->hw);
2957
2958 return ret;
2959}
2960
2961static int ath5k_start(struct ieee80211_hw *hw) 2950static int ath5k_start(struct ieee80211_hw *hw)
2962{ 2951{
2963 return ath5k_init(hw->priv); 2952 return ath5k_init(hw->priv);
@@ -3151,13 +3140,15 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw,
3151 3140
3152 if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) { 3141 if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) {
3153 if (*new_flags & FIF_PROMISC_IN_BSS) { 3142 if (*new_flags & FIF_PROMISC_IN_BSS) {
3154 rfilt |= AR5K_RX_FILTER_PROM;
3155 __set_bit(ATH_STAT_PROMISC, sc->status); 3143 __set_bit(ATH_STAT_PROMISC, sc->status);
3156 } else { 3144 } else {
3157 __clear_bit(ATH_STAT_PROMISC, sc->status); 3145 __clear_bit(ATH_STAT_PROMISC, sc->status);
3158 } 3146 }
3159 } 3147 }
3160 3148
3149 if (test_bit(ATH_STAT_PROMISC, sc->status))
3150 rfilt |= AR5K_RX_FILTER_PROM;
3151
3161 /* Note, AR5K_RX_FILTER_MCAST is already enabled */ 3152 /* Note, AR5K_RX_FILTER_MCAST is already enabled */
3162 if (*new_flags & FIF_ALLMULTI) { 3153 if (*new_flags & FIF_ALLMULTI) {
3163 mfilt[0] = ~0; 3154 mfilt[0] = ~0;
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c
index 1b81c4778800..492cbb15720d 100644
--- a/drivers/net/wireless/ath/ath5k/phy.c
+++ b/drivers/net/wireless/ath/ath5k/phy.c
@@ -1814,6 +1814,13 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode)
1814 u8 def_ant, tx_ant, ee_mode; 1814 u8 def_ant, tx_ant, ee_mode;
1815 u32 sta_id1 = 0; 1815 u32 sta_id1 = 0;
1816 1816
1817 /* if channel is not initialized yet we can't set the antennas
1818 * so just store the mode. it will be set on the next reset */
1819 if (channel == NULL) {
1820 ah->ah_ant_mode = ant_mode;
1821 return;
1822 }
1823
1817 def_ant = ah->ah_def_ant; 1824 def_ant = ah->ah_def_ant;
1818 1825
1819 ATH5K_TRACE(ah->ah_sc); 1826 ATH5K_TRACE(ah->ah_sc);
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 3db19172b43b..859aa4ab0769 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -1198,7 +1198,7 @@ void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
1198 int r; 1198 int r;
1199 1199
1200 ath_print(common, ATH_DBG_FATAL, 1200 ath_print(common, ATH_DBG_FATAL,
1201 "Unable to stop TxDMA. Reset HAL!\n"); 1201 "Failed to stop TX DMA. Resetting hardware!\n");
1202 1202
1203 spin_lock_bh(&sc->sc_resetlock); 1203 spin_lock_bh(&sc->sc_resetlock);
1204 r = ath9k_hw_reset(ah, sc->sc_ah->curchan, false); 1204 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,
1728 } else 1728 } else
1729 bf->bf_isnullfunc = false; 1729 bf->bf_isnullfunc = false;
1730 1730
1731 bf->bf_tx_aborted = false;
1732
1731 return 0; 1733 return 0;
1732} 1734}
1733 1735
@@ -1989,7 +1991,7 @@ static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf,
1989 int nbad = 0; 1991 int nbad = 0;
1990 int isaggr = 0; 1992 int isaggr = 0;
1991 1993
1992 if (bf->bf_tx_aborted) 1994 if (bf->bf_lastbf->bf_tx_aborted)
1993 return 0; 1995 return 0;
1994 1996
1995 isaggr = bf_isaggr(bf); 1997 isaggr = bf_isaggr(bf);
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c
index d70732819423..ff9b5c882184 100644
--- a/drivers/net/wireless/hostap/hostap_hw.c
+++ b/drivers/net/wireless/hostap/hostap_hw.c
@@ -2618,15 +2618,6 @@ static irqreturn_t prism2_interrupt(int irq, void *dev_id)
2618 int events = 0; 2618 int events = 0;
2619 u16 ev; 2619 u16 ev;
2620 2620
2621 /* Detect early interrupt before driver is fully configued */
2622 if (!dev->base_addr) {
2623 if (net_ratelimit()) {
2624 printk(KERN_DEBUG "%s: Interrupt, but dev not configured\n",
2625 dev->name);
2626 }
2627 return IRQ_HANDLED;
2628 }
2629
2630 iface = netdev_priv(dev); 2621 iface = netdev_priv(dev);
2631 local = iface->local; 2622 local = iface->local;
2632 2623
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index 068f7f8435c5..c44a303e62ed 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -2852,6 +2852,7 @@ static struct iwl_lib_ops iwl3945_lib = {
2852 .isr = iwl_isr_legacy, 2852 .isr = iwl_isr_legacy,
2853 .config_ap = iwl3945_config_ap, 2853 .config_ap = iwl3945_config_ap,
2854 .manage_ibss_station = iwl3945_manage_ibss_station, 2854 .manage_ibss_station = iwl3945_manage_ibss_station,
2855 .recover_from_tx_stall = iwl_bg_monitor_recover,
2855 .check_plcp_health = iwl3945_good_plcp_health, 2856 .check_plcp_health = iwl3945_good_plcp_health,
2856 2857
2857 .debugfs_ops = { 2858 .debugfs_ops = {
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index 1004cfc403b1..0f292a210ed9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -1119,10 +1119,9 @@ static int iwl_get_single_channel_for_scan(struct iwl_priv *priv,
1119 struct iwl_scan_channel *scan_ch) 1119 struct iwl_scan_channel *scan_ch)
1120{ 1120{
1121 const struct ieee80211_supported_band *sband; 1121 const struct ieee80211_supported_band *sband;
1122 const struct iwl_channel_info *ch_info;
1123 u16 passive_dwell = 0; 1122 u16 passive_dwell = 0;
1124 u16 active_dwell = 0; 1123 u16 active_dwell = 0;
1125 int i, added = 0; 1124 int added = 0;
1126 u16 channel = 0; 1125 u16 channel = 0;
1127 1126
1128 sband = iwl_get_hw_mode(priv, band); 1127 sband = iwl_get_hw_mode(priv, band);
@@ -1137,32 +1136,7 @@ static int iwl_get_single_channel_for_scan(struct iwl_priv *priv,
1137 if (passive_dwell <= active_dwell) 1136 if (passive_dwell <= active_dwell)
1138 passive_dwell = active_dwell + 1; 1137 passive_dwell = active_dwell + 1;
1139 1138
1140 /* only scan single channel, good enough to reset the RF */ 1139 channel = iwl_get_single_channel_number(priv, band);
1141 /* pick the first valid not in-use channel */
1142 if (band == IEEE80211_BAND_5GHZ) {
1143 for (i = 14; i < priv->channel_count; i++) {
1144 if (priv->channel_info[i].channel !=
1145 le16_to_cpu(priv->staging_rxon.channel)) {
1146 channel = priv->channel_info[i].channel;
1147 ch_info = iwl_get_channel_info(priv,
1148 band, channel);
1149 if (is_channel_valid(ch_info))
1150 break;
1151 }
1152 }
1153 } else {
1154 for (i = 0; i < 14; i++) {
1155 if (priv->channel_info[i].channel !=
1156 le16_to_cpu(priv->staging_rxon.channel)) {
1157 channel =
1158 priv->channel_info[i].channel;
1159 ch_info = iwl_get_channel_info(priv,
1160 band, channel);
1161 if (is_channel_valid(ch_info))
1162 break;
1163 }
1164 }
1165 }
1166 if (channel) { 1140 if (channel) {
1167 scan_ch->channel = cpu_to_le16(channel); 1141 scan_ch->channel = cpu_to_le16(channel);
1168 scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; 1142 scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
index c402bfc83f36..a732f1094e5d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
@@ -1125,6 +1125,7 @@ static void iwlagn_tx_status(struct iwl_priv *priv, struct sk_buff *skb)
1125 struct ieee80211_sta *sta; 1125 struct ieee80211_sta *sta;
1126 struct iwl_station_priv *sta_priv; 1126 struct iwl_station_priv *sta_priv;
1127 1127
1128 rcu_read_lock();
1128 sta = ieee80211_find_sta(priv->vif, hdr->addr1); 1129 sta = ieee80211_find_sta(priv->vif, hdr->addr1);
1129 if (sta) { 1130 if (sta) {
1130 sta_priv = (void *)sta->drv_priv; 1131 sta_priv = (void *)sta->drv_priv;
@@ -1133,6 +1134,7 @@ static void iwlagn_tx_status(struct iwl_priv *priv, struct sk_buff *skb)
1133 atomic_dec_return(&sta_priv->pending_frames) == 0) 1134 atomic_dec_return(&sta_priv->pending_frames) == 0)
1134 ieee80211_sta_block_awake(priv->hw, sta, false); 1135 ieee80211_sta_block_awake(priv->hw, sta, false);
1135 } 1136 }
1137 rcu_read_unlock();
1136 1138
1137 ieee80211_tx_status_irqsafe(priv->hw, skb); 1139 ieee80211_tx_status_irqsafe(priv->hw, skb);
1138} 1140}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index aef4f71f1981..7726e67044c0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -1484,6 +1484,156 @@ bool iwl_good_ack_health(struct iwl_priv *priv,
1484} 1484}
1485 1485
1486 1486
1487/*****************************************************************************
1488 *
1489 * sysfs attributes
1490 *
1491 *****************************************************************************/
1492
1493#ifdef CONFIG_IWLWIFI_DEBUG
1494
1495/*
1496 * The following adds a new attribute to the sysfs representation
1497 * of this device driver (i.e. a new file in /sys/class/net/wlan0/device/)
1498 * used for controlling the debug level.
1499 *
1500 * See the level definitions in iwl for details.
1501 *
1502 * The debug_level being managed using sysfs below is a per device debug
1503 * level that is used instead of the global debug level if it (the per
1504 * device debug level) is set.
1505 */
1506static ssize_t show_debug_level(struct device *d,
1507 struct device_attribute *attr, char *buf)
1508{
1509 struct iwl_priv *priv = dev_get_drvdata(d);
1510 return sprintf(buf, "0x%08X\n", iwl_get_debug_level(priv));
1511}
1512static ssize_t store_debug_level(struct device *d,
1513 struct device_attribute *attr,
1514 const char *buf, size_t count)
1515{
1516 struct iwl_priv *priv = dev_get_drvdata(d);
1517 unsigned long val;
1518 int ret;
1519
1520 ret = strict_strtoul(buf, 0, &val);
1521 if (ret)
1522 IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf);
1523 else {
1524 priv->debug_level = val;
1525 if (iwl_alloc_traffic_mem(priv))
1526 IWL_ERR(priv,
1527 "Not enough memory to generate traffic log\n");
1528 }
1529 return strnlen(buf, count);
1530}
1531
1532static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO,
1533 show_debug_level, store_debug_level);
1534
1535
1536#endif /* CONFIG_IWLWIFI_DEBUG */
1537
1538
1539static ssize_t show_temperature(struct device *d,
1540 struct device_attribute *attr, char *buf)
1541{
1542 struct iwl_priv *priv = dev_get_drvdata(d);
1543
1544 if (!iwl_is_alive(priv))
1545 return -EAGAIN;
1546
1547 return sprintf(buf, "%d\n", priv->temperature);
1548}
1549
1550static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL);
1551
1552static ssize_t show_tx_power(struct device *d,
1553 struct device_attribute *attr, char *buf)
1554{
1555 struct iwl_priv *priv = dev_get_drvdata(d);
1556
1557 if (!iwl_is_ready_rf(priv))
1558 return sprintf(buf, "off\n");
1559 else
1560 return sprintf(buf, "%d\n", priv->tx_power_user_lmt);
1561}
1562
1563static ssize_t store_tx_power(struct device *d,
1564 struct device_attribute *attr,
1565 const char *buf, size_t count)
1566{
1567 struct iwl_priv *priv = dev_get_drvdata(d);
1568 unsigned long val;
1569 int ret;
1570
1571 ret = strict_strtoul(buf, 10, &val);
1572 if (ret)
1573 IWL_INFO(priv, "%s is not in decimal form.\n", buf);
1574 else {
1575 ret = iwl_set_tx_power(priv, val, false);
1576 if (ret)
1577 IWL_ERR(priv, "failed setting tx power (0x%d).\n",
1578 ret);
1579 else
1580 ret = count;
1581 }
1582 return ret;
1583}
1584
1585static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);
1586
1587static ssize_t show_rts_ht_protection(struct device *d,
1588 struct device_attribute *attr, char *buf)
1589{
1590 struct iwl_priv *priv = dev_get_drvdata(d);
1591
1592 return sprintf(buf, "%s\n",
1593 priv->cfg->use_rts_for_ht ? "RTS/CTS" : "CTS-to-self");
1594}
1595
1596static ssize_t store_rts_ht_protection(struct device *d,
1597 struct device_attribute *attr,
1598 const char *buf, size_t count)
1599{
1600 struct iwl_priv *priv = dev_get_drvdata(d);
1601 unsigned long val;
1602 int ret;
1603
1604 ret = strict_strtoul(buf, 10, &val);
1605 if (ret)
1606 IWL_INFO(priv, "Input is not in decimal form.\n");
1607 else {
1608 if (!iwl_is_associated(priv))
1609 priv->cfg->use_rts_for_ht = val ? true : false;
1610 else
1611 IWL_ERR(priv, "Sta associated with AP - "
1612 "Change protection mechanism is not allowed\n");
1613 ret = count;
1614 }
1615 return ret;
1616}
1617
1618static DEVICE_ATTR(rts_ht_protection, S_IWUSR | S_IRUGO,
1619 show_rts_ht_protection, store_rts_ht_protection);
1620
1621
1622static struct attribute *iwl_sysfs_entries[] = {
1623 &dev_attr_temperature.attr,
1624 &dev_attr_tx_power.attr,
1625 &dev_attr_rts_ht_protection.attr,
1626#ifdef CONFIG_IWLWIFI_DEBUG
1627 &dev_attr_debug_level.attr,
1628#endif
1629 NULL
1630};
1631
1632static struct attribute_group iwl_attribute_group = {
1633 .name = NULL, /* put in device directory */
1634 .attrs = iwl_sysfs_entries,
1635};
1636
1487/****************************************************************************** 1637/******************************************************************************
1488 * 1638 *
1489 * uCode download functions 1639 * uCode download functions
@@ -1965,6 +2115,13 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
1965 if (err) 2115 if (err)
1966 IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); 2116 IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
1967 2117
2118 err = sysfs_create_group(&priv->pci_dev->dev.kobj,
2119 &iwl_attribute_group);
2120 if (err) {
2121 IWL_ERR(priv, "failed to create sysfs device attributes\n");
2122 goto out_unbind;
2123 }
2124
1968 /* We have our copies now, allow OS release its copies */ 2125 /* We have our copies now, allow OS release its copies */
1969 release_firmware(ucode_raw); 2126 release_firmware(ucode_raw);
1970 complete(&priv->_agn.firmware_loading_complete); 2127 complete(&priv->_agn.firmware_loading_complete);
@@ -3264,141 +3421,6 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
3264 3421
3265/***************************************************************************** 3422/*****************************************************************************
3266 * 3423 *
3267 * sysfs attributes
3268 *
3269 *****************************************************************************/
3270
3271#ifdef CONFIG_IWLWIFI_DEBUG
3272
3273/*
3274 * The following adds a new attribute to the sysfs representation
3275 * of this device driver (i.e. a new file in /sys/class/net/wlan0/device/)
3276 * used for controlling the debug level.
3277 *
3278 * See the level definitions in iwl for details.
3279 *
3280 * The debug_level being managed using sysfs below is a per device debug
3281 * level that is used instead of the global debug level if it (the per
3282 * device debug level) is set.
3283 */
3284static ssize_t show_debug_level(struct device *d,
3285 struct device_attribute *attr, char *buf)
3286{
3287 struct iwl_priv *priv = dev_get_drvdata(d);
3288 return sprintf(buf, "0x%08X\n", iwl_get_debug_level(priv));
3289}
3290static ssize_t store_debug_level(struct device *d,
3291 struct device_attribute *attr,
3292 const char *buf, size_t count)
3293{
3294 struct iwl_priv *priv = dev_get_drvdata(d);
3295 unsigned long val;
3296 int ret;
3297
3298 ret = strict_strtoul(buf, 0, &val);
3299 if (ret)
3300 IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf);
3301 else {
3302 priv->debug_level = val;
3303 if (iwl_alloc_traffic_mem(priv))
3304 IWL_ERR(priv,
3305 "Not enough memory to generate traffic log\n");
3306 }
3307 return strnlen(buf, count);
3308}
3309
3310static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO,
3311 show_debug_level, store_debug_level);
3312
3313
3314#endif /* CONFIG_IWLWIFI_DEBUG */
3315
3316
3317static ssize_t show_temperature(struct device *d,
3318 struct device_attribute *attr, char *buf)
3319{
3320 struct iwl_priv *priv = dev_get_drvdata(d);
3321
3322 if (!iwl_is_alive(priv))
3323 return -EAGAIN;
3324
3325 return sprintf(buf, "%d\n", priv->temperature);
3326}
3327
3328static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL);
3329
3330static ssize_t show_tx_power(struct device *d,
3331 struct device_attribute *attr, char *buf)
3332{
3333 struct iwl_priv *priv = dev_get_drvdata(d);
3334
3335 if (!iwl_is_ready_rf(priv))
3336 return sprintf(buf, "off\n");
3337 else
3338 return sprintf(buf, "%d\n", priv->tx_power_user_lmt);
3339}
3340
3341static ssize_t store_tx_power(struct device *d,
3342 struct device_attribute *attr,
3343 const char *buf, size_t count)
3344{
3345 struct iwl_priv *priv = dev_get_drvdata(d);
3346 unsigned long val;
3347 int ret;
3348
3349 ret = strict_strtoul(buf, 10, &val);
3350 if (ret)
3351 IWL_INFO(priv, "%s is not in decimal form.\n", buf);
3352 else {
3353 ret = iwl_set_tx_power(priv, val, false);
3354 if (ret)
3355 IWL_ERR(priv, "failed setting tx power (0x%d).\n",
3356 ret);
3357 else
3358 ret = count;
3359 }
3360 return ret;
3361}
3362
3363static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);
3364
3365static ssize_t show_rts_ht_protection(struct device *d,
3366 struct device_attribute *attr, char *buf)
3367{
3368 struct iwl_priv *priv = dev_get_drvdata(d);
3369
3370 return sprintf(buf, "%s\n",
3371 priv->cfg->use_rts_for_ht ? "RTS/CTS" : "CTS-to-self");
3372}
3373
3374static ssize_t store_rts_ht_protection(struct device *d,
3375 struct device_attribute *attr,
3376 const char *buf, size_t count)
3377{
3378 struct iwl_priv *priv = dev_get_drvdata(d);
3379 unsigned long val;
3380 int ret;
3381
3382 ret = strict_strtoul(buf, 10, &val);
3383 if (ret)
3384 IWL_INFO(priv, "Input is not in decimal form.\n");
3385 else {
3386 if (!iwl_is_associated(priv))
3387 priv->cfg->use_rts_for_ht = val ? true : false;
3388 else
3389 IWL_ERR(priv, "Sta associated with AP - "
3390 "Change protection mechanism is not allowed\n");
3391 ret = count;
3392 }
3393 return ret;
3394}
3395
3396static DEVICE_ATTR(rts_ht_protection, S_IWUSR | S_IRUGO,
3397 show_rts_ht_protection, store_rts_ht_protection);
3398
3399
3400/*****************************************************************************
3401 *
3402 * driver setup and teardown 3424 * driver setup and teardown
3403 * 3425 *
3404 *****************************************************************************/ 3426 *****************************************************************************/
@@ -3550,21 +3572,6 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
3550 kfree(priv->scan_cmd); 3572 kfree(priv->scan_cmd);
3551} 3573}
3552 3574
3553static struct attribute *iwl_sysfs_entries[] = {
3554 &dev_attr_temperature.attr,
3555 &dev_attr_tx_power.attr,
3556 &dev_attr_rts_ht_protection.attr,
3557#ifdef CONFIG_IWLWIFI_DEBUG
3558 &dev_attr_debug_level.attr,
3559#endif
3560 NULL
3561};
3562
3563static struct attribute_group iwl_attribute_group = {
3564 .name = NULL, /* put in device directory */
3565 .attrs = iwl_sysfs_entries,
3566};
3567
3568static struct ieee80211_ops iwl_hw_ops = { 3575static struct ieee80211_ops iwl_hw_ops = {
3569 .tx = iwl_mac_tx, 3576 .tx = iwl_mac_tx,
3570 .start = iwl_mac_start, 3577 .start = iwl_mac_start,
@@ -3750,11 +3757,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
3750 IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq); 3757 IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
3751 goto out_disable_msi; 3758 goto out_disable_msi;
3752 } 3759 }
3753 err = sysfs_create_group(&pdev->dev.kobj, &iwl_attribute_group);
3754 if (err) {
3755 IWL_ERR(priv, "failed to create sysfs device attributes\n");
3756 goto out_free_irq;
3757 }
3758 3760
3759 iwl_setup_deferred_work(priv); 3761 iwl_setup_deferred_work(priv);
3760 iwl_setup_rx_handlers(priv); 3762 iwl_setup_rx_handlers(priv);
@@ -3788,15 +3790,13 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
3788 3790
3789 err = iwl_request_firmware(priv, true); 3791 err = iwl_request_firmware(priv, true);
3790 if (err) 3792 if (err)
3791 goto out_remove_sysfs; 3793 goto out_destroy_workqueue;
3792 3794
3793 return 0; 3795 return 0;
3794 3796
3795 out_remove_sysfs: 3797 out_destroy_workqueue:
3796 destroy_workqueue(priv->workqueue); 3798 destroy_workqueue(priv->workqueue);
3797 priv->workqueue = NULL; 3799 priv->workqueue = NULL;
3798 sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
3799 out_free_irq:
3800 free_irq(priv->pci_dev->irq, priv); 3800 free_irq(priv->pci_dev->irq, priv);
3801 iwl_free_isr_ict(priv); 3801 iwl_free_isr_ict(priv);
3802 out_disable_msi: 3802 out_disable_msi:
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 5a7eca8fb789..426e95567de3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -854,6 +854,45 @@ void iwl_set_rxon_chain(struct iwl_priv *priv)
854} 854}
855EXPORT_SYMBOL(iwl_set_rxon_chain); 855EXPORT_SYMBOL(iwl_set_rxon_chain);
856 856
857/* Return valid channel */
858u8 iwl_get_single_channel_number(struct iwl_priv *priv,
859 enum ieee80211_band band)
860{
861 const struct iwl_channel_info *ch_info;
862 int i;
863 u8 channel = 0;
864
865 /* only scan single channel, good enough to reset the RF */
866 /* pick the first valid not in-use channel */
867 if (band == IEEE80211_BAND_5GHZ) {
868 for (i = 14; i < priv->channel_count; i++) {
869 if (priv->channel_info[i].channel !=
870 le16_to_cpu(priv->staging_rxon.channel)) {
871 channel = priv->channel_info[i].channel;
872 ch_info = iwl_get_channel_info(priv,
873 band, channel);
874 if (is_channel_valid(ch_info))
875 break;
876 }
877 }
878 } else {
879 for (i = 0; i < 14; i++) {
880 if (priv->channel_info[i].channel !=
881 le16_to_cpu(priv->staging_rxon.channel)) {
882 channel =
883 priv->channel_info[i].channel;
884 ch_info = iwl_get_channel_info(priv,
885 band, channel);
886 if (is_channel_valid(ch_info))
887 break;
888 }
889 }
890 }
891
892 return channel;
893}
894EXPORT_SYMBOL(iwl_get_single_channel_number);
895
857/** 896/**
858 * iwl_set_rxon_channel - Set the phymode and channel values in staging RXON 897 * iwl_set_rxon_channel - Set the phymode and channel values in staging RXON
859 * @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz 898 * @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 7e5a5ba41fd2..31775bd9c361 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -343,6 +343,8 @@ int iwl_check_rxon_cmd(struct iwl_priv *priv);
343int iwl_full_rxon_required(struct iwl_priv *priv); 343int iwl_full_rxon_required(struct iwl_priv *priv);
344void iwl_set_rxon_chain(struct iwl_priv *priv); 344void iwl_set_rxon_chain(struct iwl_priv *priv);
345int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch); 345int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch);
346u8 iwl_get_single_channel_number(struct iwl_priv *priv,
347 enum ieee80211_band band);
346void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf); 348void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf);
347u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv, 349u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
348 struct ieee80211_sta_ht_cap *sta_ht_inf); 350 struct ieee80211_sta_ht_cap *sta_ht_inf);
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 3e5bffb6034f..6c353cacc8d6 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -1844,6 +1844,49 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
1844#endif 1844#endif
1845} 1845}
1846 1846
1847static int iwl3945_get_single_channel_for_scan(struct iwl_priv *priv,
1848 struct ieee80211_vif *vif,
1849 enum ieee80211_band band,
1850 struct iwl3945_scan_channel *scan_ch)
1851{
1852 const struct ieee80211_supported_band *sband;
1853 u16 passive_dwell = 0;
1854 u16 active_dwell = 0;
1855 int added = 0;
1856 u8 channel = 0;
1857
1858 sband = iwl_get_hw_mode(priv, band);
1859 if (!sband) {
1860 IWL_ERR(priv, "invalid band\n");
1861 return added;
1862 }
1863
1864 active_dwell = iwl_get_active_dwell_time(priv, band, 0);
1865 passive_dwell = iwl_get_passive_dwell_time(priv, band, vif);
1866
1867 if (passive_dwell <= active_dwell)
1868 passive_dwell = active_dwell + 1;
1869
1870
1871 channel = iwl_get_single_channel_number(priv, band);
1872
1873 if (channel) {
1874 scan_ch->channel = channel;
1875 scan_ch->type = 0; /* passive */
1876 scan_ch->active_dwell = cpu_to_le16(active_dwell);
1877 scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
1878 /* Set txpower levels to defaults */
1879 scan_ch->tpc.dsp_atten = 110;
1880 if (band == IEEE80211_BAND_5GHZ)
1881 scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
1882 else
1883 scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
1884 added++;
1885 } else
1886 IWL_ERR(priv, "no valid channel found\n");
1887 return added;
1888}
1889
1847static int iwl3945_get_channels_for_scan(struct iwl_priv *priv, 1890static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
1848 enum ieee80211_band band, 1891 enum ieee80211_band band,
1849 u8 is_active, u8 n_probes, 1892 u8 is_active, u8 n_probes,
@@ -2992,9 +3035,16 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
2992 /* select Rx antennas */ 3035 /* select Rx antennas */
2993 scan->flags |= iwl3945_get_antenna_flags(priv); 3036 scan->flags |= iwl3945_get_antenna_flags(priv);
2994 3037
2995 scan->channel_count = 3038 if (priv->is_internal_short_scan) {
2996 iwl3945_get_channels_for_scan(priv, band, is_active, n_probes, 3039 scan->channel_count =
2997 (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)], vif); 3040 iwl3945_get_single_channel_for_scan(priv, vif, band,
3041 (void *)&scan->data[le16_to_cpu(
3042 scan->tx_cmd.len)]);
3043 } else {
3044 scan->channel_count =
3045 iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
3046 (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)], vif);
3047 }
2998 3048
2999 if (scan->channel_count == 0) { 3049 if (scan->channel_count == 0) {
3000 IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count); 3050 IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c
index a115bfa9513a..7a377f5b7662 100644
--- a/drivers/net/wireless/libertas/rx.c
+++ b/drivers/net/wireless/libertas/rx.c
@@ -329,9 +329,8 @@ static int process_rxed_802_11_packet(struct lbs_private *priv,
329 /* create the exported radio header */ 329 /* create the exported radio header */
330 330
331 /* radiotap header */ 331 /* radiotap header */
332 radiotap_hdr.hdr.it_version = 0; 332 memset(&radiotap_hdr, 0, sizeof(radiotap_hdr));
333 /* XXX must check this value for pad */ 333 /* XXX must check radiotap_hdr.hdr.it_pad for pad */
334 radiotap_hdr.hdr.it_pad = 0;
335 radiotap_hdr.hdr.it_len = cpu_to_le16 (sizeof(struct rx_radiotap_hdr)); 334 radiotap_hdr.hdr.it_len = cpu_to_le16 (sizeof(struct rx_radiotap_hdr));
336 radiotap_hdr.hdr.it_present = cpu_to_le32 (RX_RADIOTAP_PRESENT); 335 radiotap_hdr.hdr.it_present = cpu_to_le32 (RX_RADIOTAP_PRESENT);
337 radiotap_hdr.rate = convert_mv_rate_to_radiotap(prxpd->rx_rate); 336 radiotap_hdr.rate = convert_mv_rate_to_radiotap(prxpd->rx_rate);
diff --git a/drivers/net/wireless/orinoco/airport.c b/drivers/net/wireless/orinoco/airport.c
index 9bcee10c9308..4a0a0e5265c9 100644
--- a/drivers/net/wireless/orinoco/airport.c
+++ b/drivers/net/wireless/orinoco/airport.c
@@ -239,8 +239,11 @@ static struct of_device_id airport_match[] =
239MODULE_DEVICE_TABLE(of, airport_match); 239MODULE_DEVICE_TABLE(of, airport_match);
240 240
241static struct macio_driver airport_driver = { 241static struct macio_driver airport_driver = {
242 .name = DRIVER_NAME, 242 .driver = {
243 .match_table = airport_match, 243 .name = DRIVER_NAME,
244 .owner = THIS_MODULE,
245 .of_match_table = airport_match,
246 },
244 .probe = airport_attach, 247 .probe = airport_attach,
245 .remove = airport_detach, 248 .remove = airport_detach,
246 .suspend = airport_suspend, 249 .suspend = airport_suspend,
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c
index d5b197b4d5bb..73073259f508 100644
--- a/drivers/net/wireless/p54/p54usb.c
+++ b/drivers/net/wireless/p54/p54usb.c
@@ -80,6 +80,7 @@ static struct usb_device_id p54u_table[] __devinitdata = {
80 {USB_DEVICE(0x1413, 0x5400)}, /* Telsey 802.11g USB2.0 Adapter */ 80 {USB_DEVICE(0x1413, 0x5400)}, /* Telsey 802.11g USB2.0 Adapter */
81 {USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */ 81 {USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */
82 {USB_DEVICE(0x2001, 0x3704)}, /* DLink DWL-G122 rev A2 */ 82 {USB_DEVICE(0x2001, 0x3704)}, /* DLink DWL-G122 rev A2 */
83 {USB_DEVICE(0x413c, 0x5513)}, /* Dell WLA3310 USB Wireless Adapter */
83 {USB_DEVICE(0x413c, 0x8102)}, /* Spinnaker DUT */ 84 {USB_DEVICE(0x413c, 0x8102)}, /* Spinnaker DUT */
84 {USB_DEVICE(0x413c, 0x8104)}, /* Cohiba Proto board */ 85 {USB_DEVICE(0x413c, 0x8104)}, /* Cohiba Proto board */
85 {} 86 {}
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 699161327d65..0f8b84b7224c 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -413,7 +413,7 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
413 */ 413 */
414 rt2x00_desc_read(txi, 0, &word); 414 rt2x00_desc_read(txi, 0, &word);
415 rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_PKT_LEN, 415 rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_PKT_LEN,
416 skb->len - TXINFO_DESC_SIZE); 416 skb->len + TXWI_DESC_SIZE);
417 rt2x00_set_field32(&word, TXINFO_W0_WIV, 417 rt2x00_set_field32(&word, TXINFO_W0_WIV,
418 !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags)); 418 !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags));
419 rt2x00_set_field32(&word, TXINFO_W0_QSEL, 2); 419 rt2x00_set_field32(&word, TXINFO_W0_QSEL, 2);
diff --git a/drivers/net/wireless/wl12xx/wl1251_sdio.c b/drivers/net/wireless/wl12xx/wl1251_sdio.c
index d234285c2c81..c561332e7009 100644
--- a/drivers/net/wireless/wl12xx/wl1251_sdio.c
+++ b/drivers/net/wireless/wl12xx/wl1251_sdio.c
@@ -259,6 +259,7 @@ disable:
259 sdio_disable_func(func); 259 sdio_disable_func(func);
260release: 260release:
261 sdio_release_host(func); 261 sdio_release_host(func);
262 wl1251_free_hw(wl);
262 return ret; 263 return ret;
263} 264}
264 265
diff --git a/drivers/parport/parport_amiga.c b/drivers/parport/parport_amiga.c
index 1586e1caa2f5..8bef6d60f88b 100644
--- a/drivers/parport/parport_amiga.c
+++ b/drivers/parport/parport_amiga.c
@@ -18,6 +18,8 @@
18#include <linux/parport.h> 18#include <linux/parport.h>
19#include <linux/ioport.h> 19#include <linux/ioport.h>
20#include <linux/interrupt.h> 20#include <linux/interrupt.h>
21#include <linux/platform_device.h>
22
21#include <asm/setup.h> 23#include <asm/setup.h>
22#include <asm/amigahw.h> 24#include <asm/amigahw.h>
23#include <asm/irq.h> 25#include <asm/irq.h>
@@ -31,7 +33,6 @@
31#define DPRINTK(x...) do { } while (0) 33#define DPRINTK(x...) do { } while (0)
32#endif 34#endif
33 35
34static struct parport *this_port = NULL;
35 36
36static void amiga_write_data(struct parport *p, unsigned char data) 37static void amiga_write_data(struct parport *p, unsigned char data)
37{ 38{
@@ -227,18 +228,11 @@ static struct parport_operations pp_amiga_ops = {
227 228
228/* ----------- Initialisation code --------------------------------- */ 229/* ----------- Initialisation code --------------------------------- */
229 230
230static int __init parport_amiga_init(void) 231static int __init amiga_parallel_probe(struct platform_device *pdev)
231{ 232{
232 struct parport *p; 233 struct parport *p;
233 int err; 234 int err;
234 235
235 if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_PARALLEL))
236 return -ENODEV;
237
238 err = -EBUSY;
239 if (!request_mem_region(CIAA_PHYSADDR-1+0x100, 0x100, "parallel"))
240 goto out_mem;
241
242 ciaa.ddrb = 0xff; 236 ciaa.ddrb = 0xff;
243 ciab.ddra &= 0xf8; 237 ciab.ddra &= 0xf8;
244 mb(); 238 mb();
@@ -246,41 +240,63 @@ static int __init parport_amiga_init(void)
246 p = parport_register_port((unsigned long)&ciaa.prb, IRQ_AMIGA_CIAA_FLG, 240 p = parport_register_port((unsigned long)&ciaa.prb, IRQ_AMIGA_CIAA_FLG,
247 PARPORT_DMA_NONE, &pp_amiga_ops); 241 PARPORT_DMA_NONE, &pp_amiga_ops);
248 if (!p) 242 if (!p)
249 goto out_port; 243 return -EBUSY;
250 244
251 err = request_irq(IRQ_AMIGA_CIAA_FLG, parport_irq_handler, 0, p->name, p); 245 err = request_irq(IRQ_AMIGA_CIAA_FLG, parport_irq_handler, 0, p->name,
246 p);
252 if (err) 247 if (err)
253 goto out_irq; 248 goto out_irq;
254 249
255 this_port = p;
256 printk(KERN_INFO "%s: Amiga built-in port using irq\n", p->name); 250 printk(KERN_INFO "%s: Amiga built-in port using irq\n", p->name);
257 /* XXX: set operating mode */ 251 /* XXX: set operating mode */
258 parport_announce_port(p); 252 parport_announce_port(p);
259 253
254 platform_set_drvdata(pdev, p);
255
260 return 0; 256 return 0;
261 257
262out_irq: 258out_irq:
263 parport_put_port(p); 259 parport_put_port(p);
264out_port:
265 release_mem_region(CIAA_PHYSADDR-1+0x100, 0x100);
266out_mem:
267 return err; 260 return err;
268} 261}
269 262
270static void __exit parport_amiga_exit(void) 263static int __exit amiga_parallel_remove(struct platform_device *pdev)
264{
265 struct parport *port = platform_get_drvdata(pdev);
266
267 parport_remove_port(port);
268 if (port->irq != PARPORT_IRQ_NONE)
269 free_irq(IRQ_AMIGA_CIAA_FLG, port);
270 parport_put_port(port);
271 platform_set_drvdata(pdev, NULL);
272 return 0;
273}
274
275static struct platform_driver amiga_parallel_driver = {
276 .remove = __exit_p(amiga_parallel_remove),
277 .driver = {
278 .name = "amiga-parallel",
279 .owner = THIS_MODULE,
280 },
281};
282
283static int __init amiga_parallel_init(void)
284{
285 return platform_driver_probe(&amiga_parallel_driver,
286 amiga_parallel_probe);
287}
288
289module_init(amiga_parallel_init);
290
291static void __exit amiga_parallel_exit(void)
271{ 292{
272 parport_remove_port(this_port); 293 platform_driver_unregister(&amiga_parallel_driver);
273 if (this_port->irq != PARPORT_IRQ_NONE)
274 free_irq(IRQ_AMIGA_CIAA_FLG, this_port);
275 parport_put_port(this_port);
276 release_mem_region(CIAA_PHYSADDR-1+0x100, 0x100);
277} 294}
278 295
296module_exit(amiga_parallel_exit);
279 297
280MODULE_AUTHOR("Joerg Dorchain <joerg@dorchain.net>"); 298MODULE_AUTHOR("Joerg Dorchain <joerg@dorchain.net>");
281MODULE_DESCRIPTION("Parport Driver for Amiga builtin Port"); 299MODULE_DESCRIPTION("Parport Driver for Amiga builtin Port");
282MODULE_SUPPORTED_DEVICE("Amiga builtin Parallel Port"); 300MODULE_SUPPORTED_DEVICE("Amiga builtin Parallel Port");
283MODULE_LICENSE("GPL"); 301MODULE_LICENSE("GPL");
284 302MODULE_ALIAS("platform:amiga-parallel");
285module_init(parport_amiga_init)
286module_exit(parport_amiga_exit)
diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c
index b3e5580c837b..4952c3b9379d 100644
--- a/drivers/pci/hotplug/cpqphp_core.c
+++ b/drivers/pci/hotplug/cpqphp_core.c
@@ -828,7 +828,14 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
828 pci_name(pdev), err); 828 pci_name(pdev), err);
829 return err; 829 return err;
830 } 830 }
831
831 bus = pdev->subordinate; 832 bus = pdev->subordinate;
833 if (!bus) {
834 dev_notice(&pdev->dev, "the device is not a bridge, "
835 "skipping\n");
836 rc = -ENODEV;
837 goto err_disable_device;
838 }
832 839
833 /* Need to read VID early b/c it's used to differentiate CPQ and INTC 840 /* Need to read VID early b/c it's used to differentiate CPQ and INTC
834 * discovery 841 * discovery
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index afd2fbf7d797..c9957f68ac9b 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -1035,39 +1035,6 @@ error:
1035 return retval; 1035 return retval;
1036} 1036}
1037 1037
1038static void pci_remove_slot_links(struct pci_dev *dev)
1039{
1040 char func[10];
1041 struct pci_slot *slot;
1042
1043 sysfs_remove_link(&dev->dev.kobj, "slot");
1044 list_for_each_entry(slot, &dev->bus->slots, list) {
1045 if (slot->number != PCI_SLOT(dev->devfn))
1046 continue;
1047 snprintf(func, 10, "function%d", PCI_FUNC(dev->devfn));
1048 sysfs_remove_link(&slot->kobj, func);
1049 }
1050}
1051
1052static int pci_create_slot_links(struct pci_dev *dev)
1053{
1054 int result = 0;
1055 char func[10];
1056 struct pci_slot *slot;
1057
1058 list_for_each_entry(slot, &dev->bus->slots, list) {
1059 if (slot->number != PCI_SLOT(dev->devfn))
1060 continue;
1061 result = sysfs_create_link(&dev->dev.kobj, &slot->kobj, "slot");
1062 if (result)
1063 goto out;
1064 snprintf(func, 10, "function%d", PCI_FUNC(dev->devfn));
1065 result = sysfs_create_link(&slot->kobj, &dev->dev.kobj, func);
1066 }
1067out:
1068 return result;
1069}
1070
1071int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) 1038int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
1072{ 1039{
1073 int retval; 1040 int retval;
@@ -1130,8 +1097,6 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
1130 if (retval) 1097 if (retval)
1131 goto err_vga_file; 1098 goto err_vga_file;
1132 1099
1133 pci_create_slot_links(pdev);
1134
1135 return 0; 1100 return 0;
1136 1101
1137err_vga_file: 1102err_vga_file:
@@ -1181,8 +1146,6 @@ void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
1181 if (!sysfs_initialized) 1146 if (!sysfs_initialized)
1182 return; 1147 return;
1183 1148
1184 pci_remove_slot_links(pdev);
1185
1186 pci_remove_capabilities_sysfs(pdev); 1149 pci_remove_capabilities_sysfs(pdev);
1187 1150
1188 if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE) 1151 if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE)
diff --git a/drivers/pci/pcie/aer/aerdrv.h b/drivers/pci/pcie/aer/aerdrv.h
index 7aaae2d2bd67..80c11d131499 100644
--- a/drivers/pci/pcie/aer/aerdrv.h
+++ b/drivers/pci/pcie/aer/aerdrv.h
@@ -130,4 +130,21 @@ static inline int aer_osc_setup(struct pcie_device *pciedev)
130} 130}
131#endif 131#endif
132 132
133#ifdef CONFIG_ACPI_APEI
134extern int pcie_aer_get_firmware_first(struct pci_dev *pci_dev);
135#else
136static inline int pcie_aer_get_firmware_first(struct pci_dev *pci_dev)
137{
138 if (pci_dev->__aer_firmware_first_valid)
139 return pci_dev->__aer_firmware_first;
140 return 0;
141}
142#endif
143
144static inline void pcie_aer_force_firmware_first(struct pci_dev *pci_dev,
145 int enable)
146{
147 pci_dev->__aer_firmware_first = !!enable;
148 pci_dev->__aer_firmware_first_valid = 1;
149}
133#endif /* _AERDRV_H_ */ 150#endif /* _AERDRV_H_ */
diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c
index 04814087658d..f278d7b0d95d 100644
--- a/drivers/pci/pcie/aer/aerdrv_acpi.c
+++ b/drivers/pci/pcie/aer/aerdrv_acpi.c
@@ -16,6 +16,7 @@
16#include <linux/acpi.h> 16#include <linux/acpi.h>
17#include <linux/pci-acpi.h> 17#include <linux/pci-acpi.h>
18#include <linux/delay.h> 18#include <linux/delay.h>
19#include <acpi/apei.h>
19#include "aerdrv.h" 20#include "aerdrv.h"
20 21
21/** 22/**
@@ -53,3 +54,79 @@ int aer_osc_setup(struct pcie_device *pciedev)
53 54
54 return 0; 55 return 0;
55} 56}
57
58#ifdef CONFIG_ACPI_APEI
59static inline int hest_match_pci(struct acpi_hest_aer_common *p,
60 struct pci_dev *pci)
61{
62 return (0 == pci_domain_nr(pci->bus) &&
63 p->bus == pci->bus->number &&
64 p->device == PCI_SLOT(pci->devfn) &&
65 p->function == PCI_FUNC(pci->devfn));
66}
67
68struct aer_hest_parse_info {
69 struct pci_dev *pci_dev;
70 int firmware_first;
71};
72
73static int aer_hest_parse(struct acpi_hest_header *hest_hdr, void *data)
74{
75 struct aer_hest_parse_info *info = data;
76 struct acpi_hest_aer_common *p;
77 u8 pcie_type = 0;
78 u8 bridge = 0;
79 int ff = 0;
80
81 switch (hest_hdr->type) {
82 case ACPI_HEST_TYPE_AER_ROOT_PORT:
83 pcie_type = PCI_EXP_TYPE_ROOT_PORT;
84 break;
85 case ACPI_HEST_TYPE_AER_ENDPOINT:
86 pcie_type = PCI_EXP_TYPE_ENDPOINT;
87 break;
88 case ACPI_HEST_TYPE_AER_BRIDGE:
89 if ((info->pci_dev->class >> 16) == PCI_BASE_CLASS_BRIDGE)
90 bridge = 1;
91 break;
92 default:
93 return 0;
94 }
95
96 p = (struct acpi_hest_aer_common *)(hest_hdr + 1);
97 if (p->flags & ACPI_HEST_GLOBAL) {
98 if ((info->pci_dev->is_pcie &&
99 info->pci_dev->pcie_type == pcie_type) || bridge)
100 ff = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST);
101 } else
102 if (hest_match_pci(p, info->pci_dev))
103 ff = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST);
104 info->firmware_first = ff;
105
106 return 0;
107}
108
109static void aer_set_firmware_first(struct pci_dev *pci_dev)
110{
111 int rc;
112 struct aer_hest_parse_info info = {
113 .pci_dev = pci_dev,
114 .firmware_first = 0,
115 };
116
117 rc = apei_hest_parse(aer_hest_parse, &info);
118
119 if (rc)
120 pci_dev->__aer_firmware_first = 0;
121 else
122 pci_dev->__aer_firmware_first = info.firmware_first;
123 pci_dev->__aer_firmware_first_valid = 1;
124}
125
126int pcie_aer_get_firmware_first(struct pci_dev *dev)
127{
128 if (!dev->__aer_firmware_first_valid)
129 aer_set_firmware_first(dev);
130 return dev->__aer_firmware_first;
131}
132#endif
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
index df2d686fe3dd..8af4f619bba2 100644
--- a/drivers/pci/pcie/aer/aerdrv_core.c
+++ b/drivers/pci/pcie/aer/aerdrv_core.c
@@ -36,7 +36,7 @@ int pci_enable_pcie_error_reporting(struct pci_dev *dev)
36 u16 reg16 = 0; 36 u16 reg16 = 0;
37 int pos; 37 int pos;
38 38
39 if (dev->aer_firmware_first) 39 if (pcie_aer_get_firmware_first(dev))
40 return -EIO; 40 return -EIO;
41 41
42 pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); 42 pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
@@ -63,7 +63,7 @@ int pci_disable_pcie_error_reporting(struct pci_dev *dev)
63 u16 reg16 = 0; 63 u16 reg16 = 0;
64 int pos; 64 int pos;
65 65
66 if (dev->aer_firmware_first) 66 if (pcie_aer_get_firmware_first(dev))
67 return -EIO; 67 return -EIO;
68 68
69 pos = pci_pcie_cap(dev); 69 pos = pci_pcie_cap(dev);
@@ -771,7 +771,7 @@ void aer_isr(struct work_struct *work)
771 */ 771 */
772int aer_init(struct pcie_device *dev) 772int aer_init(struct pcie_device *dev)
773{ 773{
774 if (dev->port->aer_firmware_first) { 774 if (pcie_aer_get_firmware_first(dev->port)) {
775 dev_printk(KERN_DEBUG, &dev->device, 775 dev_printk(KERN_DEBUG, &dev->device,
776 "PCIe errors handled by platform firmware.\n"); 776 "PCIe errors handled by platform firmware.\n");
777 goto out; 777 goto out;
@@ -785,7 +785,7 @@ out:
785 if (forceload) { 785 if (forceload) {
786 dev_printk(KERN_DEBUG, &dev->device, 786 dev_printk(KERN_DEBUG, &dev->device,
787 "aerdrv forceload requested.\n"); 787 "aerdrv forceload requested.\n");
788 dev->port->aer_firmware_first = 0; 788 pcie_aer_force_firmware_first(dev->port, 0);
789 return 0; 789 return 0;
790 } 790 }
791 return -ENXIO; 791 return -ENXIO;
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index c82548afcd5c..f4adba2d1dd3 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -10,7 +10,6 @@
10#include <linux/module.h> 10#include <linux/module.h>
11#include <linux/cpumask.h> 11#include <linux/cpumask.h>
12#include <linux/pci-aspm.h> 12#include <linux/pci-aspm.h>
13#include <acpi/acpi_hest.h>
14#include "pci.h" 13#include "pci.h"
15 14
16#define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */ 15#define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */
@@ -904,12 +903,6 @@ void set_pcie_hotplug_bridge(struct pci_dev *pdev)
904 pdev->is_hotplug_bridge = 1; 903 pdev->is_hotplug_bridge = 1;
905} 904}
906 905
907static void set_pci_aer_firmware_first(struct pci_dev *pdev)
908{
909 if (acpi_hest_firmware_first_pci(pdev))
910 pdev->aer_firmware_first = 1;
911}
912
913#define LEGACY_IO_RESOURCE (IORESOURCE_IO | IORESOURCE_PCI_FIXED) 906#define LEGACY_IO_RESOURCE (IORESOURCE_IO | IORESOURCE_PCI_FIXED)
914 907
915/** 908/**
@@ -939,7 +932,6 @@ int pci_setup_device(struct pci_dev *dev)
939 dev->multifunction = !!(hdr_type & 0x80); 932 dev->multifunction = !!(hdr_type & 0x80);
940 dev->error_state = pci_channel_io_normal; 933 dev->error_state = pci_channel_io_normal;
941 set_pcie_port_type(dev); 934 set_pcie_port_type(dev);
942 set_pci_aer_firmware_first(dev);
943 935
944 list_for_each_entry(slot, &dev->bus->slots, list) 936 list_for_each_entry(slot, &dev->bus->slots, list)
945 if (PCI_SLOT(dev->devfn) == slot->number) 937 if (PCI_SLOT(dev->devfn) == slot->number)
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index b7512cf08c58..477345d41641 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -1457,7 +1457,8 @@ static void quirk_jmicron_ata(struct pci_dev *pdev)
1457 conf5 &= ~(1 << 24); /* Clear bit 24 */ 1457 conf5 &= ~(1 << 24); /* Clear bit 24 */
1458 1458
1459 switch (pdev->device) { 1459 switch (pdev->device) {
1460 case PCI_DEVICE_ID_JMICRON_JMB360: 1460 case PCI_DEVICE_ID_JMICRON_JMB360: /* SATA single port */
1461 case PCI_DEVICE_ID_JMICRON_JMB362: /* SATA dual ports */
1461 /* The controller should be in single function ahci mode */ 1462 /* The controller should be in single function ahci mode */
1462 conf1 |= 0x0002A100; /* Set 8, 13, 15, 17 */ 1463 conf1 |= 0x0002A100; /* Set 8, 13, 15, 17 */
1463 break; 1464 break;
@@ -1493,12 +1494,14 @@ static void quirk_jmicron_ata(struct pci_dev *pdev)
1493} 1494}
1494DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB360, quirk_jmicron_ata); 1495DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB360, quirk_jmicron_ata);
1495DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, quirk_jmicron_ata); 1496DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, quirk_jmicron_ata);
1497DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB362, quirk_jmicron_ata);
1496DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, quirk_jmicron_ata); 1498DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, quirk_jmicron_ata);
1497DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, quirk_jmicron_ata); 1499DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, quirk_jmicron_ata);
1498DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, quirk_jmicron_ata); 1500DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, quirk_jmicron_ata);
1499DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368, quirk_jmicron_ata); 1501DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368, quirk_jmicron_ata);
1500DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB360, quirk_jmicron_ata); 1502DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB360, quirk_jmicron_ata);
1501DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, quirk_jmicron_ata); 1503DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, quirk_jmicron_ata);
1504DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB362, quirk_jmicron_ata);
1502DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, quirk_jmicron_ata); 1505DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, quirk_jmicron_ata);
1503DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, quirk_jmicron_ata); 1506DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, quirk_jmicron_ata);
1504DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, quirk_jmicron_ata); 1507DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, quirk_jmicron_ata);
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 17bed18d24ad..92379e2d37e7 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -97,16 +97,16 @@ int pci_claim_resource(struct pci_dev *dev, int resource)
97 97
98 root = pci_find_parent_resource(dev, res); 98 root = pci_find_parent_resource(dev, res);
99 if (!root) { 99 if (!root) {
100 dev_err(&dev->dev, "no compatible bridge window for %pR\n", 100 dev_info(&dev->dev, "no compatible bridge window for %pR\n",
101 res); 101 res);
102 return -EINVAL; 102 return -EINVAL;
103 } 103 }
104 104
105 conflict = request_resource_conflict(root, res); 105 conflict = request_resource_conflict(root, res);
106 if (conflict) { 106 if (conflict) {
107 dev_err(&dev->dev, 107 dev_info(&dev->dev,
108 "address space collision: %pR conflicts with %s %pR\n", 108 "address space collision: %pR conflicts with %s %pR\n",
109 res, conflict->name, conflict); 109 res, conflict->name, conflict);
110 return -EBUSY; 110 return -EBUSY;
111 } 111 }
112 112
diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c
index e0189cf7c558..659eaa0fc48f 100644
--- a/drivers/pci/slot.c
+++ b/drivers/pci/slot.c
@@ -97,50 +97,6 @@ static ssize_t cur_speed_read_file(struct pci_slot *slot, char *buf)
97 return bus_speed_read(slot->bus->cur_bus_speed, buf); 97 return bus_speed_read(slot->bus->cur_bus_speed, buf);
98} 98}
99 99
100static void remove_sysfs_files(struct pci_slot *slot)
101{
102 char func[10];
103 struct list_head *tmp;
104
105 list_for_each(tmp, &slot->bus->devices) {
106 struct pci_dev *dev = pci_dev_b(tmp);
107 if (PCI_SLOT(dev->devfn) != slot->number)
108 continue;
109 sysfs_remove_link(&dev->dev.kobj, "slot");
110
111 snprintf(func, 10, "function%d", PCI_FUNC(dev->devfn));
112 sysfs_remove_link(&slot->kobj, func);
113 }
114}
115
116static int create_sysfs_files(struct pci_slot *slot)
117{
118 int result;
119 char func[10];
120 struct list_head *tmp;
121
122 list_for_each(tmp, &slot->bus->devices) {
123 struct pci_dev *dev = pci_dev_b(tmp);
124 if (PCI_SLOT(dev->devfn) != slot->number)
125 continue;
126
127 result = sysfs_create_link(&dev->dev.kobj, &slot->kobj, "slot");
128 if (result)
129 goto fail;
130
131 snprintf(func, 10, "function%d", PCI_FUNC(dev->devfn));
132 result = sysfs_create_link(&slot->kobj, &dev->dev.kobj, func);
133 if (result)
134 goto fail;
135 }
136
137 return 0;
138
139fail:
140 remove_sysfs_files(slot);
141 return result;
142}
143
144static void pci_slot_release(struct kobject *kobj) 100static void pci_slot_release(struct kobject *kobj)
145{ 101{
146 struct pci_dev *dev; 102 struct pci_dev *dev;
@@ -153,8 +109,6 @@ static void pci_slot_release(struct kobject *kobj)
153 if (PCI_SLOT(dev->devfn) == slot->number) 109 if (PCI_SLOT(dev->devfn) == slot->number)
154 dev->slot = NULL; 110 dev->slot = NULL;
155 111
156 remove_sysfs_files(slot);
157
158 list_del(&slot->list); 112 list_del(&slot->list);
159 113
160 kfree(slot); 114 kfree(slot);
@@ -346,8 +300,6 @@ placeholder:
346 INIT_LIST_HEAD(&slot->list); 300 INIT_LIST_HEAD(&slot->list);
347 list_add(&slot->list, &parent->slots); 301 list_add(&slot->list, &parent->slots);
348 302
349 create_sysfs_files(slot);
350
351 list_for_each_entry(dev, &parent->devices, bus_list) 303 list_for_each_entry(dev, &parent->devices, bus_list)
352 if (PCI_SLOT(dev->devfn) == slot_nr) 304 if (PCI_SLOT(dev->devfn) == slot_nr)
353 dev->slot = slot; 305 dev->slot = slot;
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 7ef7adee5e4f..9fc339845538 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -671,6 +671,7 @@ static void pcmcia_requery(struct pcmcia_socket *s)
671 if (old_funcs != new_funcs) { 671 if (old_funcs != new_funcs) {
672 /* we need to re-start */ 672 /* we need to re-start */
673 pcmcia_card_remove(s, NULL); 673 pcmcia_card_remove(s, NULL);
674 s->functions = 0;
674 pcmcia_card_add(s); 675 pcmcia_card_add(s);
675 } 676 }
676 } 677 }
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c
index 1a648b90b634..25e5e30a18af 100644
--- a/drivers/pcmcia/m8xx_pcmcia.c
+++ b/drivers/pcmcia/m8xx_pcmcia.c
@@ -1157,7 +1157,7 @@ static int __init m8xx_probe(struct of_device *ofdev,
1157 unsigned int i, m, hwirq; 1157 unsigned int i, m, hwirq;
1158 pcmconf8xx_t *pcmcia; 1158 pcmconf8xx_t *pcmcia;
1159 int status; 1159 int status;
1160 struct device_node *np = ofdev->node; 1160 struct device_node *np = ofdev->dev.of_node;
1161 1161
1162 pcmcia_info("%s\n", version); 1162 pcmcia_info("%s\n", version);
1163 1163
@@ -1301,7 +1301,7 @@ static struct of_platform_driver m8xx_pcmcia_driver = {
1301 .driver = { 1301 .driver = {
1302 .name = driver_name, 1302 .name = driver_name,
1303 .owner = THIS_MODULE, 1303 .owner = THIS_MODULE,
1304 .match_table = m8xx_pcmcia_match, 1304 .of_match_table = m8xx_pcmcia_match,
1305 }, 1305 },
1306 .probe = m8xx_probe, 1306 .probe = m8xx_probe,
1307 .remove = m8xx_remove, 1307 .remove = m8xx_remove,
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index 424e576f3acb..f1d41374eea7 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -880,6 +880,12 @@ static struct cardbus_type cardbus_type[] = {
880 .restore_state = ti_restore_state, 880 .restore_state = ti_restore_state,
881 .sock_init = ti_init, 881 .sock_init = ti_init,
882 }, 882 },
883 [CARDBUS_TYPE_ENE] = {
884 .override = ene_override,
885 .save_state = ti_save_state,
886 .restore_state = ti_restore_state,
887 .sock_init = ti_init,
888 },
883#endif 889#endif
884#ifdef CONFIG_YENTA_RICOH 890#ifdef CONFIG_YENTA_RICOH
885 [CARDBUS_TYPE_RICOH] = { 891 [CARDBUS_TYPE_RICOH] = {
@@ -902,14 +908,6 @@ static struct cardbus_type cardbus_type[] = {
902 .restore_state = o2micro_restore_state, 908 .restore_state = o2micro_restore_state,
903 }, 909 },
904#endif 910#endif
905#ifdef CONFIG_YENTA_TI
906 [CARDBUS_TYPE_ENE] = {
907 .override = ene_override,
908 .save_state = ti_save_state,
909 .restore_state = ti_restore_state,
910 .sock_init = ti_init,
911 },
912#endif
913}; 911};
914 912
915 913
@@ -975,7 +973,7 @@ static irqreturn_t yenta_probe_handler(int irq, void *dev_id)
975/* probes the PCI interrupt, use only on override functions */ 973/* probes the PCI interrupt, use only on override functions */
976static int yenta_probe_cb_irq(struct yenta_socket *socket) 974static int yenta_probe_cb_irq(struct yenta_socket *socket)
977{ 975{
978 u8 reg; 976 u8 reg = 0;
979 977
980 if (!socket->cb_irq) 978 if (!socket->cb_irq)
981 return -1; 979 return -1;
@@ -989,7 +987,8 @@ static int yenta_probe_cb_irq(struct yenta_socket *socket)
989 } 987 }
990 988
991 /* generate interrupt, wait */ 989 /* generate interrupt, wait */
992 reg = exca_readb(socket, I365_CSCINT); 990 if (!socket->dev->irq)
991 reg = exca_readb(socket, I365_CSCINT);
993 exca_writeb(socket, I365_CSCINT, reg | I365_CSC_STSCHG); 992 exca_writeb(socket, I365_CSCINT, reg | I365_CSC_STSCHG);
994 cb_writel(socket, CB_SOCKET_EVENT, -1); 993 cb_writel(socket, CB_SOCKET_EVENT, -1);
995 cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK); 994 cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK);
diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c
index 576c3ed92435..40658e3385b4 100644
--- a/drivers/platform/x86/intel_scu_ipc.c
+++ b/drivers/platform/x86/intel_scu_ipc.c
@@ -524,7 +524,7 @@ int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen,
524 for (i = 0; i < inlen; i++) 524 for (i = 0; i < inlen; i++)
525 ipc_data_writel(*in++, 4 * i); 525 ipc_data_writel(*in++, 4 * i);
526 526
527 ipc_command(cmd << 12 | sub); 527 ipc_command((cmd << 12) | sub | (inlen << 18));
528 err = busy_loop(); 528 err = busy_loop();
529 529
530 for (i = 0; i < outlen; i++) 530 for (i = 0; i < outlen; i++)
diff --git a/drivers/power/max17040_battery.c b/drivers/power/max17040_battery.c
index f3e22c9fe20a..2f2f9a6f54fa 100644
--- a/drivers/power/max17040_battery.c
+++ b/drivers/power/max17040_battery.c
@@ -225,7 +225,6 @@ static int __devinit max17040_probe(struct i2c_client *client,
225 ret = power_supply_register(&client->dev, &chip->battery); 225 ret = power_supply_register(&client->dev, &chip->battery);
226 if (ret) { 226 if (ret) {
227 dev_err(&client->dev, "failed: power supply register\n"); 227 dev_err(&client->dev, "failed: power supply register\n");
228 i2c_set_clientdata(client, NULL);
229 kfree(chip); 228 kfree(chip);
230 return ret; 229 return ret;
231 } 230 }
@@ -245,7 +244,6 @@ static int __devexit max17040_remove(struct i2c_client *client)
245 244
246 power_supply_unregister(&chip->battery); 245 power_supply_unregister(&chip->battery);
247 cancel_delayed_work(&chip->work); 246 cancel_delayed_work(&chip->work);
248 i2c_set_clientdata(client, NULL);
249 kfree(chip); 247 kfree(chip);
250 return 0; 248 return 0;
251} 249}
diff --git a/drivers/rapidio/Kconfig b/drivers/rapidio/Kconfig
index c32822ad84a4..070211a5955c 100644
--- a/drivers/rapidio/Kconfig
+++ b/drivers/rapidio/Kconfig
@@ -8,3 +8,27 @@ config RAPIDIO_DISC_TIMEOUT
8 ---help--- 8 ---help---
9 Amount of time a discovery node waits for a host to complete 9 Amount of time a discovery node waits for a host to complete
10 enumeration before giving up. 10 enumeration before giving up.
11
12config RAPIDIO_ENABLE_RX_TX_PORTS
13 bool "Enable RapidIO Input/Output Ports"
14 depends on RAPIDIO
15 ---help---
16 The RapidIO specification describes a Output port transmit
17 enable and a Input port receive enable. The recommended state
18 for Input ports and Output ports should be disabled. When
19 this switch is set the RapidIO subsystem will enable all
20 ports for Input/Output direction to allow other traffic
21 than Maintenance transfers.
22
23source "drivers/rapidio/switches/Kconfig"
24
25config RAPIDIO_DEBUG
26 bool "RapidIO subsystem debug messages"
27 depends on RAPIDIO
28 help
29 Say Y here if you want the RapidIO subsystem to produce a bunch of
30 debug messages to the system log. Select this if you are having a
31 problem with the RapidIO subsystem and want to see more of what is
32 going on.
33
34 If you are unsure about this, say N here.
diff --git a/drivers/rapidio/Makefile b/drivers/rapidio/Makefile
index 7c0e1818de51..b6139fe187bf 100644
--- a/drivers/rapidio/Makefile
+++ b/drivers/rapidio/Makefile
@@ -4,3 +4,7 @@
4obj-y += rio.o rio-access.o rio-driver.o rio-scan.o rio-sysfs.o 4obj-y += rio.o rio-access.o rio-driver.o rio-scan.o rio-sysfs.o
5 5
6obj-$(CONFIG_RAPIDIO) += switches/ 6obj-$(CONFIG_RAPIDIO) += switches/
7
8ifeq ($(CONFIG_RAPIDIO_DEBUG),y)
9EXTRA_CFLAGS += -DDEBUG
10endif
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c
index 45415096c294..8070e074c739 100644
--- a/drivers/rapidio/rio-scan.c
+++ b/drivers/rapidio/rio-scan.c
@@ -4,6 +4,14 @@
4 * Copyright 2005 MontaVista Software, Inc. 4 * Copyright 2005 MontaVista Software, Inc.
5 * Matt Porter <mporter@kernel.crashing.org> 5 * Matt Porter <mporter@kernel.crashing.org>
6 * 6 *
7 * Copyright 2009 Integrated Device Technology, Inc.
8 * Alex Bounine <alexandre.bounine@idt.com>
9 * - Added Port-Write/Error Management initialization and handling
10 *
11 * Copyright 2009 Sysgo AG
12 * Thomas Moll <thomas.moll@sysgo.com>
13 * - Added Input- Output- enable functionality, to allow full communication
14 *
7 * This program is free software; you can redistribute it and/or modify it 15 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the 16 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your 17 * Free Software Foundation; either version 2 of the License, or (at your
@@ -31,15 +39,16 @@
31LIST_HEAD(rio_devices); 39LIST_HEAD(rio_devices);
32static LIST_HEAD(rio_switches); 40static LIST_HEAD(rio_switches);
33 41
34#define RIO_ENUM_CMPL_MAGIC 0xdeadbeef
35
36static void rio_enum_timeout(unsigned long); 42static void rio_enum_timeout(unsigned long);
37 43
44static void rio_init_em(struct rio_dev *rdev);
45
38DEFINE_SPINLOCK(rio_global_list_lock); 46DEFINE_SPINLOCK(rio_global_list_lock);
39 47
40static int next_destid = 0; 48static int next_destid = 0;
41static int next_switchid = 0; 49static int next_switchid = 0;
42static int next_net = 0; 50static int next_net = 0;
51static int next_comptag;
43 52
44static struct timer_list rio_enum_timer = 53static struct timer_list rio_enum_timer =
45TIMER_INITIALIZER(rio_enum_timeout, 0, 0); 54TIMER_INITIALIZER(rio_enum_timeout, 0, 0);
@@ -52,12 +61,6 @@ static int rio_mport_phys_table[] = {
52 -1, 61 -1,
53}; 62};
54 63
55static int rio_sport_phys_table[] = {
56 RIO_EFB_PAR_EP_FREE_ID,
57 RIO_EFB_SER_EP_FREE_ID,
58 -1,
59};
60
61/** 64/**
62 * rio_get_device_id - Get the base/extended device id for a device 65 * rio_get_device_id - Get the base/extended device id for a device
63 * @port: RIO master port 66 * @port: RIO master port
@@ -118,12 +121,26 @@ static int rio_clear_locks(struct rio_mport *port)
118 u32 result; 121 u32 result;
119 int ret = 0; 122 int ret = 0;
120 123
121 /* Write component tag CSR magic complete value */ 124 /* Assign component tag to all devices */
122 rio_local_write_config_32(port, RIO_COMPONENT_TAG_CSR, 125 next_comptag = 1;
123 RIO_ENUM_CMPL_MAGIC); 126 rio_local_write_config_32(port, RIO_COMPONENT_TAG_CSR, next_comptag++);
124 list_for_each_entry(rdev, &rio_devices, global_list) 127
125 rio_write_config_32(rdev, RIO_COMPONENT_TAG_CSR, 128 list_for_each_entry(rdev, &rio_devices, global_list) {
126 RIO_ENUM_CMPL_MAGIC); 129 /* Mark device as discovered */
130 rio_read_config_32(rdev,
131 rdev->phys_efptr + RIO_PORT_GEN_CTL_CSR,
132 &result);
133 rio_write_config_32(rdev,
134 rdev->phys_efptr + RIO_PORT_GEN_CTL_CSR,
135 result | RIO_PORT_GEN_DISCOVERED);
136
137 rio_write_config_32(rdev, RIO_COMPONENT_TAG_CSR, next_comptag);
138 rdev->comp_tag = next_comptag++;
139 if (next_comptag >= 0x10000) {
140 pr_err("RIO: Component Tag Counter Overflow\n");
141 break;
142 }
143 }
127 144
128 /* Release host device id locks */ 145 /* Release host device id locks */
129 rio_local_write_config_32(port, RIO_HOST_DID_LOCK_CSR, 146 rio_local_write_config_32(port, RIO_HOST_DID_LOCK_CSR,
@@ -229,27 +246,37 @@ static int rio_is_switch(struct rio_dev *rdev)
229} 246}
230 247
231/** 248/**
232 * rio_route_set_ops- Sets routing operations for a particular vendor switch 249 * rio_switch_init - Sets switch operations for a particular vendor switch
233 * @rdev: RIO device 250 * @rdev: RIO device
251 * @do_enum: Enumeration/Discovery mode flag
234 * 252 *
235 * Searches the RIO route ops table for known switch types. If the vid 253 * Searches the RIO switch ops table for known switch types. If the vid
236 * and did match a switch table entry, then set the add_entry() and 254 * and did match a switch table entry, then call switch initialization
237 * get_entry() ops to the table entry values. 255 * routine to setup switch-specific routines.
238 */ 256 */
239static void rio_route_set_ops(struct rio_dev *rdev) 257static void rio_switch_init(struct rio_dev *rdev, int do_enum)
240{ 258{
241 struct rio_route_ops *cur = __start_rio_route_ops; 259 struct rio_switch_ops *cur = __start_rio_switch_ops;
242 struct rio_route_ops *end = __end_rio_route_ops; 260 struct rio_switch_ops *end = __end_rio_switch_ops;
243 261
244 while (cur < end) { 262 while (cur < end) {
245 if ((cur->vid == rdev->vid) && (cur->did == rdev->did)) { 263 if ((cur->vid == rdev->vid) && (cur->did == rdev->did)) {
246 pr_debug("RIO: adding routing ops for %s\n", rio_name(rdev)); 264 pr_debug("RIO: calling init routine for %s\n",
247 rdev->rswitch->add_entry = cur->add_hook; 265 rio_name(rdev));
248 rdev->rswitch->get_entry = cur->get_hook; 266 cur->init_hook(rdev, do_enum);
267 break;
249 } 268 }
250 cur++; 269 cur++;
251 } 270 }
252 271
272 if ((cur >= end) && (rdev->pef & RIO_PEF_STD_RT)) {
273 pr_debug("RIO: adding STD routing ops for %s\n",
274 rio_name(rdev));
275 rdev->rswitch->add_entry = rio_std_route_add_entry;
276 rdev->rswitch->get_entry = rio_std_route_get_entry;
277 rdev->rswitch->clr_table = rio_std_route_clr_table;
278 }
279
253 if (!rdev->rswitch->add_entry || !rdev->rswitch->get_entry) 280 if (!rdev->rswitch->add_entry || !rdev->rswitch->get_entry)
254 printk(KERN_ERR "RIO: missing routing ops for %s\n", 281 printk(KERN_ERR "RIO: missing routing ops for %s\n",
255 rio_name(rdev)); 282 rio_name(rdev));
@@ -281,6 +308,65 @@ static int __devinit rio_add_device(struct rio_dev *rdev)
281} 308}
282 309
283/** 310/**
311 * rio_enable_rx_tx_port - enable input reciever and output transmitter of
312 * given port
313 * @port: Master port associated with the RIO network
314 * @local: local=1 select local port otherwise a far device is reached
315 * @destid: Destination ID of the device to check host bit
316 * @hopcount: Number of hops to reach the target
317 * @port_num: Port (-number on switch) to enable on a far end device
318 *
319 * Returns 0 or 1 from on General Control Command and Status Register
320 * (EXT_PTR+0x3C)
321 */
322inline int rio_enable_rx_tx_port(struct rio_mport *port,
323 int local, u16 destid,
324 u8 hopcount, u8 port_num) {
325#ifdef CONFIG_RAPIDIO_ENABLE_RX_TX_PORTS
326 u32 regval;
327 u32 ext_ftr_ptr;
328
329 /*
330 * enable rx input tx output port
331 */
332 pr_debug("rio_enable_rx_tx_port(local = %d, destid = %d, hopcount = "
333 "%d, port_num = %d)\n", local, destid, hopcount, port_num);
334
335 ext_ftr_ptr = rio_mport_get_physefb(port, local, destid, hopcount);
336
337 if (local) {
338 rio_local_read_config_32(port, ext_ftr_ptr +
339 RIO_PORT_N_CTL_CSR(0),
340 &regval);
341 } else {
342 if (rio_mport_read_config_32(port, destid, hopcount,
343 ext_ftr_ptr + RIO_PORT_N_CTL_CSR(port_num), &regval) < 0)
344 return -EIO;
345 }
346
347 if (regval & RIO_PORT_N_CTL_P_TYP_SER) {
348 /* serial */
349 regval = regval | RIO_PORT_N_CTL_EN_RX_SER
350 | RIO_PORT_N_CTL_EN_TX_SER;
351 } else {
352 /* parallel */
353 regval = regval | RIO_PORT_N_CTL_EN_RX_PAR
354 | RIO_PORT_N_CTL_EN_TX_PAR;
355 }
356
357 if (local) {
358 rio_local_write_config_32(port, ext_ftr_ptr +
359 RIO_PORT_N_CTL_CSR(0), regval);
360 } else {
361 if (rio_mport_write_config_32(port, destid, hopcount,
362 ext_ftr_ptr + RIO_PORT_N_CTL_CSR(port_num), regval) < 0)
363 return -EIO;
364 }
365#endif
366 return 0;
367}
368
369/**
284 * rio_setup_device- Allocates and sets up a RIO device 370 * rio_setup_device- Allocates and sets up a RIO device
285 * @net: RIO network 371 * @net: RIO network
286 * @port: Master port to send transactions 372 * @port: Master port to send transactions
@@ -325,8 +411,14 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
325 rdev->asm_rev = result >> 16; 411 rdev->asm_rev = result >> 16;
326 rio_mport_read_config_32(port, destid, hopcount, RIO_PEF_CAR, 412 rio_mport_read_config_32(port, destid, hopcount, RIO_PEF_CAR,
327 &rdev->pef); 413 &rdev->pef);
328 if (rdev->pef & RIO_PEF_EXT_FEATURES) 414 if (rdev->pef & RIO_PEF_EXT_FEATURES) {
329 rdev->efptr = result & 0xffff; 415 rdev->efptr = result & 0xffff;
416 rdev->phys_efptr = rio_mport_get_physefb(port, 0, destid,
417 hopcount);
418
419 rdev->em_efptr = rio_mport_get_feature(port, 0, destid,
420 hopcount, RIO_EFB_ERR_MGMNT);
421 }
330 422
331 rio_mport_read_config_32(port, destid, hopcount, RIO_SRC_OPS_CAR, 423 rio_mport_read_config_32(port, destid, hopcount, RIO_SRC_OPS_CAR,
332 &rdev->src_ops); 424 &rdev->src_ops);
@@ -349,12 +441,13 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
349 if (rio_is_switch(rdev)) { 441 if (rio_is_switch(rdev)) {
350 rio_mport_read_config_32(port, destid, hopcount, 442 rio_mport_read_config_32(port, destid, hopcount,
351 RIO_SWP_INFO_CAR, &rdev->swpinfo); 443 RIO_SWP_INFO_CAR, &rdev->swpinfo);
352 rswitch = kmalloc(sizeof(struct rio_switch), GFP_KERNEL); 444 rswitch = kzalloc(sizeof(struct rio_switch), GFP_KERNEL);
353 if (!rswitch) 445 if (!rswitch)
354 goto cleanup; 446 goto cleanup;
355 rswitch->switchid = next_switchid; 447 rswitch->switchid = next_switchid;
356 rswitch->hopcount = hopcount; 448 rswitch->hopcount = hopcount;
357 rswitch->destid = destid; 449 rswitch->destid = destid;
450 rswitch->port_ok = 0;
358 rswitch->route_table = kzalloc(sizeof(u8)* 451 rswitch->route_table = kzalloc(sizeof(u8)*
359 RIO_MAX_ROUTE_ENTRIES(port->sys_size), 452 RIO_MAX_ROUTE_ENTRIES(port->sys_size),
360 GFP_KERNEL); 453 GFP_KERNEL);
@@ -367,13 +460,22 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
367 rdev->rswitch = rswitch; 460 rdev->rswitch = rswitch;
368 dev_set_name(&rdev->dev, "%02x:s:%04x", rdev->net->id, 461 dev_set_name(&rdev->dev, "%02x:s:%04x", rdev->net->id,
369 rdev->rswitch->switchid); 462 rdev->rswitch->switchid);
370 rio_route_set_ops(rdev); 463 rio_switch_init(rdev, do_enum);
464
465 if (do_enum && rdev->rswitch->clr_table)
466 rdev->rswitch->clr_table(port, destid, hopcount,
467 RIO_GLOBAL_TABLE);
371 468
372 list_add_tail(&rswitch->node, &rio_switches); 469 list_add_tail(&rswitch->node, &rio_switches);
373 470
374 } else 471 } else {
472 if (do_enum)
473 /*Enable Input Output Port (transmitter reviever)*/
474 rio_enable_rx_tx_port(port, 0, destid, hopcount, 0);
475
375 dev_set_name(&rdev->dev, "%02x:e:%04x", rdev->net->id, 476 dev_set_name(&rdev->dev, "%02x:e:%04x", rdev->net->id,
376 rdev->destid); 477 rdev->destid);
478 }
377 479
378 rdev->dev.bus = &rio_bus_type; 480 rdev->dev.bus = &rio_bus_type;
379 481
@@ -414,23 +516,29 @@ cleanup:
414 * 516 *
415 * Reads the port error status CSR for a particular switch port to 517 * Reads the port error status CSR for a particular switch port to
416 * determine if the port has an active link. Returns 518 * determine if the port has an active link. Returns
417 * %PORT_N_ERR_STS_PORT_OK if the port is active or %0 if it is 519 * %RIO_PORT_N_ERR_STS_PORT_OK if the port is active or %0 if it is
418 * inactive. 520 * inactive.
419 */ 521 */
420static int 522static int
421rio_sport_is_active(struct rio_mport *port, u16 destid, u8 hopcount, int sport) 523rio_sport_is_active(struct rio_mport *port, u16 destid, u8 hopcount, int sport)
422{ 524{
423 u32 result; 525 u32 result = 0;
424 u32 ext_ftr_ptr; 526 u32 ext_ftr_ptr;
425 527
426 int *entry = rio_sport_phys_table; 528 ext_ftr_ptr = rio_mport_get_efb(port, 0, destid, hopcount, 0);
427
428 do {
429 if ((ext_ftr_ptr =
430 rio_mport_get_feature(port, 0, destid, hopcount, *entry)))
431 529
530 while (ext_ftr_ptr) {
531 rio_mport_read_config_32(port, destid, hopcount,
532 ext_ftr_ptr, &result);
533 result = RIO_GET_BLOCK_ID(result);
534 if ((result == RIO_EFB_SER_EP_FREE_ID) ||
535 (result == RIO_EFB_SER_EP_FREE_ID_V13P) ||
536 (result == RIO_EFB_SER_EP_FREC_ID))
432 break; 537 break;
433 } while (*++entry >= 0); 538
539 ext_ftr_ptr = rio_mport_get_efb(port, 0, destid, hopcount,
540 ext_ftr_ptr);
541 }
434 542
435 if (ext_ftr_ptr) 543 if (ext_ftr_ptr)
436 rio_mport_read_config_32(port, destid, hopcount, 544 rio_mport_read_config_32(port, destid, hopcount,
@@ -438,7 +546,81 @@ rio_sport_is_active(struct rio_mport *port, u16 destid, u8 hopcount, int sport)
438 RIO_PORT_N_ERR_STS_CSR(sport), 546 RIO_PORT_N_ERR_STS_CSR(sport),
439 &result); 547 &result);
440 548
441 return (result & PORT_N_ERR_STS_PORT_OK); 549 return result & RIO_PORT_N_ERR_STS_PORT_OK;
550}
551
552/**
553 * rio_lock_device - Acquires host device lock for specified device
554 * @port: Master port to send transaction
555 * @destid: Destination ID for device/switch
556 * @hopcount: Hopcount to reach switch
557 * @wait_ms: Max wait time in msec (0 = no timeout)
558 *
559 * Attepts to acquire host device lock for specified device
560 * Returns 0 if device lock acquired or EINVAL if timeout expires.
561 */
562static int
563rio_lock_device(struct rio_mport *port, u16 destid, u8 hopcount, int wait_ms)
564{
565 u32 result;
566 int tcnt = 0;
567
568 /* Attempt to acquire device lock */
569 rio_mport_write_config_32(port, destid, hopcount,
570 RIO_HOST_DID_LOCK_CSR, port->host_deviceid);
571 rio_mport_read_config_32(port, destid, hopcount,
572 RIO_HOST_DID_LOCK_CSR, &result);
573
574 while (result != port->host_deviceid) {
575 if (wait_ms != 0 && tcnt == wait_ms) {
576 pr_debug("RIO: timeout when locking device %x:%x\n",
577 destid, hopcount);
578 return -EINVAL;
579 }
580
581 /* Delay a bit */
582 mdelay(1);
583 tcnt++;
584 /* Try to acquire device lock again */
585 rio_mport_write_config_32(port, destid,
586 hopcount,
587 RIO_HOST_DID_LOCK_CSR,
588 port->host_deviceid);
589 rio_mport_read_config_32(port, destid,
590 hopcount,
591 RIO_HOST_DID_LOCK_CSR, &result);
592 }
593
594 return 0;
595}
596
597/**
598 * rio_unlock_device - Releases host device lock for specified device
599 * @port: Master port to send transaction
600 * @destid: Destination ID for device/switch
601 * @hopcount: Hopcount to reach switch
602 *
603 * Returns 0 if device lock released or EINVAL if fails.
604 */
605static int
606rio_unlock_device(struct rio_mport *port, u16 destid, u8 hopcount)
607{
608 u32 result;
609
610 /* Release device lock */
611 rio_mport_write_config_32(port, destid,
612 hopcount,
613 RIO_HOST_DID_LOCK_CSR,
614 port->host_deviceid);
615 rio_mport_read_config_32(port, destid, hopcount,
616 RIO_HOST_DID_LOCK_CSR, &result);
617 if ((result & 0xffff) != 0xffff) {
618 pr_debug("RIO: badness when releasing device lock %x:%x\n",
619 destid, hopcount);
620 return -EINVAL;
621 }
622
623 return 0;
442} 624}
443 625
444/** 626/**
@@ -448,6 +630,7 @@ rio_sport_is_active(struct rio_mport *port, u16 destid, u8 hopcount, int sport)
448 * @table: Routing table ID 630 * @table: Routing table ID
449 * @route_destid: Destination ID to be routed 631 * @route_destid: Destination ID to be routed
450 * @route_port: Port number to be routed 632 * @route_port: Port number to be routed
633 * @lock: lock switch device flag
451 * 634 *
452 * Calls the switch specific add_entry() method to add a route entry 635 * Calls the switch specific add_entry() method to add a route entry
453 * on a switch. The route table can be specified using the @table 636 * on a switch. The route table can be specified using the @table
@@ -456,12 +639,26 @@ rio_sport_is_active(struct rio_mport *port, u16 destid, u8 hopcount, int sport)
456 * %RIO_GLOBAL_TABLE in @table. Returns %0 on success or %-EINVAL 639 * %RIO_GLOBAL_TABLE in @table. Returns %0 on success or %-EINVAL
457 * on failure. 640 * on failure.
458 */ 641 */
459static int rio_route_add_entry(struct rio_mport *mport, struct rio_switch *rswitch, 642static int
460 u16 table, u16 route_destid, u8 route_port) 643rio_route_add_entry(struct rio_mport *mport, struct rio_switch *rswitch,
644 u16 table, u16 route_destid, u8 route_port, int lock)
461{ 645{
462 return rswitch->add_entry(mport, rswitch->destid, 646 int rc;
647
648 if (lock) {
649 rc = rio_lock_device(mport, rswitch->destid,
650 rswitch->hopcount, 1000);
651 if (rc)
652 return rc;
653 }
654
655 rc = rswitch->add_entry(mport, rswitch->destid,
463 rswitch->hopcount, table, 656 rswitch->hopcount, table,
464 route_destid, route_port); 657 route_destid, route_port);
658 if (lock)
659 rio_unlock_device(mport, rswitch->destid, rswitch->hopcount);
660
661 return rc;
465} 662}
466 663
467/** 664/**
@@ -471,6 +668,7 @@ static int rio_route_add_entry(struct rio_mport *mport, struct rio_switch *rswit
471 * @table: Routing table ID 668 * @table: Routing table ID
472 * @route_destid: Destination ID to be routed 669 * @route_destid: Destination ID to be routed
473 * @route_port: Pointer to read port number into 670 * @route_port: Pointer to read port number into
671 * @lock: lock switch device flag
474 * 672 *
475 * Calls the switch specific get_entry() method to read a route entry 673 * Calls the switch specific get_entry() method to read a route entry
476 * in a switch. The route table can be specified using the @table 674 * in a switch. The route table can be specified using the @table
@@ -481,11 +679,24 @@ static int rio_route_add_entry(struct rio_mport *mport, struct rio_switch *rswit
481 */ 679 */
482static int 680static int
483rio_route_get_entry(struct rio_mport *mport, struct rio_switch *rswitch, u16 table, 681rio_route_get_entry(struct rio_mport *mport, struct rio_switch *rswitch, u16 table,
484 u16 route_destid, u8 * route_port) 682 u16 route_destid, u8 *route_port, int lock)
485{ 683{
486 return rswitch->get_entry(mport, rswitch->destid, 684 int rc;
685
686 if (lock) {
687 rc = rio_lock_device(mport, rswitch->destid,
688 rswitch->hopcount, 1000);
689 if (rc)
690 return rc;
691 }
692
693 rc = rswitch->get_entry(mport, rswitch->destid,
487 rswitch->hopcount, table, 694 rswitch->hopcount, table,
488 route_destid, route_port); 695 route_destid, route_port);
696 if (lock)
697 rio_unlock_device(mport, rswitch->destid, rswitch->hopcount);
698
699 return rc;
489} 700}
490 701
491/** 702/**
@@ -625,14 +836,14 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
625 sw_inport = rio_get_swpinfo_inport(port, 836 sw_inport = rio_get_swpinfo_inport(port,
626 RIO_ANY_DESTID(port->sys_size), hopcount); 837 RIO_ANY_DESTID(port->sys_size), hopcount);
627 rio_route_add_entry(port, rdev->rswitch, RIO_GLOBAL_TABLE, 838 rio_route_add_entry(port, rdev->rswitch, RIO_GLOBAL_TABLE,
628 port->host_deviceid, sw_inport); 839 port->host_deviceid, sw_inport, 0);
629 rdev->rswitch->route_table[port->host_deviceid] = sw_inport; 840 rdev->rswitch->route_table[port->host_deviceid] = sw_inport;
630 841
631 for (destid = 0; destid < next_destid; destid++) { 842 for (destid = 0; destid < next_destid; destid++) {
632 if (destid == port->host_deviceid) 843 if (destid == port->host_deviceid)
633 continue; 844 continue;
634 rio_route_add_entry(port, rdev->rswitch, RIO_GLOBAL_TABLE, 845 rio_route_add_entry(port, rdev->rswitch, RIO_GLOBAL_TABLE,
635 destid, sw_inport); 846 destid, sw_inport, 0);
636 rdev->rswitch->route_table[destid] = sw_inport; 847 rdev->rswitch->route_table[destid] = sw_inport;
637 } 848 }
638 849
@@ -644,8 +855,15 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
644 rio_name(rdev), rdev->vid, rdev->did, num_ports); 855 rio_name(rdev), rdev->vid, rdev->did, num_ports);
645 sw_destid = next_destid; 856 sw_destid = next_destid;
646 for (port_num = 0; port_num < num_ports; port_num++) { 857 for (port_num = 0; port_num < num_ports; port_num++) {
647 if (sw_inport == port_num) 858 /*Enable Input Output Port (transmitter reviever)*/
859 rio_enable_rx_tx_port(port, 0,
860 RIO_ANY_DESTID(port->sys_size),
861 hopcount, port_num);
862
863 if (sw_inport == port_num) {
864 rdev->rswitch->port_ok |= (1 << port_num);
648 continue; 865 continue;
866 }
649 867
650 cur_destid = next_destid; 868 cur_destid = next_destid;
651 869
@@ -655,10 +873,11 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
655 pr_debug( 873 pr_debug(
656 "RIO: scanning device on port %d\n", 874 "RIO: scanning device on port %d\n",
657 port_num); 875 port_num);
876 rdev->rswitch->port_ok |= (1 << port_num);
658 rio_route_add_entry(port, rdev->rswitch, 877 rio_route_add_entry(port, rdev->rswitch,
659 RIO_GLOBAL_TABLE, 878 RIO_GLOBAL_TABLE,
660 RIO_ANY_DESTID(port->sys_size), 879 RIO_ANY_DESTID(port->sys_size),
661 port_num); 880 port_num, 0);
662 881
663 if (rio_enum_peer(net, port, hopcount + 1) < 0) 882 if (rio_enum_peer(net, port, hopcount + 1) < 0)
664 return -1; 883 return -1;
@@ -672,15 +891,35 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
672 rio_route_add_entry(port, rdev->rswitch, 891 rio_route_add_entry(port, rdev->rswitch,
673 RIO_GLOBAL_TABLE, 892 RIO_GLOBAL_TABLE,
674 destid, 893 destid,
675 port_num); 894 port_num,
895 0);
676 rdev->rswitch-> 896 rdev->rswitch->
677 route_table[destid] = 897 route_table[destid] =
678 port_num; 898 port_num;
679 } 899 }
680 } 900 }
901 } else {
902 /* If switch supports Error Management,
903 * set PORT_LOCKOUT bit for unused port
904 */
905 if (rdev->em_efptr)
906 rio_set_port_lockout(rdev, port_num, 1);
907
908 rdev->rswitch->port_ok &= ~(1 << port_num);
681 } 909 }
682 } 910 }
683 911
912 /* Direct Port-write messages to the enumeratiing host */
913 if ((rdev->src_ops & RIO_SRC_OPS_PORT_WRITE) &&
914 (rdev->em_efptr)) {
915 rio_write_config_32(rdev,
916 rdev->em_efptr + RIO_EM_PW_TGT_DEVID,
917 (port->host_deviceid << 16) |
918 (port->sys_size << 15));
919 }
920
921 rio_init_em(rdev);
922
684 /* Check for empty switch */ 923 /* Check for empty switch */
685 if (next_destid == sw_destid) { 924 if (next_destid == sw_destid) {
686 next_destid++; 925 next_destid++;
@@ -700,21 +939,16 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
700 * rio_enum_complete- Tests if enumeration of a network is complete 939 * rio_enum_complete- Tests if enumeration of a network is complete
701 * @port: Master port to send transaction 940 * @port: Master port to send transaction
702 * 941 *
703 * Tests the Component Tag CSR for presence of the magic enumeration 942 * Tests the Component Tag CSR for non-zero value (enumeration
704 * complete flag. Return %1 if enumeration is complete or %0 if 943 * complete flag). Return %1 if enumeration is complete or %0 if
705 * enumeration is incomplete. 944 * enumeration is incomplete.
706 */ 945 */
707static int rio_enum_complete(struct rio_mport *port) 946static int rio_enum_complete(struct rio_mport *port)
708{ 947{
709 u32 tag_csr; 948 u32 tag_csr;
710 int ret = 0;
711 949
712 rio_local_read_config_32(port, RIO_COMPONENT_TAG_CSR, &tag_csr); 950 rio_local_read_config_32(port, RIO_COMPONENT_TAG_CSR, &tag_csr);
713 951 return (tag_csr & 0xffff) ? 1 : 0;
714 if (tag_csr == RIO_ENUM_CMPL_MAGIC)
715 ret = 1;
716
717 return ret;
718} 952}
719 953
720/** 954/**
@@ -763,17 +997,21 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid,
763 pr_debug( 997 pr_debug(
764 "RIO: scanning device on port %d\n", 998 "RIO: scanning device on port %d\n",
765 port_num); 999 port_num);
1000
1001 rio_lock_device(port, destid, hopcount, 1000);
1002
766 for (ndestid = 0; 1003 for (ndestid = 0;
767 ndestid < RIO_ANY_DESTID(port->sys_size); 1004 ndestid < RIO_ANY_DESTID(port->sys_size);
768 ndestid++) { 1005 ndestid++) {
769 rio_route_get_entry(port, rdev->rswitch, 1006 rio_route_get_entry(port, rdev->rswitch,
770 RIO_GLOBAL_TABLE, 1007 RIO_GLOBAL_TABLE,
771 ndestid, 1008 ndestid,
772 &route_port); 1009 &route_port, 0);
773 if (route_port == port_num) 1010 if (route_port == port_num)
774 break; 1011 break;
775 } 1012 }
776 1013
1014 rio_unlock_device(port, destid, hopcount);
777 if (rio_disc_peer 1015 if (rio_disc_peer
778 (net, port, ndestid, hopcount + 1) < 0) 1016 (net, port, ndestid, hopcount + 1) < 0)
779 return -1; 1017 return -1;
@@ -792,7 +1030,7 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid,
792 * 1030 *
793 * Reads the port error status CSR for the master port to 1031 * Reads the port error status CSR for the master port to
794 * determine if the port has an active link. Returns 1032 * determine if the port has an active link. Returns
795 * %PORT_N_ERR_STS_PORT_OK if the master port is active 1033 * %RIO_PORT_N_ERR_STS_PORT_OK if the master port is active
796 * or %0 if it is inactive. 1034 * or %0 if it is inactive.
797 */ 1035 */
798static int rio_mport_is_active(struct rio_mport *port) 1036static int rio_mport_is_active(struct rio_mport *port)
@@ -813,7 +1051,7 @@ static int rio_mport_is_active(struct rio_mport *port)
813 RIO_PORT_N_ERR_STS_CSR(port->index), 1051 RIO_PORT_N_ERR_STS_CSR(port->index),
814 &result); 1052 &result);
815 1053
816 return (result & PORT_N_ERR_STS_PORT_OK); 1054 return result & RIO_PORT_N_ERR_STS_PORT_OK;
817} 1055}
818 1056
819/** 1057/**
@@ -866,12 +1104,17 @@ static void rio_update_route_tables(struct rio_mport *port)
866 continue; 1104 continue;
867 1105
868 if (RIO_INVALID_ROUTE == rswitch->route_table[destid]) { 1106 if (RIO_INVALID_ROUTE == rswitch->route_table[destid]) {
1107 /* Skip if destid ends in empty switch*/
1108 if (rswitch->destid == destid)
1109 continue;
869 1110
870 sport = rio_get_swpinfo_inport(port, 1111 sport = rio_get_swpinfo_inport(port,
871 rswitch->destid, rswitch->hopcount); 1112 rswitch->destid, rswitch->hopcount);
872 1113
873 if (rswitch->add_entry) { 1114 if (rswitch->add_entry) {
874 rio_route_add_entry(port, rswitch, RIO_GLOBAL_TABLE, destid, sport); 1115 rio_route_add_entry(port, rswitch,
1116 RIO_GLOBAL_TABLE, destid,
1117 sport, 0);
875 rswitch->route_table[destid] = sport; 1118 rswitch->route_table[destid] = sport;
876 } 1119 }
877 } 1120 }
@@ -880,6 +1123,32 @@ static void rio_update_route_tables(struct rio_mport *port)
880} 1123}
881 1124
882/** 1125/**
1126 * rio_init_em - Initializes RIO Error Management (for switches)
1127 * @rdev: RIO device
1128 *
1129 * For each enumerated switch, call device-specific error management
1130 * initialization routine (if supplied by the switch driver).
1131 */
1132static void rio_init_em(struct rio_dev *rdev)
1133{
1134 if (rio_is_switch(rdev) && (rdev->em_efptr) &&
1135 (rdev->rswitch->em_init)) {
1136 rdev->rswitch->em_init(rdev);
1137 }
1138}
1139
1140/**
1141 * rio_pw_enable - Enables/disables port-write handling by a master port
1142 * @port: Master port associated with port-write handling
1143 * @enable: 1=enable, 0=disable
1144 */
1145static void rio_pw_enable(struct rio_mport *port, int enable)
1146{
1147 if (port->ops->pwenable)
1148 port->ops->pwenable(port, enable);
1149}
1150
1151/**
883 * rio_enum_mport- Start enumeration through a master port 1152 * rio_enum_mport- Start enumeration through a master port
884 * @mport: Master port to send transactions 1153 * @mport: Master port to send transactions
885 * 1154 *
@@ -911,6 +1180,10 @@ int __devinit rio_enum_mport(struct rio_mport *mport)
911 rc = -ENOMEM; 1180 rc = -ENOMEM;
912 goto out; 1181 goto out;
913 } 1182 }
1183
1184 /* Enable Input Output Port (transmitter reviever) */
1185 rio_enable_rx_tx_port(mport, 1, 0, 0, 0);
1186
914 if (rio_enum_peer(net, mport, 0) < 0) { 1187 if (rio_enum_peer(net, mport, 0) < 0) {
915 /* A higher priority host won enumeration, bail. */ 1188 /* A higher priority host won enumeration, bail. */
916 printk(KERN_INFO 1189 printk(KERN_INFO
@@ -922,6 +1195,7 @@ int __devinit rio_enum_mport(struct rio_mport *mport)
922 } 1195 }
923 rio_update_route_tables(mport); 1196 rio_update_route_tables(mport);
924 rio_clear_locks(mport); 1197 rio_clear_locks(mport);
1198 rio_pw_enable(mport, 1);
925 } else { 1199 } else {
926 printk(KERN_INFO "RIO: master port %d link inactive\n", 1200 printk(KERN_INFO "RIO: master port %d link inactive\n",
927 mport->id); 1201 mport->id);
@@ -945,15 +1219,22 @@ static void rio_build_route_tables(void)
945 u8 sport; 1219 u8 sport;
946 1220
947 list_for_each_entry(rdev, &rio_devices, global_list) 1221 list_for_each_entry(rdev, &rio_devices, global_list)
948 if (rio_is_switch(rdev)) 1222 if (rio_is_switch(rdev)) {
949 for (i = 0; 1223 rio_lock_device(rdev->net->hport, rdev->rswitch->destid,
950 i < RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size); 1224 rdev->rswitch->hopcount, 1000);
951 i++) { 1225 for (i = 0;
952 if (rio_route_get_entry 1226 i < RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size);
953 (rdev->net->hport, rdev->rswitch, RIO_GLOBAL_TABLE, 1227 i++) {
954 i, &sport) < 0) 1228 if (rio_route_get_entry
955 continue; 1229 (rdev->net->hport, rdev->rswitch,
956 rdev->rswitch->route_table[i] = sport; 1230 RIO_GLOBAL_TABLE, i, &sport, 0) < 0)
1231 continue;
1232 rdev->rswitch->route_table[i] = sport;
1233 }
1234
1235 rio_unlock_device(rdev->net->hport,
1236 rdev->rswitch->destid,
1237 rdev->rswitch->hopcount);
957 } 1238 }
958} 1239}
959 1240
@@ -1012,6 +1293,13 @@ int __devinit rio_disc_mport(struct rio_mport *mport)
1012 del_timer_sync(&rio_enum_timer); 1293 del_timer_sync(&rio_enum_timer);
1013 1294
1014 pr_debug("done\n"); 1295 pr_debug("done\n");
1296
1297 /* Read DestID assigned by enumerator */
1298 rio_local_read_config_32(mport, RIO_DID_CSR,
1299 &mport->host_deviceid);
1300 mport->host_deviceid = RIO_GET_DID(mport->sys_size,
1301 mport->host_deviceid);
1302
1015 if (rio_disc_peer(net, mport, RIO_ANY_DESTID(mport->sys_size), 1303 if (rio_disc_peer(net, mport, RIO_ANY_DESTID(mport->sys_size),
1016 0) < 0) { 1304 0) < 0) {
1017 printk(KERN_INFO 1305 printk(KERN_INFO
diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c
index 6395c780008b..08fa453af974 100644
--- a/drivers/rapidio/rio.c
+++ b/drivers/rapidio/rio.c
@@ -5,6 +5,10 @@
5 * Copyright 2005 MontaVista Software, Inc. 5 * Copyright 2005 MontaVista Software, Inc.
6 * Matt Porter <mporter@kernel.crashing.org> 6 * Matt Porter <mporter@kernel.crashing.org>
7 * 7 *
8 * Copyright 2009 Integrated Device Technology, Inc.
9 * Alex Bounine <alexandre.bounine@idt.com>
10 * - Added Port-Write/Error Management initialization and handling
11 *
8 * This program is free software; you can redistribute it and/or modify it 12 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the 13 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your 14 * Free Software Foundation; either version 2 of the License, or (at your
@@ -333,6 +337,331 @@ int rio_release_outb_dbell(struct rio_dev *rdev, struct resource *res)
333} 337}
334 338
335/** 339/**
340 * rio_request_inb_pwrite - request inbound port-write message service
341 * @rdev: RIO device to which register inbound port-write callback routine
342 * @pwcback: Callback routine to execute when port-write is received
343 *
344 * Binds a port-write callback function to the RapidIO device.
345 * Returns 0 if the request has been satisfied.
346 */
347int rio_request_inb_pwrite(struct rio_dev *rdev,
348 int (*pwcback)(struct rio_dev *rdev, union rio_pw_msg *msg, int step))
349{
350 int rc = 0;
351
352 spin_lock(&rio_global_list_lock);
353 if (rdev->pwcback != NULL)
354 rc = -ENOMEM;
355 else
356 rdev->pwcback = pwcback;
357
358 spin_unlock(&rio_global_list_lock);
359 return rc;
360}
361EXPORT_SYMBOL_GPL(rio_request_inb_pwrite);
362
363/**
364 * rio_release_inb_pwrite - release inbound port-write message service
365 * @rdev: RIO device which registered for inbound port-write callback
366 *
367 * Removes callback from the rio_dev structure. Returns 0 if the request
368 * has been satisfied.
369 */
370int rio_release_inb_pwrite(struct rio_dev *rdev)
371{
372 int rc = -ENOMEM;
373
374 spin_lock(&rio_global_list_lock);
375 if (rdev->pwcback) {
376 rdev->pwcback = NULL;
377 rc = 0;
378 }
379
380 spin_unlock(&rio_global_list_lock);
381 return rc;
382}
383EXPORT_SYMBOL_GPL(rio_release_inb_pwrite);
384
385/**
386 * rio_mport_get_physefb - Helper function that returns register offset
387 * for Physical Layer Extended Features Block.
388 * @port: Master port to issue transaction
389 * @local: Indicate a local master port or remote device access
390 * @destid: Destination ID of the device
391 * @hopcount: Number of switch hops to the device
392 */
393u32
394rio_mport_get_physefb(struct rio_mport *port, int local,
395 u16 destid, u8 hopcount)
396{
397 u32 ext_ftr_ptr;
398 u32 ftr_header;
399
400 ext_ftr_ptr = rio_mport_get_efb(port, local, destid, hopcount, 0);
401
402 while (ext_ftr_ptr) {
403 if (local)
404 rio_local_read_config_32(port, ext_ftr_ptr,
405 &ftr_header);
406 else
407 rio_mport_read_config_32(port, destid, hopcount,
408 ext_ftr_ptr, &ftr_header);
409
410 ftr_header = RIO_GET_BLOCK_ID(ftr_header);
411 switch (ftr_header) {
412
413 case RIO_EFB_SER_EP_ID_V13P:
414 case RIO_EFB_SER_EP_REC_ID_V13P:
415 case RIO_EFB_SER_EP_FREE_ID_V13P:
416 case RIO_EFB_SER_EP_ID:
417 case RIO_EFB_SER_EP_REC_ID:
418 case RIO_EFB_SER_EP_FREE_ID:
419 case RIO_EFB_SER_EP_FREC_ID:
420
421 return ext_ftr_ptr;
422
423 default:
424 break;
425 }
426
427 ext_ftr_ptr = rio_mport_get_efb(port, local, destid,
428 hopcount, ext_ftr_ptr);
429 }
430
431 return ext_ftr_ptr;
432}
433
434/**
435 * rio_get_comptag - Begin or continue searching for a RIO device by component tag
436 * @comp_tag: RIO component tag to match
437 * @from: Previous RIO device found in search, or %NULL for new search
438 *
439 * Iterates through the list of known RIO devices. If a RIO device is
440 * found with a matching @comp_tag, a pointer to its device
441 * structure is returned. Otherwise, %NULL is returned. A new search
442 * is initiated by passing %NULL to the @from argument. Otherwise, if
443 * @from is not %NULL, searches continue from next device on the global
444 * list.
445 */
446static struct rio_dev *rio_get_comptag(u32 comp_tag, struct rio_dev *from)
447{
448 struct list_head *n;
449 struct rio_dev *rdev;
450
451 spin_lock(&rio_global_list_lock);
452 n = from ? from->global_list.next : rio_devices.next;
453
454 while (n && (n != &rio_devices)) {
455 rdev = rio_dev_g(n);
456 if (rdev->comp_tag == comp_tag)
457 goto exit;
458 n = n->next;
459 }
460 rdev = NULL;
461exit:
462 spin_unlock(&rio_global_list_lock);
463 return rdev;
464}
465
466/**
467 * rio_set_port_lockout - Sets/clears LOCKOUT bit (RIO EM 1.3) for a switch port.
468 * @rdev: Pointer to RIO device control structure
469 * @pnum: Switch port number to set LOCKOUT bit
470 * @lock: Operation : set (=1) or clear (=0)
471 */
472int rio_set_port_lockout(struct rio_dev *rdev, u32 pnum, int lock)
473{
474 u8 hopcount = 0xff;
475 u16 destid = rdev->destid;
476 u32 regval;
477
478 if (rdev->rswitch) {
479 destid = rdev->rswitch->destid;
480 hopcount = rdev->rswitch->hopcount;
481 }
482
483 rio_mport_read_config_32(rdev->net->hport, destid, hopcount,
484 rdev->phys_efptr + RIO_PORT_N_CTL_CSR(pnum),
485 &regval);
486 if (lock)
487 regval |= RIO_PORT_N_CTL_LOCKOUT;
488 else
489 regval &= ~RIO_PORT_N_CTL_LOCKOUT;
490
491 rio_mport_write_config_32(rdev->net->hport, destid, hopcount,
492 rdev->phys_efptr + RIO_PORT_N_CTL_CSR(pnum),
493 regval);
494 return 0;
495}
496
497/**
498 * rio_inb_pwrite_handler - process inbound port-write message
499 * @pw_msg: pointer to inbound port-write message
500 *
501 * Processes an inbound port-write message. Returns 0 if the request
502 * has been satisfied.
503 */
504int rio_inb_pwrite_handler(union rio_pw_msg *pw_msg)
505{
506 struct rio_dev *rdev;
507 struct rio_mport *mport;
508 u8 hopcount;
509 u16 destid;
510 u32 err_status;
511 int rc, portnum;
512
513 rdev = rio_get_comptag(pw_msg->em.comptag, NULL);
514 if (rdev == NULL) {
515 /* Someting bad here (probably enumeration error) */
516 pr_err("RIO: %s No matching device for CTag 0x%08x\n",
517 __func__, pw_msg->em.comptag);
518 return -EIO;
519 }
520
521 pr_debug("RIO: Port-Write message from %s\n", rio_name(rdev));
522
523#ifdef DEBUG_PW
524 {
525 u32 i;
526 for (i = 0; i < RIO_PW_MSG_SIZE/sizeof(u32);) {
527 pr_debug("0x%02x: %08x %08x %08x %08x",
528 i*4, pw_msg->raw[i], pw_msg->raw[i + 1],
529 pw_msg->raw[i + 2], pw_msg->raw[i + 3]);
530 i += 4;
531 }
532 pr_debug("\n");
533 }
534#endif
535
536 /* Call an external service function (if such is registered
537 * for this device). This may be the service for endpoints that send
538 * device-specific port-write messages. End-point messages expected
539 * to be handled completely by EP specific device driver.
540 * For switches rc==0 signals that no standard processing required.
541 */
542 if (rdev->pwcback != NULL) {
543 rc = rdev->pwcback(rdev, pw_msg, 0);
544 if (rc == 0)
545 return 0;
546 }
547
548 /* For End-point devices processing stops here */
549 if (!(rdev->pef & RIO_PEF_SWITCH))
550 return 0;
551
552 if (rdev->phys_efptr == 0) {
553 pr_err("RIO_PW: Bad switch initialization for %s\n",
554 rio_name(rdev));
555 return 0;
556 }
557
558 mport = rdev->net->hport;
559 destid = rdev->rswitch->destid;
560 hopcount = rdev->rswitch->hopcount;
561
562 /*
563 * Process the port-write notification from switch
564 */
565
566 portnum = pw_msg->em.is_port & 0xFF;
567
568 if (rdev->rswitch->em_handle)
569 rdev->rswitch->em_handle(rdev, portnum);
570
571 rio_mport_read_config_32(mport, destid, hopcount,
572 rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum),
573 &err_status);
574 pr_debug("RIO_PW: SP%d_ERR_STS_CSR=0x%08x\n", portnum, err_status);
575
576 if (pw_msg->em.errdetect) {
577 pr_debug("RIO_PW: RIO_EM_P%d_ERR_DETECT=0x%08x\n",
578 portnum, pw_msg->em.errdetect);
579 /* Clear EM Port N Error Detect CSR */
580 rio_mport_write_config_32(mport, destid, hopcount,
581 rdev->em_efptr + RIO_EM_PN_ERR_DETECT(portnum), 0);
582 }
583
584 if (pw_msg->em.ltlerrdet) {
585 pr_debug("RIO_PW: RIO_EM_LTL_ERR_DETECT=0x%08x\n",
586 pw_msg->em.ltlerrdet);
587 /* Clear EM L/T Layer Error Detect CSR */
588 rio_mport_write_config_32(mport, destid, hopcount,
589 rdev->em_efptr + RIO_EM_LTL_ERR_DETECT, 0);
590 }
591
592 /* Clear Port Errors */
593 rio_mport_write_config_32(mport, destid, hopcount,
594 rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum),
595 err_status & RIO_PORT_N_ERR_STS_CLR_MASK);
596
597 if (rdev->rswitch->port_ok & (1 << portnum)) {
598 if (err_status & RIO_PORT_N_ERR_STS_PORT_UNINIT) {
599 rdev->rswitch->port_ok &= ~(1 << portnum);
600 rio_set_port_lockout(rdev, portnum, 1);
601
602 rio_mport_write_config_32(mport, destid, hopcount,
603 rdev->phys_efptr +
604 RIO_PORT_N_ACK_STS_CSR(portnum),
605 RIO_PORT_N_ACK_CLEAR);
606
607 /* Schedule Extraction Service */
608 pr_debug("RIO_PW: Device Extraction on [%s]-P%d\n",
609 rio_name(rdev), portnum);
610 }
611 } else {
612 if (err_status & RIO_PORT_N_ERR_STS_PORT_OK) {
613 rdev->rswitch->port_ok |= (1 << portnum);
614 rio_set_port_lockout(rdev, portnum, 0);
615
616 /* Schedule Insertion Service */
617 pr_debug("RIO_PW: Device Insertion on [%s]-P%d\n",
618 rio_name(rdev), portnum);
619 }
620 }
621
622 /* Clear Port-Write Pending bit */
623 rio_mport_write_config_32(mport, destid, hopcount,
624 rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum),
625 RIO_PORT_N_ERR_STS_PW_PEND);
626
627 return 0;
628}
629EXPORT_SYMBOL_GPL(rio_inb_pwrite_handler);
630
631/**
632 * rio_mport_get_efb - get pointer to next extended features block
633 * @port: Master port to issue transaction
634 * @local: Indicate a local master port or remote device access
635 * @destid: Destination ID of the device
636 * @hopcount: Number of switch hops to the device
637 * @from: Offset of current Extended Feature block header (if 0 starts
638 * from ExtFeaturePtr)
639 */
640u32
641rio_mport_get_efb(struct rio_mport *port, int local, u16 destid,
642 u8 hopcount, u32 from)
643{
644 u32 reg_val;
645
646 if (from == 0) {
647 if (local)
648 rio_local_read_config_32(port, RIO_ASM_INFO_CAR,
649 &reg_val);
650 else
651 rio_mport_read_config_32(port, destid, hopcount,
652 RIO_ASM_INFO_CAR, &reg_val);
653 return reg_val & RIO_EXT_FTR_PTR_MASK;
654 } else {
655 if (local)
656 rio_local_read_config_32(port, from, &reg_val);
657 else
658 rio_mport_read_config_32(port, destid, hopcount,
659 from, &reg_val);
660 return RIO_GET_BLOCK_ID(reg_val);
661 }
662}
663
664/**
336 * rio_mport_get_feature - query for devices' extended features 665 * rio_mport_get_feature - query for devices' extended features
337 * @port: Master port to issue transaction 666 * @port: Master port to issue transaction
338 * @local: Indicate a local master port or remote device access 667 * @local: Indicate a local master port or remote device access
@@ -451,6 +780,110 @@ struct rio_dev *rio_get_device(u16 vid, u16 did, struct rio_dev *from)
451 return rio_get_asm(vid, did, RIO_ANY_ID, RIO_ANY_ID, from); 780 return rio_get_asm(vid, did, RIO_ANY_ID, RIO_ANY_ID, from);
452} 781}
453 782
783/**
784 * rio_std_route_add_entry - Add switch route table entry using standard
785 * registers defined in RIO specification rev.1.3
786 * @mport: Master port to issue transaction
787 * @destid: Destination ID of the device
788 * @hopcount: Number of switch hops to the device
789 * @table: routing table ID (global or port-specific)
790 * @route_destid: destID entry in the RT
791 * @route_port: destination port for specified destID
792 */
793int rio_std_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
794 u16 table, u16 route_destid, u8 route_port)
795{
796 if (table == RIO_GLOBAL_TABLE) {
797 rio_mport_write_config_32(mport, destid, hopcount,
798 RIO_STD_RTE_CONF_DESTID_SEL_CSR,
799 (u32)route_destid);
800 rio_mport_write_config_32(mport, destid, hopcount,
801 RIO_STD_RTE_CONF_PORT_SEL_CSR,
802 (u32)route_port);
803 }
804
805 udelay(10);
806 return 0;
807}
808
809/**
810 * rio_std_route_get_entry - Read switch route table entry (port number)
811 * assosiated with specified destID using standard registers defined in RIO
812 * specification rev.1.3
813 * @mport: Master port to issue transaction
814 * @destid: Destination ID of the device
815 * @hopcount: Number of switch hops to the device
816 * @table: routing table ID (global or port-specific)
817 * @route_destid: destID entry in the RT
818 * @route_port: returned destination port for specified destID
819 */
820int rio_std_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
821 u16 table, u16 route_destid, u8 *route_port)
822{
823 u32 result;
824
825 if (table == RIO_GLOBAL_TABLE) {
826 rio_mport_write_config_32(mport, destid, hopcount,
827 RIO_STD_RTE_CONF_DESTID_SEL_CSR, route_destid);
828 rio_mport_read_config_32(mport, destid, hopcount,
829 RIO_STD_RTE_CONF_PORT_SEL_CSR, &result);
830
831 *route_port = (u8)result;
832 }
833
834 return 0;
835}
836
837/**
838 * rio_std_route_clr_table - Clear swotch route table using standard registers
839 * defined in RIO specification rev.1.3.
840 * @mport: Master port to issue transaction
841 * @destid: Destination ID of the device
842 * @hopcount: Number of switch hops to the device
843 * @table: routing table ID (global or port-specific)
844 */
845int rio_std_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount,
846 u16 table)
847{
848 u32 max_destid = 0xff;
849 u32 i, pef, id_inc = 1, ext_cfg = 0;
850 u32 port_sel = RIO_INVALID_ROUTE;
851
852 if (table == RIO_GLOBAL_TABLE) {
853 rio_mport_read_config_32(mport, destid, hopcount,
854 RIO_PEF_CAR, &pef);
855
856 if (mport->sys_size) {
857 rio_mport_read_config_32(mport, destid, hopcount,
858 RIO_SWITCH_RT_LIMIT,
859 &max_destid);
860 max_destid &= RIO_RT_MAX_DESTID;
861 }
862
863 if (pef & RIO_PEF_EXT_RT) {
864 ext_cfg = 0x80000000;
865 id_inc = 4;
866 port_sel = (RIO_INVALID_ROUTE << 24) |
867 (RIO_INVALID_ROUTE << 16) |
868 (RIO_INVALID_ROUTE << 8) |
869 RIO_INVALID_ROUTE;
870 }
871
872 for (i = 0; i <= max_destid;) {
873 rio_mport_write_config_32(mport, destid, hopcount,
874 RIO_STD_RTE_CONF_DESTID_SEL_CSR,
875 ext_cfg | i);
876 rio_mport_write_config_32(mport, destid, hopcount,
877 RIO_STD_RTE_CONF_PORT_SEL_CSR,
878 port_sel);
879 i += id_inc;
880 }
881 }
882
883 udelay(10);
884 return 0;
885}
886
454static void rio_fixup_device(struct rio_dev *dev) 887static void rio_fixup_device(struct rio_dev *dev)
455{ 888{
456} 889}
diff --git a/drivers/rapidio/rio.h b/drivers/rapidio/rio.h
index 7786d02581f2..f27b7a9c47d2 100644
--- a/drivers/rapidio/rio.h
+++ b/drivers/rapidio/rio.h
@@ -18,38 +18,50 @@
18 18
19extern u32 rio_mport_get_feature(struct rio_mport *mport, int local, u16 destid, 19extern u32 rio_mport_get_feature(struct rio_mport *mport, int local, u16 destid,
20 u8 hopcount, int ftr); 20 u8 hopcount, int ftr);
21extern u32 rio_mport_get_physefb(struct rio_mport *port, int local,
22 u16 destid, u8 hopcount);
23extern u32 rio_mport_get_efb(struct rio_mport *port, int local, u16 destid,
24 u8 hopcount, u32 from);
21extern int rio_create_sysfs_dev_files(struct rio_dev *rdev); 25extern int rio_create_sysfs_dev_files(struct rio_dev *rdev);
22extern int rio_enum_mport(struct rio_mport *mport); 26extern int rio_enum_mport(struct rio_mport *mport);
23extern int rio_disc_mport(struct rio_mport *mport); 27extern int rio_disc_mport(struct rio_mport *mport);
28extern int rio_std_route_add_entry(struct rio_mport *mport, u16 destid,
29 u8 hopcount, u16 table, u16 route_destid,
30 u8 route_port);
31extern int rio_std_route_get_entry(struct rio_mport *mport, u16 destid,
32 u8 hopcount, u16 table, u16 route_destid,
33 u8 *route_port);
34extern int rio_std_route_clr_table(struct rio_mport *mport, u16 destid,
35 u8 hopcount, u16 table);
36extern int rio_set_port_lockout(struct rio_dev *rdev, u32 pnum, int lock);
24 37
25/* Structures internal to the RIO core code */ 38/* Structures internal to the RIO core code */
26extern struct device_attribute rio_dev_attrs[]; 39extern struct device_attribute rio_dev_attrs[];
27extern spinlock_t rio_global_list_lock; 40extern spinlock_t rio_global_list_lock;
28 41
29extern struct rio_route_ops __start_rio_route_ops[]; 42extern struct rio_switch_ops __start_rio_switch_ops[];
30extern struct rio_route_ops __end_rio_route_ops[]; 43extern struct rio_switch_ops __end_rio_switch_ops[];
31 44
32/* Helpers internal to the RIO core code */ 45/* Helpers internal to the RIO core code */
33#define DECLARE_RIO_ROUTE_SECTION(section, vid, did, add_hook, get_hook) \ 46#define DECLARE_RIO_SWITCH_SECTION(section, name, vid, did, init_hook) \
34 static struct rio_route_ops __rio_route_ops __used \ 47 static const struct rio_switch_ops __rio_switch_##name __used \
35 __section(section)= { vid, did, add_hook, get_hook }; 48 __section(section) = { vid, did, init_hook };
36 49
37/** 50/**
38 * DECLARE_RIO_ROUTE_OPS - Registers switch routing operations 51 * DECLARE_RIO_SWITCH_INIT - Registers switch initialization routine
39 * @vid: RIO vendor ID 52 * @vid: RIO vendor ID
40 * @did: RIO device ID 53 * @did: RIO device ID
41 * @add_hook: Callback that adds a route entry 54 * @init_hook: Callback that performs switch-specific initialization
42 * @get_hook: Callback that gets a route entry
43 * 55 *
44 * Manipulating switch route tables in RIO is switch specific. This 56 * Manipulating switch route tables and error management in RIO
45 * registers a switch by vendor and device ID with two callbacks for 57 * is switch specific. This registers a switch by vendor and device ID with
46 * modifying and retrieving route entries in a switch. A &struct 58 * initialization callback for setting up switch operations and (if required)
47 * rio_route_ops is initialized with the ops and placed into a 59 * hardware initialization. A &struct rio_switch_ops is initialized with
48 * RIO-specific kernel section. 60 * pointer to the init routine and placed into a RIO-specific kernel section.
49 */ 61 */
50#define DECLARE_RIO_ROUTE_OPS(vid, did, add_hook, get_hook) \ 62#define DECLARE_RIO_SWITCH_INIT(vid, did, init_hook) \
51 DECLARE_RIO_ROUTE_SECTION(.rio_route_ops, \ 63 DECLARE_RIO_SWITCH_SECTION(.rio_switch_ops, vid##did, \
52 vid, did, add_hook, get_hook) 64 vid, did, init_hook)
53 65
54#define RIO_GET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x00ff0000) >> 16)) 66#define RIO_GET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x00ff0000) >> 16))
55#define RIO_SET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x000000ff) << 16)) 67#define RIO_SET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x000000ff) << 16))
diff --git a/drivers/rapidio/switches/Kconfig b/drivers/rapidio/switches/Kconfig
new file mode 100644
index 000000000000..2b4e9b2b6631
--- /dev/null
+++ b/drivers/rapidio/switches/Kconfig
@@ -0,0 +1,28 @@
1#
2# RapidIO switches configuration
3#
4config RAPIDIO_TSI57X
5 bool "IDT Tsi57x SRIO switches support"
6 depends on RAPIDIO
7 ---help---
8 Includes support for IDT Tsi57x family of serial RapidIO switches.
9
10config RAPIDIO_CPS_XX
11 bool "IDT CPS-xx SRIO switches support"
12 depends on RAPIDIO
13 ---help---
14 Includes support for IDT CPS-16/12/10/8 serial RapidIO switches.
15
16config RAPIDIO_TSI568
17 bool "Tsi568 SRIO switch support"
18 depends on RAPIDIO
19 default n
20 ---help---
21 Includes support for IDT Tsi568 serial RapidIO switch.
22
23config RAPIDIO_TSI500
24 bool "Tsi500 Parallel RapidIO switch support"
25 depends on RAPIDIO
26 default n
27 ---help---
28 Includes support for IDT Tsi500 parallel RapidIO switch.
diff --git a/drivers/rapidio/switches/Makefile b/drivers/rapidio/switches/Makefile
index b924f8301761..fe4adc3e8d5f 100644
--- a/drivers/rapidio/switches/Makefile
+++ b/drivers/rapidio/switches/Makefile
@@ -2,4 +2,11 @@
2# Makefile for RIO switches 2# Makefile for RIO switches
3# 3#
4 4
5obj-$(CONFIG_RAPIDIO) += tsi500.o 5obj-$(CONFIG_RAPIDIO_TSI57X) += tsi57x.o
6obj-$(CONFIG_RAPIDIO_CPS_XX) += idtcps.o
7obj-$(CONFIG_RAPIDIO_TSI568) += tsi568.o
8obj-$(CONFIG_RAPIDIO_TSI500) += tsi500.o
9
10ifeq ($(CONFIG_RAPIDIO_DEBUG),y)
11EXTRA_CFLAGS += -DDEBUG
12endif
diff --git a/drivers/rapidio/switches/idtcps.c b/drivers/rapidio/switches/idtcps.c
new file mode 100644
index 000000000000..2c790c144f89
--- /dev/null
+++ b/drivers/rapidio/switches/idtcps.c
@@ -0,0 +1,137 @@
1/*
2 * IDT CPS RapidIO switches support
3 *
4 * Copyright 2009-2010 Integrated Device Technology, Inc.
5 * Alexandre Bounine <alexandre.bounine@idt.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#include <linux/rio.h>
14#include <linux/rio_drv.h>
15#include <linux/rio_ids.h>
16#include "../rio.h"
17
18#define CPS_DEFAULT_ROUTE 0xde
19#define CPS_NO_ROUTE 0xdf
20
21#define IDTCPS_RIO_DOMAIN 0xf20020
22
23static int
24idtcps_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
25 u16 table, u16 route_destid, u8 route_port)
26{
27 u32 result;
28
29 if (table == RIO_GLOBAL_TABLE) {
30 rio_mport_write_config_32(mport, destid, hopcount,
31 RIO_STD_RTE_CONF_DESTID_SEL_CSR, route_destid);
32
33 rio_mport_read_config_32(mport, destid, hopcount,
34 RIO_STD_RTE_CONF_PORT_SEL_CSR, &result);
35
36 result = (0xffffff00 & result) | (u32)route_port;
37 rio_mport_write_config_32(mport, destid, hopcount,
38 RIO_STD_RTE_CONF_PORT_SEL_CSR, result);
39 }
40
41 return 0;
42}
43
44static int
45idtcps_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
46 u16 table, u16 route_destid, u8 *route_port)
47{
48 u32 result;
49
50 if (table == RIO_GLOBAL_TABLE) {
51 rio_mport_write_config_32(mport, destid, hopcount,
52 RIO_STD_RTE_CONF_DESTID_SEL_CSR, route_destid);
53
54 rio_mport_read_config_32(mport, destid, hopcount,
55 RIO_STD_RTE_CONF_PORT_SEL_CSR, &result);
56
57 if (CPS_DEFAULT_ROUTE == (u8)result ||
58 CPS_NO_ROUTE == (u8)result)
59 *route_port = RIO_INVALID_ROUTE;
60 else
61 *route_port = (u8)result;
62 }
63
64 return 0;
65}
66
67static int
68idtcps_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount,
69 u16 table)
70{
71 u32 i;
72
73 if (table == RIO_GLOBAL_TABLE) {
74 for (i = 0x80000000; i <= 0x800000ff;) {
75 rio_mport_write_config_32(mport, destid, hopcount,
76 RIO_STD_RTE_CONF_DESTID_SEL_CSR, i);
77 rio_mport_write_config_32(mport, destid, hopcount,
78 RIO_STD_RTE_CONF_PORT_SEL_CSR,
79 (CPS_DEFAULT_ROUTE << 24) |
80 (CPS_DEFAULT_ROUTE << 16) |
81 (CPS_DEFAULT_ROUTE << 8) | CPS_DEFAULT_ROUTE);
82 i += 4;
83 }
84 }
85
86 return 0;
87}
88
89static int
90idtcps_set_domain(struct rio_mport *mport, u16 destid, u8 hopcount,
91 u8 sw_domain)
92{
93 /*
94 * Switch domain configuration operates only at global level
95 */
96 rio_mport_write_config_32(mport, destid, hopcount,
97 IDTCPS_RIO_DOMAIN, (u32)sw_domain);
98 return 0;
99}
100
101static int
102idtcps_get_domain(struct rio_mport *mport, u16 destid, u8 hopcount,
103 u8 *sw_domain)
104{
105 u32 regval;
106
107 /*
108 * Switch domain configuration operates only at global level
109 */
110 rio_mport_read_config_32(mport, destid, hopcount,
111 IDTCPS_RIO_DOMAIN, &regval);
112
113 *sw_domain = (u8)(regval & 0xff);
114
115 return 0;
116}
117
118static int idtcps_switch_init(struct rio_dev *rdev, int do_enum)
119{
120 pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev));
121 rdev->rswitch->add_entry = idtcps_route_add_entry;
122 rdev->rswitch->get_entry = idtcps_route_get_entry;
123 rdev->rswitch->clr_table = idtcps_route_clr_table;
124 rdev->rswitch->set_domain = idtcps_set_domain;
125 rdev->rswitch->get_domain = idtcps_get_domain;
126 rdev->rswitch->em_init = NULL;
127 rdev->rswitch->em_handle = NULL;
128
129 return 0;
130}
131
132DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS6Q, idtcps_switch_init);
133DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS8, idtcps_switch_init);
134DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS10Q, idtcps_switch_init);
135DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS12, idtcps_switch_init);
136DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS16, idtcps_switch_init);
137DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDT70K200, idtcps_switch_init);
diff --git a/drivers/rapidio/switches/tsi500.c b/drivers/rapidio/switches/tsi500.c
index c77c23bd9840..914eddd5aa42 100644
--- a/drivers/rapidio/switches/tsi500.c
+++ b/drivers/rapidio/switches/tsi500.c
@@ -1,6 +1,10 @@
1/* 1/*
2 * RapidIO Tsi500 switch support 2 * RapidIO Tsi500 switch support
3 * 3 *
4 * Copyright 2009-2010 Integrated Device Technology, Inc.
5 * Alexandre Bounine <alexandre.bounine@idt.com>
6 * - Modified switch operations initialization.
7 *
4 * Copyright 2005 MontaVista Software, Inc. 8 * Copyright 2005 MontaVista Software, Inc.
5 * Matt Porter <mporter@kernel.crashing.org> 9 * Matt Porter <mporter@kernel.crashing.org>
6 * 10 *
@@ -57,4 +61,18 @@ tsi500_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount, u16 tab
57 return ret; 61 return ret;
58} 62}
59 63
60DECLARE_RIO_ROUTE_OPS(RIO_VID_TUNDRA, RIO_DID_TSI500, tsi500_route_add_entry, tsi500_route_get_entry); 64static int tsi500_switch_init(struct rio_dev *rdev, int do_enum)
65{
66 pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev));
67 rdev->rswitch->add_entry = tsi500_route_add_entry;
68 rdev->rswitch->get_entry = tsi500_route_get_entry;
69 rdev->rswitch->clr_table = NULL;
70 rdev->rswitch->set_domain = NULL;
71 rdev->rswitch->get_domain = NULL;
72 rdev->rswitch->em_init = NULL;
73 rdev->rswitch->em_handle = NULL;
74
75 return 0;
76}
77
78DECLARE_RIO_SWITCH_INIT(RIO_VID_TUNDRA, RIO_DID_TSI500, tsi500_switch_init);
diff --git a/drivers/rapidio/switches/tsi568.c b/drivers/rapidio/switches/tsi568.c
new file mode 100644
index 000000000000..f7fd7898606e
--- /dev/null
+++ b/drivers/rapidio/switches/tsi568.c
@@ -0,0 +1,146 @@
1/*
2 * RapidIO Tsi568 switch support
3 *
4 * Copyright 2009-2010 Integrated Device Technology, Inc.
5 * Alexandre Bounine <alexandre.bounine@idt.com>
6 * - Added EM support
7 * - Modified switch operations initialization.
8 *
9 * Copyright 2005 MontaVista Software, Inc.
10 * Matt Porter <mporter@kernel.crashing.org>
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version.
16 */
17
18#include <linux/rio.h>
19#include <linux/rio_drv.h>
20#include <linux/rio_ids.h>
21#include <linux/delay.h>
22#include "../rio.h"
23
24/* Global (broadcast) route registers */
25#define SPBC_ROUTE_CFG_DESTID 0x10070
26#define SPBC_ROUTE_CFG_PORT 0x10074
27
28/* Per port route registers */
29#define SPP_ROUTE_CFG_DESTID(n) (0x11070 + 0x100*n)
30#define SPP_ROUTE_CFG_PORT(n) (0x11074 + 0x100*n)
31
32#define TSI568_SP_MODE_BC 0x10004
33#define TSI568_SP_MODE_PW_DIS 0x08000000
34
35static int
36tsi568_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
37 u16 table, u16 route_destid, u8 route_port)
38{
39 if (table == RIO_GLOBAL_TABLE) {
40 rio_mport_write_config_32(mport, destid, hopcount,
41 SPBC_ROUTE_CFG_DESTID, route_destid);
42 rio_mport_write_config_32(mport, destid, hopcount,
43 SPBC_ROUTE_CFG_PORT, route_port);
44 } else {
45 rio_mport_write_config_32(mport, destid, hopcount,
46 SPP_ROUTE_CFG_DESTID(table),
47 route_destid);
48 rio_mport_write_config_32(mport, destid, hopcount,
49 SPP_ROUTE_CFG_PORT(table), route_port);
50 }
51
52 udelay(10);
53
54 return 0;
55}
56
57static int
58tsi568_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
59 u16 table, u16 route_destid, u8 *route_port)
60{
61 int ret = 0;
62 u32 result;
63
64 if (table == RIO_GLOBAL_TABLE) {
65 rio_mport_write_config_32(mport, destid, hopcount,
66 SPBC_ROUTE_CFG_DESTID, route_destid);
67 rio_mport_read_config_32(mport, destid, hopcount,
68 SPBC_ROUTE_CFG_PORT, &result);
69 } else {
70 rio_mport_write_config_32(mport, destid, hopcount,
71 SPP_ROUTE_CFG_DESTID(table),
72 route_destid);
73 rio_mport_read_config_32(mport, destid, hopcount,
74 SPP_ROUTE_CFG_PORT(table), &result);
75 }
76
77 *route_port = result;
78 if (*route_port > 15)
79 ret = -1;
80
81 return ret;
82}
83
84static int
85tsi568_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount,
86 u16 table)
87{
88 u32 route_idx;
89 u32 lut_size;
90
91 lut_size = (mport->sys_size) ? 0x1ff : 0xff;
92
93 if (table == RIO_GLOBAL_TABLE) {
94 rio_mport_write_config_32(mport, destid, hopcount,
95 SPBC_ROUTE_CFG_DESTID, 0x80000000);
96 for (route_idx = 0; route_idx <= lut_size; route_idx++)
97 rio_mport_write_config_32(mport, destid, hopcount,
98 SPBC_ROUTE_CFG_PORT,
99 RIO_INVALID_ROUTE);
100 } else {
101 rio_mport_write_config_32(mport, destid, hopcount,
102 SPP_ROUTE_CFG_DESTID(table),
103 0x80000000);
104 for (route_idx = 0; route_idx <= lut_size; route_idx++)
105 rio_mport_write_config_32(mport, destid, hopcount,
106 SPP_ROUTE_CFG_PORT(table),
107 RIO_INVALID_ROUTE);
108 }
109
110 return 0;
111}
112
113static int
114tsi568_em_init(struct rio_dev *rdev)
115{
116 struct rio_mport *mport = rdev->net->hport;
117 u16 destid = rdev->rswitch->destid;
118 u8 hopcount = rdev->rswitch->hopcount;
119 u32 regval;
120
121 pr_debug("TSI568 %s [%d:%d]\n", __func__, destid, hopcount);
122
123 /* Make sure that Port-Writes are disabled (for all ports) */
124 rio_mport_read_config_32(mport, destid, hopcount,
125 TSI568_SP_MODE_BC, &regval);
126 rio_mport_write_config_32(mport, destid, hopcount,
127 TSI568_SP_MODE_BC, regval | TSI568_SP_MODE_PW_DIS);
128
129 return 0;
130}
131
132static int tsi568_switch_init(struct rio_dev *rdev, int do_enum)
133{
134 pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev));
135 rdev->rswitch->add_entry = tsi568_route_add_entry;
136 rdev->rswitch->get_entry = tsi568_route_get_entry;
137 rdev->rswitch->clr_table = tsi568_route_clr_table;
138 rdev->rswitch->set_domain = NULL;
139 rdev->rswitch->get_domain = NULL;
140 rdev->rswitch->em_init = tsi568_em_init;
141 rdev->rswitch->em_handle = NULL;
142
143 return 0;
144}
145
146DECLARE_RIO_SWITCH_INIT(RIO_VID_TUNDRA, RIO_DID_TSI568, tsi568_switch_init);
diff --git a/drivers/rapidio/switches/tsi57x.c b/drivers/rapidio/switches/tsi57x.c
new file mode 100644
index 000000000000..d34df722d95f
--- /dev/null
+++ b/drivers/rapidio/switches/tsi57x.c
@@ -0,0 +1,315 @@
1/*
2 * RapidIO Tsi57x switch family support
3 *
4 * Copyright 2009-2010 Integrated Device Technology, Inc.
5 * Alexandre Bounine <alexandre.bounine@idt.com>
6 * - Added EM support
7 * - Modified switch operations initialization.
8 *
9 * Copyright 2005 MontaVista Software, Inc.
10 * Matt Porter <mporter@kernel.crashing.org>
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version.
16 */
17
18#include <linux/rio.h>
19#include <linux/rio_drv.h>
20#include <linux/rio_ids.h>
21#include <linux/delay.h>
22#include "../rio.h"
23
24/* Global (broadcast) route registers */
25#define SPBC_ROUTE_CFG_DESTID 0x10070
26#define SPBC_ROUTE_CFG_PORT 0x10074
27
28/* Per port route registers */
29#define SPP_ROUTE_CFG_DESTID(n) (0x11070 + 0x100*n)
30#define SPP_ROUTE_CFG_PORT(n) (0x11074 + 0x100*n)
31
32#define TSI578_SP_MODE(n) (0x11004 + n*0x100)
33#define TSI578_SP_MODE_GLBL 0x10004
34#define TSI578_SP_MODE_PW_DIS 0x08000000
35#define TSI578_SP_MODE_LUT_512 0x01000000
36
37#define TSI578_SP_CTL_INDEP(n) (0x13004 + n*0x100)
38#define TSI578_SP_LUT_PEINF(n) (0x13010 + n*0x100)
39#define TSI578_SP_CS_TX(n) (0x13014 + n*0x100)
40#define TSI578_SP_INT_STATUS(n) (0x13018 + n*0x100)
41
42#define TSI578_GLBL_ROUTE_BASE 0x10078
43
44static int
45tsi57x_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
46 u16 table, u16 route_destid, u8 route_port)
47{
48 if (table == RIO_GLOBAL_TABLE) {
49 rio_mport_write_config_32(mport, destid, hopcount,
50 SPBC_ROUTE_CFG_DESTID, route_destid);
51 rio_mport_write_config_32(mport, destid, hopcount,
52 SPBC_ROUTE_CFG_PORT, route_port);
53 } else {
54 rio_mport_write_config_32(mport, destid, hopcount,
55 SPP_ROUTE_CFG_DESTID(table), route_destid);
56 rio_mport_write_config_32(mport, destid, hopcount,
57 SPP_ROUTE_CFG_PORT(table), route_port);
58 }
59
60 udelay(10);
61
62 return 0;
63}
64
65static int
66tsi57x_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
67 u16 table, u16 route_destid, u8 *route_port)
68{
69 int ret = 0;
70 u32 result;
71
72 if (table == RIO_GLOBAL_TABLE) {
73 /* Use local RT of the ingress port to avoid possible
74 race condition */
75 rio_mport_read_config_32(mport, destid, hopcount,
76 RIO_SWP_INFO_CAR, &result);
77 table = (result & RIO_SWP_INFO_PORT_NUM_MASK);
78 }
79
80 rio_mport_write_config_32(mport, destid, hopcount,
81 SPP_ROUTE_CFG_DESTID(table), route_destid);
82 rio_mport_read_config_32(mport, destid, hopcount,
83 SPP_ROUTE_CFG_PORT(table), &result);
84
85 *route_port = (u8)result;
86 if (*route_port > 15)
87 ret = -1;
88
89 return ret;
90}
91
92static int
93tsi57x_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount,
94 u16 table)
95{
96 u32 route_idx;
97 u32 lut_size;
98
99 lut_size = (mport->sys_size) ? 0x1ff : 0xff;
100
101 if (table == RIO_GLOBAL_TABLE) {
102 rio_mport_write_config_32(mport, destid, hopcount,
103 SPBC_ROUTE_CFG_DESTID, 0x80000000);
104 for (route_idx = 0; route_idx <= lut_size; route_idx++)
105 rio_mport_write_config_32(mport, destid, hopcount,
106 SPBC_ROUTE_CFG_PORT,
107 RIO_INVALID_ROUTE);
108 } else {
109 rio_mport_write_config_32(mport, destid, hopcount,
110 SPP_ROUTE_CFG_DESTID(table), 0x80000000);
111 for (route_idx = 0; route_idx <= lut_size; route_idx++)
112 rio_mport_write_config_32(mport, destid, hopcount,
113 SPP_ROUTE_CFG_PORT(table) , RIO_INVALID_ROUTE);
114 }
115
116 return 0;
117}
118
119static int
120tsi57x_set_domain(struct rio_mport *mport, u16 destid, u8 hopcount,
121 u8 sw_domain)
122{
123 u32 regval;
124
125 /*
126 * Switch domain configuration operates only at global level
127 */
128
129 /* Turn off flat (LUT_512) mode */
130 rio_mport_read_config_32(mport, destid, hopcount,
131 TSI578_SP_MODE_GLBL, &regval);
132 rio_mport_write_config_32(mport, destid, hopcount, TSI578_SP_MODE_GLBL,
133 regval & ~TSI578_SP_MODE_LUT_512);
134 /* Set switch domain base */
135 rio_mport_write_config_32(mport, destid, hopcount,
136 TSI578_GLBL_ROUTE_BASE,
137 (u32)(sw_domain << 24));
138 return 0;
139}
140
141static int
142tsi57x_get_domain(struct rio_mport *mport, u16 destid, u8 hopcount,
143 u8 *sw_domain)
144{
145 u32 regval;
146
147 /*
148 * Switch domain configuration operates only at global level
149 */
150 rio_mport_read_config_32(mport, destid, hopcount,
151 TSI578_GLBL_ROUTE_BASE, &regval);
152
153 *sw_domain = (u8)(regval >> 24);
154
155 return 0;
156}
157
158static int
159tsi57x_em_init(struct rio_dev *rdev)
160{
161 struct rio_mport *mport = rdev->net->hport;
162 u16 destid = rdev->rswitch->destid;
163 u8 hopcount = rdev->rswitch->hopcount;
164 u32 regval;
165 int portnum;
166
167 pr_debug("TSI578 %s [%d:%d]\n", __func__, destid, hopcount);
168
169 for (portnum = 0; portnum < 16; portnum++) {
170 /* Make sure that Port-Writes are enabled (for all ports) */
171 rio_mport_read_config_32(mport, destid, hopcount,
172 TSI578_SP_MODE(portnum), &regval);
173 rio_mport_write_config_32(mport, destid, hopcount,
174 TSI578_SP_MODE(portnum),
175 regval & ~TSI578_SP_MODE_PW_DIS);
176
177 /* Clear all pending interrupts */
178 rio_mport_read_config_32(mport, destid, hopcount,
179 rdev->phys_efptr +
180 RIO_PORT_N_ERR_STS_CSR(portnum),
181 &regval);
182 rio_mport_write_config_32(mport, destid, hopcount,
183 rdev->phys_efptr +
184 RIO_PORT_N_ERR_STS_CSR(portnum),
185 regval & 0x07120214);
186
187 rio_mport_read_config_32(mport, destid, hopcount,
188 TSI578_SP_INT_STATUS(portnum), &regval);
189 rio_mport_write_config_32(mport, destid, hopcount,
190 TSI578_SP_INT_STATUS(portnum),
191 regval & 0x000700bd);
192
193 /* Enable all interrupts to allow ports to send a port-write */
194 rio_mport_read_config_32(mport, destid, hopcount,
195 TSI578_SP_CTL_INDEP(portnum), &regval);
196 rio_mport_write_config_32(mport, destid, hopcount,
197 TSI578_SP_CTL_INDEP(portnum),
198 regval | 0x000b0000);
199
200 /* Skip next (odd) port if the current port is in x4 mode */
201 rio_mport_read_config_32(mport, destid, hopcount,
202 rdev->phys_efptr + RIO_PORT_N_CTL_CSR(portnum),
203 &regval);
204 if ((regval & RIO_PORT_N_CTL_PWIDTH) == RIO_PORT_N_CTL_PWIDTH_4)
205 portnum++;
206 }
207
208 return 0;
209}
210
211static int
212tsi57x_em_handler(struct rio_dev *rdev, u8 portnum)
213{
214 struct rio_mport *mport = rdev->net->hport;
215 u16 destid = rdev->rswitch->destid;
216 u8 hopcount = rdev->rswitch->hopcount;
217 u32 intstat, err_status;
218 int sendcount, checkcount;
219 u8 route_port;
220 u32 regval;
221
222 rio_mport_read_config_32(mport, destid, hopcount,
223 rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum),
224 &err_status);
225
226 if ((err_status & RIO_PORT_N_ERR_STS_PORT_OK) &&
227 (err_status & (RIO_PORT_N_ERR_STS_PW_OUT_ES |
228 RIO_PORT_N_ERR_STS_PW_INP_ES))) {
229 /* Remove any queued packets by locking/unlocking port */
230 rio_mport_read_config_32(mport, destid, hopcount,
231 rdev->phys_efptr + RIO_PORT_N_CTL_CSR(portnum),
232 &regval);
233 if (!(regval & RIO_PORT_N_CTL_LOCKOUT)) {
234 rio_mport_write_config_32(mport, destid, hopcount,
235 rdev->phys_efptr + RIO_PORT_N_CTL_CSR(portnum),
236 regval | RIO_PORT_N_CTL_LOCKOUT);
237 udelay(50);
238 rio_mport_write_config_32(mport, destid, hopcount,
239 rdev->phys_efptr + RIO_PORT_N_CTL_CSR(portnum),
240 regval);
241 }
242
243 /* Read from link maintenance response register to clear
244 * valid bit
245 */
246 rio_mport_read_config_32(mport, destid, hopcount,
247 rdev->phys_efptr + RIO_PORT_N_MNT_RSP_CSR(portnum),
248 &regval);
249
250 /* Send a Packet-Not-Accepted/Link-Request-Input-Status control
251 * symbol to recover from IES/OES
252 */
253 sendcount = 3;
254 while (sendcount) {
255 rio_mport_write_config_32(mport, destid, hopcount,
256 TSI578_SP_CS_TX(portnum), 0x40fc8000);
257 checkcount = 3;
258 while (checkcount--) {
259 udelay(50);
260 rio_mport_read_config_32(
261 mport, destid, hopcount,
262 rdev->phys_efptr +
263 RIO_PORT_N_MNT_RSP_CSR(portnum),
264 &regval);
265 if (regval & RIO_PORT_N_MNT_RSP_RVAL)
266 goto exit_es;
267 }
268
269 sendcount--;
270 }
271 }
272
273exit_es:
274 /* Clear implementation specific error status bits */
275 rio_mport_read_config_32(mport, destid, hopcount,
276 TSI578_SP_INT_STATUS(portnum), &intstat);
277 pr_debug("TSI578[%x:%x] SP%d_INT_STATUS=0x%08x\n",
278 destid, hopcount, portnum, intstat);
279
280 if (intstat & 0x10000) {
281 rio_mport_read_config_32(mport, destid, hopcount,
282 TSI578_SP_LUT_PEINF(portnum), &regval);
283 regval = (mport->sys_size) ? (regval >> 16) : (regval >> 24);
284 route_port = rdev->rswitch->route_table[regval];
285 pr_debug("RIO: TSI578[%s] P%d LUT Parity Error (destID=%d)\n",
286 rio_name(rdev), portnum, regval);
287 tsi57x_route_add_entry(mport, destid, hopcount,
288 RIO_GLOBAL_TABLE, regval, route_port);
289 }
290
291 rio_mport_write_config_32(mport, destid, hopcount,
292 TSI578_SP_INT_STATUS(portnum),
293 intstat & 0x000700bd);
294
295 return 0;
296}
297
298static int tsi57x_switch_init(struct rio_dev *rdev, int do_enum)
299{
300 pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev));
301 rdev->rswitch->add_entry = tsi57x_route_add_entry;
302 rdev->rswitch->get_entry = tsi57x_route_get_entry;
303 rdev->rswitch->clr_table = tsi57x_route_clr_table;
304 rdev->rswitch->set_domain = tsi57x_set_domain;
305 rdev->rswitch->get_domain = tsi57x_get_domain;
306 rdev->rswitch->em_init = tsi57x_em_init;
307 rdev->rswitch->em_handle = tsi57x_em_handler;
308
309 return 0;
310}
311
312DECLARE_RIO_SWITCH_INIT(RIO_VID_TUNDRA, RIO_DID_TSI572, tsi57x_switch_init);
313DECLARE_RIO_SWITCH_INIT(RIO_VID_TUNDRA, RIO_DID_TSI574, tsi57x_switch_init);
314DECLARE_RIO_SWITCH_INIT(RIO_VID_TUNDRA, RIO_DID_TSI577, tsi57x_switch_init);
315DECLARE_RIO_SWITCH_INIT(RIO_VID_TUNDRA, RIO_DID_TSI578, tsi57x_switch_init);
diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c
index 1afd008ca957..7b14a67bdca2 100644
--- a/drivers/regulator/ab3100.c
+++ b/drivers/regulator/ab3100.c
@@ -16,7 +16,7 @@
16#include <linux/delay.h> 16#include <linux/delay.h>
17#include <linux/platform_device.h> 17#include <linux/platform_device.h>
18#include <linux/regulator/driver.h> 18#include <linux/regulator/driver.h>
19#include <linux/mfd/ab3100.h> 19#include <linux/mfd/abx500.h>
20 20
21/* LDO registers and some handy masking definitions for AB3100 */ 21/* LDO registers and some handy masking definitions for AB3100 */
22#define AB3100_LDO_A 0x40 22#define AB3100_LDO_A 0x40
@@ -41,7 +41,7 @@
41 * struct ab3100_regulator 41 * struct ab3100_regulator
42 * A struct passed around the individual regulator functions 42 * A struct passed around the individual regulator functions
43 * @platform_device: platform device holding this regulator 43 * @platform_device: platform device holding this regulator
44 * @ab3100: handle to the AB3100 parent chip 44 * @dev: handle to the device
45 * @plfdata: AB3100 platform data passed in at probe time 45 * @plfdata: AB3100 platform data passed in at probe time
46 * @regreg: regulator register number in the AB3100 46 * @regreg: regulator register number in the AB3100
47 * @fixed_voltage: a fixed voltage for this regulator, if this 47 * @fixed_voltage: a fixed voltage for this regulator, if this
@@ -52,7 +52,7 @@
52 */ 52 */
53struct ab3100_regulator { 53struct ab3100_regulator {
54 struct regulator_dev *rdev; 54 struct regulator_dev *rdev;
55 struct ab3100 *ab3100; 55 struct device *dev;
56 struct ab3100_platform_data *plfdata; 56 struct ab3100_platform_data *plfdata;
57 u8 regreg; 57 u8 regreg;
58 int fixed_voltage; 58 int fixed_voltage;
@@ -183,7 +183,7 @@ static int ab3100_enable_regulator(struct regulator_dev *reg)
183 int err; 183 int err;
184 u8 regval; 184 u8 regval;
185 185
186 err = ab3100_get_register_interruptible(abreg->ab3100, abreg->regreg, 186 err = abx500_get_register_interruptible(abreg->dev, 0, abreg->regreg,
187 &regval); 187 &regval);
188 if (err) { 188 if (err) {
189 dev_warn(&reg->dev, "failed to get regid %d value\n", 189 dev_warn(&reg->dev, "failed to get regid %d value\n",
@@ -197,7 +197,7 @@ static int ab3100_enable_regulator(struct regulator_dev *reg)
197 197
198 regval |= AB3100_REG_ON_MASK; 198 regval |= AB3100_REG_ON_MASK;
199 199
200 err = ab3100_set_register_interruptible(abreg->ab3100, abreg->regreg, 200 err = abx500_set_register_interruptible(abreg->dev, 0, abreg->regreg,
201 regval); 201 regval);
202 if (err) { 202 if (err) {
203 dev_warn(&reg->dev, "failed to set regid %d value\n", 203 dev_warn(&reg->dev, "failed to set regid %d value\n",
@@ -245,14 +245,14 @@ static int ab3100_disable_regulator(struct regulator_dev *reg)
245 if (abreg->regreg == AB3100_LDO_D) { 245 if (abreg->regreg == AB3100_LDO_D) {
246 dev_info(&reg->dev, "disabling LDO D - shut down system\n"); 246 dev_info(&reg->dev, "disabling LDO D - shut down system\n");
247 /* Setting LDO D to 0x00 cuts the power to the SoC */ 247 /* Setting LDO D to 0x00 cuts the power to the SoC */
248 return ab3100_set_register_interruptible(abreg->ab3100, 248 return abx500_set_register_interruptible(abreg->dev, 0,
249 AB3100_LDO_D, 0x00U); 249 AB3100_LDO_D, 0x00U);
250 } 250 }
251 251
252 /* 252 /*
253 * All other regulators are handled here 253 * All other regulators are handled here
254 */ 254 */
255 err = ab3100_get_register_interruptible(abreg->ab3100, abreg->regreg, 255 err = abx500_get_register_interruptible(abreg->dev, 0, abreg->regreg,
256 &regval); 256 &regval);
257 if (err) { 257 if (err) {
258 dev_err(&reg->dev, "unable to get register 0x%x\n", 258 dev_err(&reg->dev, "unable to get register 0x%x\n",
@@ -260,7 +260,7 @@ static int ab3100_disable_regulator(struct regulator_dev *reg)
260 return err; 260 return err;
261 } 261 }
262 regval &= ~AB3100_REG_ON_MASK; 262 regval &= ~AB3100_REG_ON_MASK;
263 return ab3100_set_register_interruptible(abreg->ab3100, abreg->regreg, 263 return abx500_set_register_interruptible(abreg->dev, 0, abreg->regreg,
264 regval); 264 regval);
265} 265}
266 266
@@ -270,7 +270,7 @@ static int ab3100_is_enabled_regulator(struct regulator_dev *reg)
270 u8 regval; 270 u8 regval;
271 int err; 271 int err;
272 272
273 err = ab3100_get_register_interruptible(abreg->ab3100, abreg->regreg, 273 err = abx500_get_register_interruptible(abreg->dev, 0, abreg->regreg,
274 &regval); 274 &regval);
275 if (err) { 275 if (err) {
276 dev_err(&reg->dev, "unable to get register 0x%x\n", 276 dev_err(&reg->dev, "unable to get register 0x%x\n",
@@ -305,7 +305,7 @@ static int ab3100_get_voltage_regulator(struct regulator_dev *reg)
305 * For variable types, read out setting and index into 305 * For variable types, read out setting and index into
306 * supplied voltage list. 306 * supplied voltage list.
307 */ 307 */
308 err = ab3100_get_register_interruptible(abreg->ab3100, 308 err = abx500_get_register_interruptible(abreg->dev, 0,
309 abreg->regreg, &regval); 309 abreg->regreg, &regval);
310 if (err) { 310 if (err) {
311 dev_warn(&reg->dev, 311 dev_warn(&reg->dev,
@@ -373,7 +373,7 @@ static int ab3100_set_voltage_regulator(struct regulator_dev *reg,
373 if (bestindex < 0) 373 if (bestindex < 0)
374 return bestindex; 374 return bestindex;
375 375
376 err = ab3100_get_register_interruptible(abreg->ab3100, 376 err = abx500_get_register_interruptible(abreg->dev, 0,
377 abreg->regreg, &regval); 377 abreg->regreg, &regval);
378 if (err) { 378 if (err) {
379 dev_warn(&reg->dev, 379 dev_warn(&reg->dev,
@@ -386,7 +386,7 @@ static int ab3100_set_voltage_regulator(struct regulator_dev *reg,
386 regval &= ~0xE0; 386 regval &= ~0xE0;
387 regval |= (bestindex << 5); 387 regval |= (bestindex << 5);
388 388
389 err = ab3100_set_register_interruptible(abreg->ab3100, 389 err = abx500_set_register_interruptible(abreg->dev, 0,
390 abreg->regreg, regval); 390 abreg->regreg, regval);
391 if (err) 391 if (err)
392 dev_warn(&reg->dev, "failed to set regulator register %02x\n", 392 dev_warn(&reg->dev, "failed to set regulator register %02x\n",
@@ -414,7 +414,7 @@ static int ab3100_set_suspend_voltage_regulator(struct regulator_dev *reg,
414 /* LDO E and BUCK have special suspend voltages you can set */ 414 /* LDO E and BUCK have special suspend voltages you can set */
415 bestindex = ab3100_get_best_voltage_index(reg, uV, uV); 415 bestindex = ab3100_get_best_voltage_index(reg, uV, uV);
416 416
417 err = ab3100_get_register_interruptible(abreg->ab3100, 417 err = abx500_get_register_interruptible(abreg->dev, 0,
418 targetreg, &regval); 418 targetreg, &regval);
419 if (err) { 419 if (err) {
420 dev_warn(&reg->dev, 420 dev_warn(&reg->dev,
@@ -427,7 +427,7 @@ static int ab3100_set_suspend_voltage_regulator(struct regulator_dev *reg,
427 regval &= ~0xE0; 427 regval &= ~0xE0;
428 regval |= (bestindex << 5); 428 regval |= (bestindex << 5);
429 429
430 err = ab3100_set_register_interruptible(abreg->ab3100, 430 err = abx500_set_register_interruptible(abreg->dev, 0,
431 targetreg, regval); 431 targetreg, regval);
432 if (err) 432 if (err)
433 dev_warn(&reg->dev, "failed to set regulator register %02x\n", 433 dev_warn(&reg->dev, "failed to set regulator register %02x\n",
@@ -574,13 +574,12 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = {
574static int __devinit ab3100_regulators_probe(struct platform_device *pdev) 574static int __devinit ab3100_regulators_probe(struct platform_device *pdev)
575{ 575{
576 struct ab3100_platform_data *plfdata = pdev->dev.platform_data; 576 struct ab3100_platform_data *plfdata = pdev->dev.platform_data;
577 struct ab3100 *ab3100 = platform_get_drvdata(pdev);
578 int err = 0; 577 int err = 0;
579 u8 data; 578 u8 data;
580 int i; 579 int i;
581 580
582 /* Check chip state */ 581 /* Check chip state */
583 err = ab3100_get_register_interruptible(ab3100, 582 err = abx500_get_register_interruptible(&pdev->dev, 0,
584 AB3100_LDO_D, &data); 583 AB3100_LDO_D, &data);
585 if (err) { 584 if (err) {
586 dev_err(&pdev->dev, "could not read initial status of LDO_D\n"); 585 dev_err(&pdev->dev, "could not read initial status of LDO_D\n");
@@ -595,7 +594,7 @@ static int __devinit ab3100_regulators_probe(struct platform_device *pdev)
595 594
596 /* Set up regulators */ 595 /* Set up regulators */
597 for (i = 0; i < ARRAY_SIZE(ab3100_reg_init_order); i++) { 596 for (i = 0; i < ARRAY_SIZE(ab3100_reg_init_order); i++) {
598 err = ab3100_set_register_interruptible(ab3100, 597 err = abx500_set_register_interruptible(&pdev->dev, 0,
599 ab3100_reg_init_order[i], 598 ab3100_reg_init_order[i],
600 plfdata->reg_initvals[i]); 599 plfdata->reg_initvals[i]);
601 if (err) { 600 if (err) {
@@ -617,7 +616,7 @@ static int __devinit ab3100_regulators_probe(struct platform_device *pdev)
617 * see what it looks like for a certain machine, go 616 * see what it looks like for a certain machine, go
618 * into the machine I2C setup. 617 * into the machine I2C setup.
619 */ 618 */
620 reg->ab3100 = ab3100; 619 reg->dev = &pdev->dev;
621 reg->plfdata = plfdata; 620 reg->plfdata = plfdata;
622 621
623 /* 622 /*
diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c
index 671a7d1f1f0e..8ae3732eb24b 100644
--- a/drivers/regulator/lp3971.c
+++ b/drivers/regulator/lp3971.c
@@ -519,8 +519,6 @@ static int __devexit lp3971_i2c_remove(struct i2c_client *i2c)
519 struct lp3971 *lp3971 = i2c_get_clientdata(i2c); 519 struct lp3971 *lp3971 = i2c_get_clientdata(i2c);
520 int i; 520 int i;
521 521
522 i2c_set_clientdata(i2c, NULL);
523
524 for (i = 0; i < lp3971->num_regulators; i++) 522 for (i = 0; i < lp3971->num_regulators; i++)
525 regulator_unregister(lp3971->rdev[i]); 523 regulator_unregister(lp3971->rdev[i]);
526 524
diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c
index b3c1afc16889..2b54d9d75f11 100644
--- a/drivers/regulator/max1586.c
+++ b/drivers/regulator/max1586.c
@@ -244,7 +244,6 @@ static int __devexit max1586_pmic_remove(struct i2c_client *client)
244 for (i = 0; i <= MAX1586_V6; i++) 244 for (i = 0; i <= MAX1586_V6; i++)
245 if (rdev[i]) 245 if (rdev[i])
246 regulator_unregister(rdev[i]); 246 regulator_unregister(rdev[i]);
247 i2c_set_clientdata(client, NULL);
248 kfree(rdev); 247 kfree(rdev);
249 248
250 return 0; 249 return 0;
diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c
index bfc4c5ffdc96..4520ace3f7e7 100644
--- a/drivers/regulator/max8649.c
+++ b/drivers/regulator/max8649.c
@@ -357,7 +357,6 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client,
357 dev_info(info->dev, "Max8649 regulator device is detected.\n"); 357 dev_info(info->dev, "Max8649 regulator device is detected.\n");
358 return 0; 358 return 0;
359out: 359out:
360 i2c_set_clientdata(client, NULL);
361 kfree(info); 360 kfree(info);
362 return ret; 361 return ret;
363} 362}
@@ -369,7 +368,6 @@ static int __devexit max8649_regulator_remove(struct i2c_client *client)
369 if (info) { 368 if (info) {
370 if (info->regulator) 369 if (info->regulator)
371 regulator_unregister(info->regulator); 370 regulator_unregister(info->regulator);
372 i2c_set_clientdata(client, NULL);
373 kfree(info); 371 kfree(info);
374 } 372 }
375 373
diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c
index 3790b21879ff..d97220efae5a 100644
--- a/drivers/regulator/max8660.c
+++ b/drivers/regulator/max8660.c
@@ -471,7 +471,6 @@ static int __devexit max8660_remove(struct i2c_client *client)
471 for (i = 0; i < MAX8660_V_END; i++) 471 for (i = 0; i < MAX8660_V_END; i++)
472 if (rdev[i]) 472 if (rdev[i])
473 regulator_unregister(rdev[i]); 473 regulator_unregister(rdev[i]);
474 i2c_set_clientdata(client, NULL);
475 kfree(rdev); 474 kfree(rdev);
476 475
477 return 0; 476 return 0;
diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c
index 8e2f2098b005..f50afc9f287a 100644
--- a/drivers/regulator/tps65023-regulator.c
+++ b/drivers/regulator/tps65023-regulator.c
@@ -538,9 +538,6 @@ static int __devexit tps_65023_remove(struct i2c_client *client)
538 struct tps_pmic *tps = i2c_get_clientdata(client); 538 struct tps_pmic *tps = i2c_get_clientdata(client);
539 int i; 539 int i;
540 540
541 /* clear the client data in i2c */
542 i2c_set_clientdata(client, NULL);
543
544 for (i = 0; i < TPS65023_NUM_REGULATOR; i++) 541 for (i = 0; i < TPS65023_NUM_REGULATOR; i++)
545 regulator_unregister(tps->rdev[i]); 542 regulator_unregister(tps->rdev[i]);
546 543
diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c
index 74841abcc9cc..14b4576281c5 100644
--- a/drivers/regulator/tps6507x-regulator.c
+++ b/drivers/regulator/tps6507x-regulator.c
@@ -22,68 +22,9 @@
22#include <linux/platform_device.h> 22#include <linux/platform_device.h>
23#include <linux/regulator/driver.h> 23#include <linux/regulator/driver.h>
24#include <linux/regulator/machine.h> 24#include <linux/regulator/machine.h>
25#include <linux/i2c.h>
26#include <linux/delay.h> 25#include <linux/delay.h>
27#include <linux/slab.h> 26#include <linux/slab.h>
28 27#include <linux/mfd/tps6507x.h>
29/* Register definitions */
30#define TPS6507X_REG_PPATH1 0X01
31#define TPS6507X_REG_INT 0X02
32#define TPS6507X_REG_CHGCONFIG0 0X03
33#define TPS6507X_REG_CHGCONFIG1 0X04
34#define TPS6507X_REG_CHGCONFIG2 0X05
35#define TPS6507X_REG_CHGCONFIG3 0X06
36#define TPS6507X_REG_REG_ADCONFIG 0X07
37#define TPS6507X_REG_TSCMODE 0X08
38#define TPS6507X_REG_ADRESULT_1 0X09
39#define TPS6507X_REG_ADRESULT_2 0X0A
40#define TPS6507X_REG_PGOOD 0X0B
41#define TPS6507X_REG_PGOODMASK 0X0C
42#define TPS6507X_REG_CON_CTRL1 0X0D
43#define TPS6507X_REG_CON_CTRL2 0X0E
44#define TPS6507X_REG_CON_CTRL3 0X0F
45#define TPS6507X_REG_DEFDCDC1 0X10
46#define TPS6507X_REG_DEFDCDC2_LOW 0X11
47#define TPS6507X_REG_DEFDCDC2_HIGH 0X12
48#define TPS6507X_REG_DEFDCDC3_LOW 0X13
49#define TPS6507X_REG_DEFDCDC3_HIGH 0X14
50#define TPS6507X_REG_DEFSLEW 0X15
51#define TPS6507X_REG_LDO_CTRL1 0X16
52#define TPS6507X_REG_DEFLDO2 0X17
53#define TPS6507X_REG_WLED_CTRL1 0X18
54#define TPS6507X_REG_WLED_CTRL2 0X19
55
56/* CON_CTRL1 bitfields */
57#define TPS6507X_CON_CTRL1_DCDC1_ENABLE BIT(4)
58#define TPS6507X_CON_CTRL1_DCDC2_ENABLE BIT(3)
59#define TPS6507X_CON_CTRL1_DCDC3_ENABLE BIT(2)
60#define TPS6507X_CON_CTRL1_LDO1_ENABLE BIT(1)
61#define TPS6507X_CON_CTRL1_LDO2_ENABLE BIT(0)
62
63/* DEFDCDC1 bitfields */
64#define TPS6507X_DEFDCDC1_DCDC1_EXT_ADJ_EN BIT(7)
65#define TPS6507X_DEFDCDC1_DCDC1_MASK 0X3F
66
67/* DEFDCDC2_LOW bitfields */
68#define TPS6507X_DEFDCDC2_LOW_DCDC2_MASK 0X3F
69
70/* DEFDCDC2_HIGH bitfields */
71#define TPS6507X_DEFDCDC2_HIGH_DCDC2_MASK 0X3F
72
73/* DEFDCDC3_LOW bitfields */
74#define TPS6507X_DEFDCDC3_LOW_DCDC3_MASK 0X3F
75
76/* DEFDCDC3_HIGH bitfields */
77#define TPS6507X_DEFDCDC3_HIGH_DCDC3_MASK 0X3F
78
79/* TPS6507X_REG_LDO_CTRL1 bitfields */
80#define TPS6507X_REG_LDO_CTRL1_LDO1_MASK 0X0F
81
82/* TPS6507X_REG_DEFLDO2 bitfields */
83#define TPS6507X_REG_DEFLDO2_LDO2_MASK 0X3F
84
85/* VDCDC MASK */
86#define TPS6507X_DEFDCDCX_DCDC_MASK 0X3F
87 28
88/* DCDC's */ 29/* DCDC's */
89#define TPS6507X_DCDC_1 0 30#define TPS6507X_DCDC_1 0
@@ -162,101 +103,146 @@ struct tps_info {
162 const u16 *table; 103 const u16 *table;
163}; 104};
164 105
165struct tps_pmic { 106static const struct tps_info tps6507x_pmic_regs[] = {
107 {
108 .name = "VDCDC1",
109 .min_uV = 725000,
110 .max_uV = 3300000,
111 .table_len = ARRAY_SIZE(VDCDCx_VSEL_table),
112 .table = VDCDCx_VSEL_table,
113 },
114 {
115 .name = "VDCDC2",
116 .min_uV = 725000,
117 .max_uV = 3300000,
118 .table_len = ARRAY_SIZE(VDCDCx_VSEL_table),
119 .table = VDCDCx_VSEL_table,
120 },
121 {
122 .name = "VDCDC3",
123 .min_uV = 725000,
124 .max_uV = 3300000,
125 .table_len = ARRAY_SIZE(VDCDCx_VSEL_table),
126 .table = VDCDCx_VSEL_table,
127 },
128 {
129 .name = "LDO1",
130 .min_uV = 1000000,
131 .max_uV = 3300000,
132 .table_len = ARRAY_SIZE(LDO1_VSEL_table),
133 .table = LDO1_VSEL_table,
134 },
135 {
136 .name = "LDO2",
137 .min_uV = 725000,
138 .max_uV = 3300000,
139 .table_len = ARRAY_SIZE(LDO2_VSEL_table),
140 .table = LDO2_VSEL_table,
141 },
142};
143
144struct tps6507x_pmic {
166 struct regulator_desc desc[TPS6507X_NUM_REGULATOR]; 145 struct regulator_desc desc[TPS6507X_NUM_REGULATOR];
167 struct i2c_client *client; 146 struct tps6507x_dev *mfd;
168 struct regulator_dev *rdev[TPS6507X_NUM_REGULATOR]; 147 struct regulator_dev *rdev[TPS6507X_NUM_REGULATOR];
169 const struct tps_info *info[TPS6507X_NUM_REGULATOR]; 148 const struct tps_info *info[TPS6507X_NUM_REGULATOR];
170 struct mutex io_lock; 149 struct mutex io_lock;
171}; 150};
172 151static inline int tps6507x_pmic_read(struct tps6507x_pmic *tps, u8 reg)
173static inline int tps_6507x_read(struct tps_pmic *tps, u8 reg)
174{ 152{
175 return i2c_smbus_read_byte_data(tps->client, reg); 153 u8 val;
154 int err;
155
156 err = tps->mfd->read_dev(tps->mfd, reg, 1, &val);
157
158 if (err)
159 return err;
160
161 return val;
176} 162}
177 163
178static inline int tps_6507x_write(struct tps_pmic *tps, u8 reg, u8 val) 164static inline int tps6507x_pmic_write(struct tps6507x_pmic *tps, u8 reg, u8 val)
179{ 165{
180 return i2c_smbus_write_byte_data(tps->client, reg, val); 166 return tps->mfd->write_dev(tps->mfd, reg, 1, &val);
181} 167}
182 168
183static int tps_6507x_set_bits(struct tps_pmic *tps, u8 reg, u8 mask) 169static int tps6507x_pmic_set_bits(struct tps6507x_pmic *tps, u8 reg, u8 mask)
184{ 170{
185 int err, data; 171 int err, data;
186 172
187 mutex_lock(&tps->io_lock); 173 mutex_lock(&tps->io_lock);
188 174
189 data = tps_6507x_read(tps, reg); 175 data = tps6507x_pmic_read(tps, reg);
190 if (data < 0) { 176 if (data < 0) {
191 dev_err(&tps->client->dev, "Read from reg 0x%x failed\n", reg); 177 dev_err(tps->mfd->dev, "Read from reg 0x%x failed\n", reg);
192 err = data; 178 err = data;
193 goto out; 179 goto out;
194 } 180 }
195 181
196 data |= mask; 182 data |= mask;
197 err = tps_6507x_write(tps, reg, data); 183 err = tps6507x_pmic_write(tps, reg, data);
198 if (err) 184 if (err)
199 dev_err(&tps->client->dev, "Write for reg 0x%x failed\n", reg); 185 dev_err(tps->mfd->dev, "Write for reg 0x%x failed\n", reg);
200 186
201out: 187out:
202 mutex_unlock(&tps->io_lock); 188 mutex_unlock(&tps->io_lock);
203 return err; 189 return err;
204} 190}
205 191
206static int tps_6507x_clear_bits(struct tps_pmic *tps, u8 reg, u8 mask) 192static int tps6507x_pmic_clear_bits(struct tps6507x_pmic *tps, u8 reg, u8 mask)
207{ 193{
208 int err, data; 194 int err, data;
209 195
210 mutex_lock(&tps->io_lock); 196 mutex_lock(&tps->io_lock);
211 197
212 data = tps_6507x_read(tps, reg); 198 data = tps6507x_pmic_read(tps, reg);
213 if (data < 0) { 199 if (data < 0) {
214 dev_err(&tps->client->dev, "Read from reg 0x%x failed\n", reg); 200 dev_err(tps->mfd->dev, "Read from reg 0x%x failed\n", reg);
215 err = data; 201 err = data;
216 goto out; 202 goto out;
217 } 203 }
218 204
219 data &= ~mask; 205 data &= ~mask;
220 err = tps_6507x_write(tps, reg, data); 206 err = tps6507x_pmic_write(tps, reg, data);
221 if (err) 207 if (err)
222 dev_err(&tps->client->dev, "Write for reg 0x%x failed\n", reg); 208 dev_err(tps->mfd->dev, "Write for reg 0x%x failed\n", reg);
223 209
224out: 210out:
225 mutex_unlock(&tps->io_lock); 211 mutex_unlock(&tps->io_lock);
226 return err; 212 return err;
227} 213}
228 214
229static int tps_6507x_reg_read(struct tps_pmic *tps, u8 reg) 215static int tps6507x_pmic_reg_read(struct tps6507x_pmic *tps, u8 reg)
230{ 216{
231 int data; 217 int data;
232 218
233 mutex_lock(&tps->io_lock); 219 mutex_lock(&tps->io_lock);
234 220
235 data = tps_6507x_read(tps, reg); 221 data = tps6507x_pmic_read(tps, reg);
236 if (data < 0) 222 if (data < 0)
237 dev_err(&tps->client->dev, "Read from reg 0x%x failed\n", reg); 223 dev_err(tps->mfd->dev, "Read from reg 0x%x failed\n", reg);
238 224
239 mutex_unlock(&tps->io_lock); 225 mutex_unlock(&tps->io_lock);
240 return data; 226 return data;
241} 227}
242 228
243static int tps_6507x_reg_write(struct tps_pmic *tps, u8 reg, u8 val) 229static int tps6507x_pmic_reg_write(struct tps6507x_pmic *tps, u8 reg, u8 val)
244{ 230{
245 int err; 231 int err;
246 232
247 mutex_lock(&tps->io_lock); 233 mutex_lock(&tps->io_lock);
248 234
249 err = tps_6507x_write(tps, reg, val); 235 err = tps6507x_pmic_write(tps, reg, val);
250 if (err < 0) 236 if (err < 0)
251 dev_err(&tps->client->dev, "Write for reg 0x%x failed\n", reg); 237 dev_err(tps->mfd->dev, "Write for reg 0x%x failed\n", reg);
252 238
253 mutex_unlock(&tps->io_lock); 239 mutex_unlock(&tps->io_lock);
254 return err; 240 return err;
255} 241}
256 242
257static int tps6507x_dcdc_is_enabled(struct regulator_dev *dev) 243static int tps6507x_pmic_dcdc_is_enabled(struct regulator_dev *dev)
258{ 244{
259 struct tps_pmic *tps = rdev_get_drvdata(dev); 245 struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
260 int data, dcdc = rdev_get_id(dev); 246 int data, dcdc = rdev_get_id(dev);
261 u8 shift; 247 u8 shift;
262 248
@@ -264,7 +250,7 @@ static int tps6507x_dcdc_is_enabled(struct regulator_dev *dev)
264 return -EINVAL; 250 return -EINVAL;
265 251
266 shift = TPS6507X_MAX_REG_ID - dcdc; 252 shift = TPS6507X_MAX_REG_ID - dcdc;
267 data = tps_6507x_reg_read(tps, TPS6507X_REG_CON_CTRL1); 253 data = tps6507x_pmic_reg_read(tps, TPS6507X_REG_CON_CTRL1);
268 254
269 if (data < 0) 255 if (data < 0)
270 return data; 256 return data;
@@ -272,9 +258,9 @@ static int tps6507x_dcdc_is_enabled(struct regulator_dev *dev)
272 return (data & 1<<shift) ? 1 : 0; 258 return (data & 1<<shift) ? 1 : 0;
273} 259}
274 260
275static int tps6507x_ldo_is_enabled(struct regulator_dev *dev) 261static int tps6507x_pmic_ldo_is_enabled(struct regulator_dev *dev)
276{ 262{
277 struct tps_pmic *tps = rdev_get_drvdata(dev); 263 struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
278 int data, ldo = rdev_get_id(dev); 264 int data, ldo = rdev_get_id(dev);
279 u8 shift; 265 u8 shift;
280 266
@@ -282,7 +268,7 @@ static int tps6507x_ldo_is_enabled(struct regulator_dev *dev)
282 return -EINVAL; 268 return -EINVAL;
283 269
284 shift = TPS6507X_MAX_REG_ID - ldo; 270 shift = TPS6507X_MAX_REG_ID - ldo;
285 data = tps_6507x_reg_read(tps, TPS6507X_REG_CON_CTRL1); 271 data = tps6507x_pmic_reg_read(tps, TPS6507X_REG_CON_CTRL1);
286 272
287 if (data < 0) 273 if (data < 0)
288 return data; 274 return data;
@@ -290,9 +276,9 @@ static int tps6507x_ldo_is_enabled(struct regulator_dev *dev)
290 return (data & 1<<shift) ? 1 : 0; 276 return (data & 1<<shift) ? 1 : 0;
291} 277}
292 278
293static int tps6507x_dcdc_enable(struct regulator_dev *dev) 279static int tps6507x_pmic_dcdc_enable(struct regulator_dev *dev)
294{ 280{
295 struct tps_pmic *tps = rdev_get_drvdata(dev); 281 struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
296 int dcdc = rdev_get_id(dev); 282 int dcdc = rdev_get_id(dev);
297 u8 shift; 283 u8 shift;
298 284
@@ -300,12 +286,12 @@ static int tps6507x_dcdc_enable(struct regulator_dev *dev)
300 return -EINVAL; 286 return -EINVAL;
301 287
302 shift = TPS6507X_MAX_REG_ID - dcdc; 288 shift = TPS6507X_MAX_REG_ID - dcdc;
303 return tps_6507x_set_bits(tps, TPS6507X_REG_CON_CTRL1, 1 << shift); 289 return tps6507x_pmic_set_bits(tps, TPS6507X_REG_CON_CTRL1, 1 << shift);
304} 290}
305 291
306static int tps6507x_dcdc_disable(struct regulator_dev *dev) 292static int tps6507x_pmic_dcdc_disable(struct regulator_dev *dev)
307{ 293{
308 struct tps_pmic *tps = rdev_get_drvdata(dev); 294 struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
309 int dcdc = rdev_get_id(dev); 295 int dcdc = rdev_get_id(dev);
310 u8 shift; 296 u8 shift;
311 297
@@ -313,12 +299,13 @@ static int tps6507x_dcdc_disable(struct regulator_dev *dev)
313 return -EINVAL; 299 return -EINVAL;
314 300
315 shift = TPS6507X_MAX_REG_ID - dcdc; 301 shift = TPS6507X_MAX_REG_ID - dcdc;
316 return tps_6507x_clear_bits(tps, TPS6507X_REG_CON_CTRL1, 1 << shift); 302 return tps6507x_pmic_clear_bits(tps, TPS6507X_REG_CON_CTRL1,
303 1 << shift);
317} 304}
318 305
319static int tps6507x_ldo_enable(struct regulator_dev *dev) 306static int tps6507x_pmic_ldo_enable(struct regulator_dev *dev)
320{ 307{
321 struct tps_pmic *tps = rdev_get_drvdata(dev); 308 struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
322 int ldo = rdev_get_id(dev); 309 int ldo = rdev_get_id(dev);
323 u8 shift; 310 u8 shift;
324 311
@@ -326,12 +313,12 @@ static int tps6507x_ldo_enable(struct regulator_dev *dev)
326 return -EINVAL; 313 return -EINVAL;
327 314
328 shift = TPS6507X_MAX_REG_ID - ldo; 315 shift = TPS6507X_MAX_REG_ID - ldo;
329 return tps_6507x_set_bits(tps, TPS6507X_REG_CON_CTRL1, 1 << shift); 316 return tps6507x_pmic_set_bits(tps, TPS6507X_REG_CON_CTRL1, 1 << shift);
330} 317}
331 318
332static int tps6507x_ldo_disable(struct regulator_dev *dev) 319static int tps6507x_pmic_ldo_disable(struct regulator_dev *dev)
333{ 320{
334 struct tps_pmic *tps = rdev_get_drvdata(dev); 321 struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
335 int ldo = rdev_get_id(dev); 322 int ldo = rdev_get_id(dev);
336 u8 shift; 323 u8 shift;
337 324
@@ -339,12 +326,13 @@ static int tps6507x_ldo_disable(struct regulator_dev *dev)
339 return -EINVAL; 326 return -EINVAL;
340 327
341 shift = TPS6507X_MAX_REG_ID - ldo; 328 shift = TPS6507X_MAX_REG_ID - ldo;
342 return tps_6507x_clear_bits(tps, TPS6507X_REG_CON_CTRL1, 1 << shift); 329 return tps6507x_pmic_clear_bits(tps, TPS6507X_REG_CON_CTRL1,
330 1 << shift);
343} 331}
344 332
345static int tps6507x_dcdc_get_voltage(struct regulator_dev *dev) 333static int tps6507x_pmic_dcdc_get_voltage(struct regulator_dev *dev)
346{ 334{
347 struct tps_pmic *tps = rdev_get_drvdata(dev); 335 struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
348 int data, dcdc = rdev_get_id(dev); 336 int data, dcdc = rdev_get_id(dev);
349 u8 reg; 337 u8 reg;
350 338
@@ -362,7 +350,7 @@ static int tps6507x_dcdc_get_voltage(struct regulator_dev *dev)
362 return -EINVAL; 350 return -EINVAL;
363 } 351 }
364 352
365 data = tps_6507x_reg_read(tps, reg); 353 data = tps6507x_pmic_reg_read(tps, reg);
366 if (data < 0) 354 if (data < 0)
367 return data; 355 return data;
368 356
@@ -370,10 +358,10 @@ static int tps6507x_dcdc_get_voltage(struct regulator_dev *dev)
370 return tps->info[dcdc]->table[data] * 1000; 358 return tps->info[dcdc]->table[data] * 1000;
371} 359}
372 360
373static int tps6507x_dcdc_set_voltage(struct regulator_dev *dev, 361static int tps6507x_pmic_dcdc_set_voltage(struct regulator_dev *dev,
374 int min_uV, int max_uV) 362 int min_uV, int max_uV)
375{ 363{
376 struct tps_pmic *tps = rdev_get_drvdata(dev); 364 struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
377 int data, vsel, dcdc = rdev_get_id(dev); 365 int data, vsel, dcdc = rdev_get_id(dev);
378 u8 reg; 366 u8 reg;
379 367
@@ -411,19 +399,19 @@ static int tps6507x_dcdc_set_voltage(struct regulator_dev *dev,
411 if (vsel == tps->info[dcdc]->table_len) 399 if (vsel == tps->info[dcdc]->table_len)
412 return -EINVAL; 400 return -EINVAL;
413 401
414 data = tps_6507x_reg_read(tps, reg); 402 data = tps6507x_pmic_reg_read(tps, reg);
415 if (data < 0) 403 if (data < 0)
416 return data; 404 return data;
417 405
418 data &= ~TPS6507X_DEFDCDCX_DCDC_MASK; 406 data &= ~TPS6507X_DEFDCDCX_DCDC_MASK;
419 data |= vsel; 407 data |= vsel;
420 408
421 return tps_6507x_reg_write(tps, reg, data); 409 return tps6507x_pmic_reg_write(tps, reg, data);
422} 410}
423 411
424static int tps6507x_ldo_get_voltage(struct regulator_dev *dev) 412static int tps6507x_pmic_ldo_get_voltage(struct regulator_dev *dev)
425{ 413{
426 struct tps_pmic *tps = rdev_get_drvdata(dev); 414 struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
427 int data, ldo = rdev_get_id(dev); 415 int data, ldo = rdev_get_id(dev);
428 u8 reg, mask; 416 u8 reg, mask;
429 417
@@ -437,7 +425,7 @@ static int tps6507x_ldo_get_voltage(struct regulator_dev *dev)
437 TPS6507X_REG_DEFLDO2_LDO2_MASK); 425 TPS6507X_REG_DEFLDO2_LDO2_MASK);
438 } 426 }
439 427
440 data = tps_6507x_reg_read(tps, reg); 428 data = tps6507x_pmic_reg_read(tps, reg);
441 if (data < 0) 429 if (data < 0)
442 return data; 430 return data;
443 431
@@ -445,10 +433,10 @@ static int tps6507x_ldo_get_voltage(struct regulator_dev *dev)
445 return tps->info[ldo]->table[data] * 1000; 433 return tps->info[ldo]->table[data] * 1000;
446} 434}
447 435
448static int tps6507x_ldo_set_voltage(struct regulator_dev *dev, 436static int tps6507x_pmic_ldo_set_voltage(struct regulator_dev *dev,
449 int min_uV, int max_uV) 437 int min_uV, int max_uV)
450{ 438{
451 struct tps_pmic *tps = rdev_get_drvdata(dev); 439 struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
452 int data, vsel, ldo = rdev_get_id(dev); 440 int data, vsel, ldo = rdev_get_id(dev);
453 u8 reg, mask; 441 u8 reg, mask;
454 442
@@ -479,20 +467,20 @@ static int tps6507x_ldo_set_voltage(struct regulator_dev *dev,
479 if (vsel == tps->info[ldo]->table_len) 467 if (vsel == tps->info[ldo]->table_len)
480 return -EINVAL; 468 return -EINVAL;
481 469
482 data = tps_6507x_reg_read(tps, reg); 470 data = tps6507x_pmic_reg_read(tps, reg);
483 if (data < 0) 471 if (data < 0)
484 return data; 472 return data;
485 473
486 data &= ~mask; 474 data &= ~mask;
487 data |= vsel; 475 data |= vsel;
488 476
489 return tps_6507x_reg_write(tps, reg, data); 477 return tps6507x_pmic_reg_write(tps, reg, data);
490} 478}
491 479
492static int tps6507x_dcdc_list_voltage(struct regulator_dev *dev, 480static int tps6507x_pmic_dcdc_list_voltage(struct regulator_dev *dev,
493 unsigned selector) 481 unsigned selector)
494{ 482{
495 struct tps_pmic *tps = rdev_get_drvdata(dev); 483 struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
496 int dcdc = rdev_get_id(dev); 484 int dcdc = rdev_get_id(dev);
497 485
498 if (dcdc < TPS6507X_DCDC_1 || dcdc > TPS6507X_DCDC_3) 486 if (dcdc < TPS6507X_DCDC_1 || dcdc > TPS6507X_DCDC_3)
@@ -504,10 +492,10 @@ static int tps6507x_dcdc_list_voltage(struct regulator_dev *dev,
504 return tps->info[dcdc]->table[selector] * 1000; 492 return tps->info[dcdc]->table[selector] * 1000;
505} 493}
506 494
507static int tps6507x_ldo_list_voltage(struct regulator_dev *dev, 495static int tps6507x_pmic_ldo_list_voltage(struct regulator_dev *dev,
508 unsigned selector) 496 unsigned selector)
509{ 497{
510 struct tps_pmic *tps = rdev_get_drvdata(dev); 498 struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
511 int ldo = rdev_get_id(dev); 499 int ldo = rdev_get_id(dev);
512 500
513 if (ldo < TPS6507X_LDO_1 || ldo > TPS6507X_LDO_2) 501 if (ldo < TPS6507X_LDO_1 || ldo > TPS6507X_LDO_2)
@@ -520,47 +508,54 @@ static int tps6507x_ldo_list_voltage(struct regulator_dev *dev,
520} 508}
521 509
522/* Operations permitted on VDCDCx */ 510/* Operations permitted on VDCDCx */
523static struct regulator_ops tps6507x_dcdc_ops = { 511static struct regulator_ops tps6507x_pmic_dcdc_ops = {
524 .is_enabled = tps6507x_dcdc_is_enabled, 512 .is_enabled = tps6507x_pmic_dcdc_is_enabled,
525 .enable = tps6507x_dcdc_enable, 513 .enable = tps6507x_pmic_dcdc_enable,
526 .disable = tps6507x_dcdc_disable, 514 .disable = tps6507x_pmic_dcdc_disable,
527 .get_voltage = tps6507x_dcdc_get_voltage, 515 .get_voltage = tps6507x_pmic_dcdc_get_voltage,
528 .set_voltage = tps6507x_dcdc_set_voltage, 516 .set_voltage = tps6507x_pmic_dcdc_set_voltage,
529 .list_voltage = tps6507x_dcdc_list_voltage, 517 .list_voltage = tps6507x_pmic_dcdc_list_voltage,
530}; 518};
531 519
532/* Operations permitted on LDOx */ 520/* Operations permitted on LDOx */
533static struct regulator_ops tps6507x_ldo_ops = { 521static struct regulator_ops tps6507x_pmic_ldo_ops = {
534 .is_enabled = tps6507x_ldo_is_enabled, 522 .is_enabled = tps6507x_pmic_ldo_is_enabled,
535 .enable = tps6507x_ldo_enable, 523 .enable = tps6507x_pmic_ldo_enable,
536 .disable = tps6507x_ldo_disable, 524 .disable = tps6507x_pmic_ldo_disable,
537 .get_voltage = tps6507x_ldo_get_voltage, 525 .get_voltage = tps6507x_pmic_ldo_get_voltage,
538 .set_voltage = tps6507x_ldo_set_voltage, 526 .set_voltage = tps6507x_pmic_ldo_set_voltage,
539 .list_voltage = tps6507x_ldo_list_voltage, 527 .list_voltage = tps6507x_pmic_ldo_list_voltage,
540}; 528};
541 529
542static int __devinit tps_6507x_probe(struct i2c_client *client, 530static __devinit
543 const struct i2c_device_id *id) 531int tps6507x_pmic_probe(struct platform_device *pdev)
544{ 532{
533 struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent);
545 static int desc_id; 534 static int desc_id;
546 const struct tps_info *info = (void *)id->driver_data; 535 const struct tps_info *info = &tps6507x_pmic_regs[0];
547 struct regulator_init_data *init_data; 536 struct regulator_init_data *init_data;
548 struct regulator_dev *rdev; 537 struct regulator_dev *rdev;
549 struct tps_pmic *tps; 538 struct tps6507x_pmic *tps;
539 struct tps6507x_board *tps_board;
550 int i; 540 int i;
551 int error; 541 int error;
552 542
553 if (!i2c_check_functionality(client->adapter, 543 /**
554 I2C_FUNC_SMBUS_BYTE_DATA)) 544 * tps_board points to pmic related constants
555 return -EIO; 545 * coming from the board-evm file.
546 */
547
548 tps_board = dev_get_platdata(tps6507x_dev->dev);
549 if (!tps_board)
550 return -EINVAL;
556 551
557 /** 552 /**
558 * init_data points to array of regulator_init structures 553 * init_data points to array of regulator_init structures
559 * coming from the board-evm file. 554 * coming from the board-evm file.
560 */ 555 */
561 init_data = client->dev.platform_data; 556 init_data = tps_board->tps6507x_pmic_init_data;
562 if (!init_data) 557 if (!init_data)
563 return -EIO; 558 return -EINVAL;
564 559
565 tps = kzalloc(sizeof(*tps), GFP_KERNEL); 560 tps = kzalloc(sizeof(*tps), GFP_KERNEL);
566 if (!tps) 561 if (!tps)
@@ -569,7 +564,7 @@ static int __devinit tps_6507x_probe(struct i2c_client *client,
569 mutex_init(&tps->io_lock); 564 mutex_init(&tps->io_lock);
570 565
571 /* common for all regulators */ 566 /* common for all regulators */
572 tps->client = client; 567 tps->mfd = tps6507x_dev;
573 568
574 for (i = 0; i < TPS6507X_NUM_REGULATOR; i++, info++, init_data++) { 569 for (i = 0; i < TPS6507X_NUM_REGULATOR; i++, info++, init_data++) {
575 /* Register the regulators */ 570 /* Register the regulators */
@@ -578,15 +573,16 @@ static int __devinit tps_6507x_probe(struct i2c_client *client,
578 tps->desc[i].id = desc_id++; 573 tps->desc[i].id = desc_id++;
579 tps->desc[i].n_voltages = num_voltages[i]; 574 tps->desc[i].n_voltages = num_voltages[i];
580 tps->desc[i].ops = (i > TPS6507X_DCDC_3 ? 575 tps->desc[i].ops = (i > TPS6507X_DCDC_3 ?
581 &tps6507x_ldo_ops : &tps6507x_dcdc_ops); 576 &tps6507x_pmic_ldo_ops : &tps6507x_pmic_dcdc_ops);
582 tps->desc[i].type = REGULATOR_VOLTAGE; 577 tps->desc[i].type = REGULATOR_VOLTAGE;
583 tps->desc[i].owner = THIS_MODULE; 578 tps->desc[i].owner = THIS_MODULE;
584 579
585 rdev = regulator_register(&tps->desc[i], 580 rdev = regulator_register(&tps->desc[i],
586 &client->dev, init_data, tps); 581 tps6507x_dev->dev, init_data, tps);
587 if (IS_ERR(rdev)) { 582 if (IS_ERR(rdev)) {
588 dev_err(&client->dev, "failed to register %s\n", 583 dev_err(tps6507x_dev->dev,
589 id->name); 584 "failed to register %s regulator\n",
585 pdev->name);
590 error = PTR_ERR(rdev); 586 error = PTR_ERR(rdev);
591 goto fail; 587 goto fail;
592 } 588 }
@@ -595,7 +591,7 @@ static int __devinit tps_6507x_probe(struct i2c_client *client,
595 tps->rdev[i] = rdev; 591 tps->rdev[i] = rdev;
596 } 592 }
597 593
598 i2c_set_clientdata(client, tps); 594 tps6507x_dev->pmic = tps;
599 595
600 return 0; 596 return 0;
601 597
@@ -608,19 +604,17 @@ fail:
608} 604}
609 605
610/** 606/**
611 * tps_6507x_remove - TPS6507x driver i2c remove handler 607 * tps6507x_remove - TPS6507x driver i2c remove handler
612 * @client: i2c driver client device structure 608 * @client: i2c driver client device structure
613 * 609 *
614 * Unregister TPS driver as an i2c client device driver 610 * Unregister TPS driver as an i2c client device driver
615 */ 611 */
616static int __devexit tps_6507x_remove(struct i2c_client *client) 612static int __devexit tps6507x_pmic_remove(struct platform_device *pdev)
617{ 613{
618 struct tps_pmic *tps = i2c_get_clientdata(client); 614 struct tps6507x_dev *tps6507x_dev = platform_get_drvdata(pdev);
615 struct tps6507x_pmic *tps = tps6507x_dev->pmic;
619 int i; 616 int i;
620 617
621 /* clear the client data in i2c */
622 i2c_set_clientdata(client, NULL);
623
624 for (i = 0; i < TPS6507X_NUM_REGULATOR; i++) 618 for (i = 0; i < TPS6507X_NUM_REGULATOR; i++)
625 regulator_unregister(tps->rdev[i]); 619 regulator_unregister(tps->rdev[i]);
626 620
@@ -629,83 +623,38 @@ static int __devexit tps_6507x_remove(struct i2c_client *client)
629 return 0; 623 return 0;
630} 624}
631 625
632static const struct tps_info tps6507x_regs[] = { 626static struct platform_driver tps6507x_pmic_driver = {
633 {
634 .name = "VDCDC1",
635 .min_uV = 725000,
636 .max_uV = 3300000,
637 .table_len = ARRAY_SIZE(VDCDCx_VSEL_table),
638 .table = VDCDCx_VSEL_table,
639 },
640 {
641 .name = "VDCDC2",
642 .min_uV = 725000,
643 .max_uV = 3300000,
644 .table_len = ARRAY_SIZE(VDCDCx_VSEL_table),
645 .table = VDCDCx_VSEL_table,
646 },
647 {
648 .name = "VDCDC3",
649 .min_uV = 725000,
650 .max_uV = 3300000,
651 .table_len = ARRAY_SIZE(VDCDCx_VSEL_table),
652 .table = VDCDCx_VSEL_table,
653 },
654 {
655 .name = "LDO1",
656 .min_uV = 1000000,
657 .max_uV = 3300000,
658 .table_len = ARRAY_SIZE(LDO1_VSEL_table),
659 .table = LDO1_VSEL_table,
660 },
661 {
662 .name = "LDO2",
663 .min_uV = 725000,
664 .max_uV = 3300000,
665 .table_len = ARRAY_SIZE(LDO2_VSEL_table),
666 .table = LDO2_VSEL_table,
667 },
668};
669
670static const struct i2c_device_id tps_6507x_id[] = {
671 {.name = "tps6507x",
672 .driver_data = (unsigned long) tps6507x_regs,},
673 { },
674};
675MODULE_DEVICE_TABLE(i2c, tps_6507x_id);
676
677static struct i2c_driver tps_6507x_i2c_driver = {
678 .driver = { 627 .driver = {
679 .name = "tps6507x", 628 .name = "tps6507x-pmic",
680 .owner = THIS_MODULE, 629 .owner = THIS_MODULE,
681 }, 630 },
682 .probe = tps_6507x_probe, 631 .probe = tps6507x_pmic_probe,
683 .remove = __devexit_p(tps_6507x_remove), 632 .remove = __devexit_p(tps6507x_pmic_remove),
684 .id_table = tps_6507x_id,
685}; 633};
686 634
687/** 635/**
688 * tps_6507x_init 636 * tps6507x_pmic_init
689 * 637 *
690 * Module init function 638 * Module init function
691 */ 639 */
692static int __init tps_6507x_init(void) 640static int __init tps6507x_pmic_init(void)
693{ 641{
694 return i2c_add_driver(&tps_6507x_i2c_driver); 642 return platform_driver_register(&tps6507x_pmic_driver);
695} 643}
696subsys_initcall(tps_6507x_init); 644subsys_initcall(tps6507x_pmic_init);
697 645
698/** 646/**
699 * tps_6507x_cleanup 647 * tps6507x_pmic_cleanup
700 * 648 *
701 * Module exit function 649 * Module exit function
702 */ 650 */
703static void __exit tps_6507x_cleanup(void) 651static void __exit tps6507x_pmic_cleanup(void)
704{ 652{
705 i2c_del_driver(&tps_6507x_i2c_driver); 653 platform_driver_unregister(&tps6507x_pmic_driver);
706} 654}
707module_exit(tps_6507x_cleanup); 655module_exit(tps6507x_pmic_cleanup);
708 656
709MODULE_AUTHOR("Texas Instruments"); 657MODULE_AUTHOR("Texas Instruments");
710MODULE_DESCRIPTION("TPS6507x voltage regulator driver"); 658MODULE_DESCRIPTION("TPS6507x voltage regulator driver");
711MODULE_LICENSE("GPL v2"); 659MODULE_LICENSE("GPL v2");
660MODULE_ALIAS("platform:tps6507x-pmic");
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index f1598324344c..10ba12c8c5e0 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -611,6 +611,13 @@ config RTC_DRV_AB3100
611 Select this to enable the ST-Ericsson AB3100 Mixed Signal IC RTC 611 Select this to enable the ST-Ericsson AB3100 Mixed Signal IC RTC
612 support. This chip contains a battery- and capacitor-backed RTC. 612 support. This chip contains a battery- and capacitor-backed RTC.
613 613
614config RTC_DRV_AB8500
615 tristate "ST-Ericsson AB8500 RTC"
616 depends on AB8500_CORE
617 help
618 Select this to enable the ST-Ericsson AB8500 power management IC RTC
619 support. This chip contains a battery- and capacitor-backed RTC.
620
614config RTC_DRV_NUC900 621config RTC_DRV_NUC900
615 tristate "NUC910/NUC920 RTC driver" 622 tristate "NUC910/NUC920 RTC driver"
616 depends on RTC_CLASS && ARCH_W90X900 623 depends on RTC_CLASS && ARCH_W90X900
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 245311a1348f..5adbba7cf89c 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -18,6 +18,7 @@ rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o
18# Keep the list ordered. 18# Keep the list ordered.
19 19
20obj-$(CONFIG_RTC_DRV_AB3100) += rtc-ab3100.o 20obj-$(CONFIG_RTC_DRV_AB3100) += rtc-ab3100.o
21obj-$(CONFIG_RTC_DRV_AB8500) += rtc-ab8500.o
21obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o 22obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o
22obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o 23obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o
23obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o 24obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o
diff --git a/drivers/rtc/rtc-ab3100.c b/drivers/rtc/rtc-ab3100.c
index 4704aac2b5af..d26780ea254b 100644
--- a/drivers/rtc/rtc-ab3100.c
+++ b/drivers/rtc/rtc-ab3100.c
@@ -9,7 +9,7 @@
9#include <linux/init.h> 9#include <linux/init.h>
10#include <linux/platform_device.h> 10#include <linux/platform_device.h>
11#include <linux/rtc.h> 11#include <linux/rtc.h>
12#include <linux/mfd/ab3100.h> 12#include <linux/mfd/abx500.h>
13 13
14/* Clock rate in Hz */ 14/* Clock rate in Hz */
15#define AB3100_RTC_CLOCK_RATE 32768 15#define AB3100_RTC_CLOCK_RATE 32768
@@ -45,7 +45,6 @@
45 */ 45 */
46static int ab3100_rtc_set_mmss(struct device *dev, unsigned long secs) 46static int ab3100_rtc_set_mmss(struct device *dev, unsigned long secs)
47{ 47{
48 struct ab3100 *ab3100_data = dev_get_drvdata(dev);
49 u8 regs[] = {AB3100_TI0, AB3100_TI1, AB3100_TI2, 48 u8 regs[] = {AB3100_TI0, AB3100_TI1, AB3100_TI2,
50 AB3100_TI3, AB3100_TI4, AB3100_TI5}; 49 AB3100_TI3, AB3100_TI4, AB3100_TI5};
51 unsigned char buf[6]; 50 unsigned char buf[6];
@@ -61,27 +60,26 @@ static int ab3100_rtc_set_mmss(struct device *dev, unsigned long secs)
61 buf[5] = (fat_time >> 40) & 0xFF; 60 buf[5] = (fat_time >> 40) & 0xFF;
62 61
63 for (i = 0; i < 6; i++) { 62 for (i = 0; i < 6; i++) {
64 err = ab3100_set_register_interruptible(ab3100_data, 63 err = abx500_set_register_interruptible(dev, 0,
65 regs[i], buf[i]); 64 regs[i], buf[i]);
66 if (err) 65 if (err)
67 return err; 66 return err;
68 } 67 }
69 68
70 /* Set the flag to mark that the clock is now set */ 69 /* Set the flag to mark that the clock is now set */
71 return ab3100_mask_and_set_register_interruptible(ab3100_data, 70 return abx500_mask_and_set_register_interruptible(dev, 0,
72 AB3100_RTC, 71 AB3100_RTC,
73 0xFE, 0x01); 72 0x01, 0x01);
74 73
75} 74}
76 75
77static int ab3100_rtc_read_time(struct device *dev, struct rtc_time *tm) 76static int ab3100_rtc_read_time(struct device *dev, struct rtc_time *tm)
78{ 77{
79 struct ab3100 *ab3100_data = dev_get_drvdata(dev);
80 unsigned long time; 78 unsigned long time;
81 u8 rtcval; 79 u8 rtcval;
82 int err; 80 int err;
83 81
84 err = ab3100_get_register_interruptible(ab3100_data, 82 err = abx500_get_register_interruptible(dev, 0,
85 AB3100_RTC, &rtcval); 83 AB3100_RTC, &rtcval);
86 if (err) 84 if (err)
87 return err; 85 return err;
@@ -94,7 +92,7 @@ static int ab3100_rtc_read_time(struct device *dev, struct rtc_time *tm)
94 u8 buf[6]; 92 u8 buf[6];
95 93
96 /* Read out time registers */ 94 /* Read out time registers */
97 err = ab3100_get_register_page_interruptible(ab3100_data, 95 err = abx500_get_register_page_interruptible(dev, 0,
98 AB3100_TI0, 96 AB3100_TI0,
99 buf, 6); 97 buf, 6);
100 if (err != 0) 98 if (err != 0)
@@ -114,7 +112,6 @@ static int ab3100_rtc_read_time(struct device *dev, struct rtc_time *tm)
114 112
115static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) 113static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
116{ 114{
117 struct ab3100 *ab3100_data = dev_get_drvdata(dev);
118 unsigned long time; 115 unsigned long time;
119 u64 fat_time; 116 u64 fat_time;
120 u8 buf[6]; 117 u8 buf[6];
@@ -122,7 +119,7 @@ static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
122 int err; 119 int err;
123 120
124 /* Figure out if alarm is enabled or not */ 121 /* Figure out if alarm is enabled or not */
125 err = ab3100_get_register_interruptible(ab3100_data, 122 err = abx500_get_register_interruptible(dev, 0,
126 AB3100_RTC, &rtcval); 123 AB3100_RTC, &rtcval);
127 if (err) 124 if (err)
128 return err; 125 return err;
@@ -133,7 +130,7 @@ static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
133 /* No idea how this could be represented */ 130 /* No idea how this could be represented */
134 alarm->pending = 0; 131 alarm->pending = 0;
135 /* Read out alarm registers, only 4 bytes */ 132 /* Read out alarm registers, only 4 bytes */
136 err = ab3100_get_register_page_interruptible(ab3100_data, 133 err = abx500_get_register_page_interruptible(dev, 0,
137 AB3100_AL0, buf, 4); 134 AB3100_AL0, buf, 4);
138 if (err) 135 if (err)
139 return err; 136 return err;
@@ -148,7 +145,6 @@ static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
148 145
149static int ab3100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) 146static int ab3100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
150{ 147{
151 struct ab3100 *ab3100_data = dev_get_drvdata(dev);
152 u8 regs[] = {AB3100_AL0, AB3100_AL1, AB3100_AL2, AB3100_AL3}; 148 u8 regs[] = {AB3100_AL0, AB3100_AL1, AB3100_AL2, AB3100_AL3};
153 unsigned char buf[4]; 149 unsigned char buf[4];
154 unsigned long secs; 150 unsigned long secs;
@@ -165,21 +161,19 @@ static int ab3100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
165 161
166 /* Set the alarm */ 162 /* Set the alarm */
167 for (i = 0; i < 4; i++) { 163 for (i = 0; i < 4; i++) {
168 err = ab3100_set_register_interruptible(ab3100_data, 164 err = abx500_set_register_interruptible(dev, 0,
169 regs[i], buf[i]); 165 regs[i], buf[i]);
170 if (err) 166 if (err)
171 return err; 167 return err;
172 } 168 }
173 /* Then enable the alarm */ 169 /* Then enable the alarm */
174 return ab3100_mask_and_set_register_interruptible(ab3100_data, 170 return abx500_mask_and_set_register_interruptible(dev, 0,
175 AB3100_RTC, ~(1 << 2), 171 AB3100_RTC, (1 << 2),
176 alarm->enabled << 2); 172 alarm->enabled << 2);
177} 173}
178 174
179static int ab3100_rtc_irq_enable(struct device *dev, unsigned int enabled) 175static int ab3100_rtc_irq_enable(struct device *dev, unsigned int enabled)
180{ 176{
181 struct ab3100 *ab3100_data = dev_get_drvdata(dev);
182
183 /* 177 /*
184 * It's not possible to enable/disable the alarm IRQ for this RTC. 178 * It's not possible to enable/disable the alarm IRQ for this RTC.
185 * It does not actually trigger any IRQ: instead its only function is 179 * It does not actually trigger any IRQ: instead its only function is
@@ -188,12 +182,12 @@ static int ab3100_rtc_irq_enable(struct device *dev, unsigned int enabled)
188 * and need to be handled there instead. 182 * and need to be handled there instead.
189 */ 183 */
190 if (enabled) 184 if (enabled)
191 return ab3100_mask_and_set_register_interruptible(ab3100_data, 185 return abx500_mask_and_set_register_interruptible(dev, 0,
192 AB3100_RTC, ~(1 << 2), 186 AB3100_RTC, (1 << 2),
193 1 << 2); 187 1 << 2);
194 else 188 else
195 return ab3100_mask_and_set_register_interruptible(ab3100_data, 189 return abx500_mask_and_set_register_interruptible(dev, 0,
196 AB3100_RTC, ~(1 << 2), 190 AB3100_RTC, (1 << 2),
197 0); 191 0);
198} 192}
199 193
@@ -210,10 +204,9 @@ static int __init ab3100_rtc_probe(struct platform_device *pdev)
210 int err; 204 int err;
211 u8 regval; 205 u8 regval;
212 struct rtc_device *rtc; 206 struct rtc_device *rtc;
213 struct ab3100 *ab3100_data = platform_get_drvdata(pdev);
214 207
215 /* The first RTC register needs special treatment */ 208 /* The first RTC register needs special treatment */
216 err = ab3100_get_register_interruptible(ab3100_data, 209 err = abx500_get_register_interruptible(&pdev->dev, 0,
217 AB3100_RTC, &regval); 210 AB3100_RTC, &regval);
218 if (err) { 211 if (err) {
219 dev_err(&pdev->dev, "unable to read RTC register\n"); 212 dev_err(&pdev->dev, "unable to read RTC register\n");
@@ -231,7 +224,7 @@ static int __init ab3100_rtc_probe(struct platform_device *pdev)
231 * This bit remains until RTC power is lost. 224 * This bit remains until RTC power is lost.
232 */ 225 */
233 regval = 1 | RTC_SETTING; 226 regval = 1 | RTC_SETTING;
234 err = ab3100_set_register_interruptible(ab3100_data, 227 err = abx500_set_register_interruptible(&pdev->dev, 0,
235 AB3100_RTC, regval); 228 AB3100_RTC, regval);
236 /* Ignore any error on this write */ 229 /* Ignore any error on this write */
237 } 230 }
diff --git a/drivers/rtc/rtc-ab8500.c b/drivers/rtc/rtc-ab8500.c
new file mode 100644
index 000000000000..2fda03125e55
--- /dev/null
+++ b/drivers/rtc/rtc-ab8500.c
@@ -0,0 +1,363 @@
1/*
2 * Copyright (C) ST-Ericsson SA 2010
3 *
4 * License terms: GNU General Public License (GPL) version 2
5 * Author: Virupax Sadashivpetimath <virupax.sadashivpetimath@stericsson.com>
6 *
7 * RTC clock driver for the RTC part of the AB8500 Power management chip.
8 * Based on RTC clock driver for the AB3100 Analog Baseband Chip by
9 * Linus Walleij <linus.walleij@stericsson.com>
10 */
11
12#include <linux/module.h>
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/platform_device.h>
16#include <linux/rtc.h>
17#include <linux/mfd/ab8500.h>
18#include <linux/delay.h>
19
20#define AB8500_RTC_SOFF_STAT_REG 0x0F00
21#define AB8500_RTC_CC_CONF_REG 0x0F01
22#define AB8500_RTC_READ_REQ_REG 0x0F02
23#define AB8500_RTC_WATCH_TSECMID_REG 0x0F03
24#define AB8500_RTC_WATCH_TSECHI_REG 0x0F04
25#define AB8500_RTC_WATCH_TMIN_LOW_REG 0x0F05
26#define AB8500_RTC_WATCH_TMIN_MID_REG 0x0F06
27#define AB8500_RTC_WATCH_TMIN_HI_REG 0x0F07
28#define AB8500_RTC_ALRM_MIN_LOW_REG 0x0F08
29#define AB8500_RTC_ALRM_MIN_MID_REG 0x0F09
30#define AB8500_RTC_ALRM_MIN_HI_REG 0x0F0A
31#define AB8500_RTC_STAT_REG 0x0F0B
32#define AB8500_RTC_BKUP_CHG_REG 0x0F0C
33#define AB8500_RTC_FORCE_BKUP_REG 0x0F0D
34#define AB8500_RTC_CALIB_REG 0x0F0E
35#define AB8500_RTC_SWITCH_STAT_REG 0x0F0F
36#define AB8500_REV_REG 0x1080
37
38/* RtcReadRequest bits */
39#define RTC_READ_REQUEST 0x01
40#define RTC_WRITE_REQUEST 0x02
41
42/* RtcCtrl bits */
43#define RTC_ALARM_ENA 0x04
44#define RTC_STATUS_DATA 0x01
45
46#define COUNTS_PER_SEC (0xF000 / 60)
47#define AB8500_RTC_EPOCH 2000
48
49static const unsigned long ab8500_rtc_time_regs[] = {
50 AB8500_RTC_WATCH_TMIN_HI_REG, AB8500_RTC_WATCH_TMIN_MID_REG,
51 AB8500_RTC_WATCH_TMIN_LOW_REG, AB8500_RTC_WATCH_TSECHI_REG,
52 AB8500_RTC_WATCH_TSECMID_REG
53};
54
55static const unsigned long ab8500_rtc_alarm_regs[] = {
56 AB8500_RTC_ALRM_MIN_HI_REG, AB8500_RTC_ALRM_MIN_MID_REG,
57 AB8500_RTC_ALRM_MIN_LOW_REG
58};
59
60/* Calculate the seconds from 1970 to 01-01-2000 00:00:00 */
61static unsigned long get_elapsed_seconds(int year)
62{
63 unsigned long secs;
64 struct rtc_time tm = {
65 .tm_year = year - 1900,
66 .tm_mday = 1,
67 };
68
69 /*
70 * This function calculates secs from 1970 and not from
71 * 1900, even if we supply the offset from year 1900.
72 */
73 rtc_tm_to_time(&tm, &secs);
74 return secs;
75}
76
77static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm)
78{
79 struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
80 unsigned long timeout = jiffies + HZ;
81 int retval, i;
82 unsigned long mins, secs;
83 unsigned char buf[ARRAY_SIZE(ab8500_rtc_time_regs)];
84
85 /* Request a data read */
86 retval = ab8500_write(ab8500, AB8500_RTC_READ_REQ_REG,
87 RTC_READ_REQUEST);
88 if (retval < 0)
89 return retval;
90
91 /* Early AB8500 chips will not clear the rtc read request bit */
92 if (ab8500->revision == 0) {
93 msleep(1);
94 } else {
95 /* Wait for some cycles after enabling the rtc read in ab8500 */
96 while (time_before(jiffies, timeout)) {
97 retval = ab8500_read(ab8500, AB8500_RTC_READ_REQ_REG);
98 if (retval < 0)
99 return retval;
100
101 if (!(retval & RTC_READ_REQUEST))
102 break;
103
104 msleep(1);
105 }
106 }
107
108 /* Read the Watchtime registers */
109 for (i = 0; i < ARRAY_SIZE(ab8500_rtc_time_regs); i++) {
110 retval = ab8500_read(ab8500, ab8500_rtc_time_regs[i]);
111 if (retval < 0)
112 return retval;
113 buf[i] = retval;
114 }
115
116 mins = (buf[0] << 16) | (buf[1] << 8) | buf[2];
117
118 secs = (buf[3] << 8) | buf[4];
119 secs = secs / COUNTS_PER_SEC;
120 secs = secs + (mins * 60);
121
122 /* Add back the initially subtracted number of seconds */
123 secs += get_elapsed_seconds(AB8500_RTC_EPOCH);
124
125 rtc_time_to_tm(secs, tm);
126 return rtc_valid_tm(tm);
127}
128
129static int ab8500_rtc_set_time(struct device *dev, struct rtc_time *tm)
130{
131 struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
132 int retval, i;
133 unsigned char buf[ARRAY_SIZE(ab8500_rtc_time_regs)];
134 unsigned long no_secs, no_mins, secs = 0;
135
136 if (tm->tm_year < (AB8500_RTC_EPOCH - 1900)) {
137 dev_dbg(dev, "year should be equal to or greater than %d\n",
138 AB8500_RTC_EPOCH);
139 return -EINVAL;
140 }
141
142 /* Get the number of seconds since 1970 */
143 rtc_tm_to_time(tm, &secs);
144
145 /*
146 * Convert it to the number of seconds since 01-01-2000 00:00:00, since
147 * we only have a small counter in the RTC.
148 */
149 secs -= get_elapsed_seconds(AB8500_RTC_EPOCH);
150
151 no_mins = secs / 60;
152
153 no_secs = secs % 60;
154 /* Make the seconds count as per the RTC resolution */
155 no_secs = no_secs * COUNTS_PER_SEC;
156
157 buf[4] = no_secs & 0xFF;
158 buf[3] = (no_secs >> 8) & 0xFF;
159
160 buf[2] = no_mins & 0xFF;
161 buf[1] = (no_mins >> 8) & 0xFF;
162 buf[0] = (no_mins >> 16) & 0xFF;
163
164 for (i = 0; i < ARRAY_SIZE(ab8500_rtc_time_regs); i++) {
165 retval = ab8500_write(ab8500, ab8500_rtc_time_regs[i], buf[i]);
166 if (retval < 0)
167 return retval;
168 }
169
170 /* Request a data write */
171 return ab8500_write(ab8500, AB8500_RTC_READ_REQ_REG, RTC_WRITE_REQUEST);
172}
173
174static int ab8500_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
175{
176 struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
177 int retval, i;
178 int rtc_ctrl;
179 unsigned char buf[ARRAY_SIZE(ab8500_rtc_alarm_regs)];
180 unsigned long secs, mins;
181
182 /* Check if the alarm is enabled or not */
183 rtc_ctrl = ab8500_read(ab8500, AB8500_RTC_STAT_REG);
184 if (rtc_ctrl < 0)
185 return rtc_ctrl;
186
187 if (rtc_ctrl & RTC_ALARM_ENA)
188 alarm->enabled = 1;
189 else
190 alarm->enabled = 0;
191
192 alarm->pending = 0;
193
194 for (i = 0; i < ARRAY_SIZE(ab8500_rtc_alarm_regs); i++) {
195 retval = ab8500_read(ab8500, ab8500_rtc_alarm_regs[i]);
196 if (retval < 0)
197 return retval;
198 buf[i] = retval;
199 }
200
201 mins = (buf[0] << 16) | (buf[1] << 8) | (buf[2]);
202 secs = mins * 60;
203
204 /* Add back the initially subtracted number of seconds */
205 secs += get_elapsed_seconds(AB8500_RTC_EPOCH);
206
207 rtc_time_to_tm(secs, &alarm->time);
208
209 return rtc_valid_tm(&alarm->time);
210}
211
212static int ab8500_rtc_irq_enable(struct device *dev, unsigned int enabled)
213{
214 struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
215
216 return ab8500_set_bits(ab8500, AB8500_RTC_STAT_REG, RTC_ALARM_ENA,
217 enabled ? RTC_ALARM_ENA : 0);
218}
219
220static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
221{
222 struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
223 int retval, i;
224 unsigned char buf[ARRAY_SIZE(ab8500_rtc_alarm_regs)];
225 unsigned long mins, secs = 0;
226
227 if (alarm->time.tm_year < (AB8500_RTC_EPOCH - 1900)) {
228 dev_dbg(dev, "year should be equal to or greater than %d\n",
229 AB8500_RTC_EPOCH);
230 return -EINVAL;
231 }
232
233 /* Get the number of seconds since 1970 */
234 rtc_tm_to_time(&alarm->time, &secs);
235
236 /*
237 * Convert it to the number of seconds since 01-01-2000 00:00:00, since
238 * we only have a small counter in the RTC.
239 */
240 secs -= get_elapsed_seconds(AB8500_RTC_EPOCH);
241
242 mins = secs / 60;
243
244 buf[2] = mins & 0xFF;
245 buf[1] = (mins >> 8) & 0xFF;
246 buf[0] = (mins >> 16) & 0xFF;
247
248 /* Set the alarm time */
249 for (i = 0; i < ARRAY_SIZE(ab8500_rtc_alarm_regs); i++) {
250 retval = ab8500_write(ab8500, ab8500_rtc_alarm_regs[i], buf[i]);
251 if (retval < 0)
252 return retval;
253 }
254
255 return ab8500_rtc_irq_enable(dev, alarm->enabled);
256}
257
258static irqreturn_t rtc_alarm_handler(int irq, void *data)
259{
260 struct rtc_device *rtc = data;
261 unsigned long events = RTC_IRQF | RTC_AF;
262
263 dev_dbg(&rtc->dev, "%s\n", __func__);
264 rtc_update_irq(rtc, 1, events);
265
266 return IRQ_HANDLED;
267}
268
269static const struct rtc_class_ops ab8500_rtc_ops = {
270 .read_time = ab8500_rtc_read_time,
271 .set_time = ab8500_rtc_set_time,
272 .read_alarm = ab8500_rtc_read_alarm,
273 .set_alarm = ab8500_rtc_set_alarm,
274 .alarm_irq_enable = ab8500_rtc_irq_enable,
275};
276
277static int __devinit ab8500_rtc_probe(struct platform_device *pdev)
278{
279 struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
280 int err;
281 struct rtc_device *rtc;
282 int rtc_ctrl;
283 int irq;
284
285 irq = platform_get_irq_byname(pdev, "ALARM");
286 if (irq < 0)
287 return irq;
288
289 /* For RTC supply test */
290 err = ab8500_set_bits(ab8500, AB8500_RTC_STAT_REG, RTC_STATUS_DATA,
291 RTC_STATUS_DATA);
292 if (err < 0)
293 return err;
294
295 /* Wait for reset by the PorRtc */
296 msleep(1);
297
298 rtc_ctrl = ab8500_read(ab8500, AB8500_RTC_STAT_REG);
299 if (rtc_ctrl < 0)
300 return rtc_ctrl;
301
302 /* Check if the RTC Supply fails */
303 if (!(rtc_ctrl & RTC_STATUS_DATA)) {
304 dev_err(&pdev->dev, "RTC supply failure\n");
305 return -ENODEV;
306 }
307
308 rtc = rtc_device_register("ab8500-rtc", &pdev->dev, &ab8500_rtc_ops,
309 THIS_MODULE);
310 if (IS_ERR(rtc)) {
311 dev_err(&pdev->dev, "Registration failed\n");
312 err = PTR_ERR(rtc);
313 return err;
314 }
315
316 err = request_threaded_irq(irq, NULL, rtc_alarm_handler, 0,
317 "ab8500-rtc", rtc);
318 if (err < 0) {
319 rtc_device_unregister(rtc);
320 return err;
321 }
322
323 platform_set_drvdata(pdev, rtc);
324
325 return 0;
326}
327
328static int __devexit ab8500_rtc_remove(struct platform_device *pdev)
329{
330 struct rtc_device *rtc = platform_get_drvdata(pdev);
331 int irq = platform_get_irq_byname(pdev, "ALARM");
332
333 free_irq(irq, rtc);
334 rtc_device_unregister(rtc);
335 platform_set_drvdata(pdev, NULL);
336
337 return 0;
338}
339
340static struct platform_driver ab8500_rtc_driver = {
341 .driver = {
342 .name = "ab8500-rtc",
343 .owner = THIS_MODULE,
344 },
345 .probe = ab8500_rtc_probe,
346 .remove = __devexit_p(ab8500_rtc_remove),
347};
348
349static int __init ab8500_rtc_init(void)
350{
351 return platform_driver_register(&ab8500_rtc_driver);
352}
353
354static void __exit ab8500_rtc_exit(void)
355{
356 platform_driver_unregister(&ab8500_rtc_driver);
357}
358
359module_init(ab8500_rtc_init);
360module_exit(ab8500_rtc_exit);
361MODULE_AUTHOR("Virupax Sadashivpetimath <virupax.sadashivpetimath@stericsson.com>");
362MODULE_DESCRIPTION("AB8500 RTC Driver");
363MODULE_LICENSE("GPL v2");
diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c
index 61945734ad00..1f0007fd4431 100644
--- a/drivers/rtc/rtc-ds1374.c
+++ b/drivers/rtc/rtc-ds1374.c
@@ -403,7 +403,6 @@ out_irq:
403 free_irq(client->irq, client); 403 free_irq(client->irq, client);
404 404
405out_free: 405out_free:
406 i2c_set_clientdata(client, NULL);
407 kfree(ds1374); 406 kfree(ds1374);
408 return ret; 407 return ret;
409} 408}
@@ -422,7 +421,6 @@ static int __devexit ds1374_remove(struct i2c_client *client)
422 } 421 }
423 422
424 rtc_device_unregister(ds1374->rtc); 423 rtc_device_unregister(ds1374->rtc);
425 i2c_set_clientdata(client, NULL);
426 kfree(ds1374); 424 kfree(ds1374);
427 return 0; 425 return 0;
428} 426}
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
index 038095d99976..6dc4e6241418 100644
--- a/drivers/rtc/rtc-m41t80.c
+++ b/drivers/rtc/rtc-m41t80.c
@@ -595,10 +595,6 @@ static void wdt_disable(void)
595static ssize_t wdt_write(struct file *file, const char __user *buf, 595static ssize_t wdt_write(struct file *file, const char __user *buf,
596 size_t count, loff_t *ppos) 596 size_t count, loff_t *ppos)
597{ 597{
598 /* Can't seek (pwrite) on this device
599 if (ppos != &file->f_pos)
600 return -ESPIPE;
601 */
602 if (count) { 598 if (count) {
603 wdt_ping(); 599 wdt_ping();
604 return 1; 600 return 1;
@@ -707,7 +703,7 @@ static int wdt_open(struct inode *inode, struct file *file)
707 */ 703 */
708 wdt_is_open = 1; 704 wdt_is_open = 1;
709 unlock_kernel(); 705 unlock_kernel();
710 return 0; 706 return nonseekable_open(inode, file);
711 } 707 }
712 return -ENODEV; 708 return -ENODEV;
713} 709}
diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c
index f0dbf9cb8f9c..db5d8c416d26 100644
--- a/drivers/rtc/rtc-mpc5121.c
+++ b/drivers/rtc/rtc-mpc5121.c
@@ -279,7 +279,7 @@ static int __devinit mpc5121_rtc_probe(struct of_device *op,
279 if (!rtc) 279 if (!rtc)
280 return -ENOMEM; 280 return -ENOMEM;
281 281
282 rtc->regs = of_iomap(op->node, 0); 282 rtc->regs = of_iomap(op->dev.of_node, 0);
283 if (!rtc->regs) { 283 if (!rtc->regs) {
284 dev_err(&op->dev, "%s: couldn't map io space\n", __func__); 284 dev_err(&op->dev, "%s: couldn't map io space\n", __func__);
285 err = -ENOSYS; 285 err = -ENOSYS;
@@ -290,7 +290,7 @@ static int __devinit mpc5121_rtc_probe(struct of_device *op,
290 290
291 dev_set_drvdata(&op->dev, rtc); 291 dev_set_drvdata(&op->dev, rtc);
292 292
293 rtc->irq = irq_of_parse_and_map(op->node, 1); 293 rtc->irq = irq_of_parse_and_map(op->dev.of_node, 1);
294 err = request_irq(rtc->irq, mpc5121_rtc_handler, IRQF_DISABLED, 294 err = request_irq(rtc->irq, mpc5121_rtc_handler, IRQF_DISABLED,
295 "mpc5121-rtc", &op->dev); 295 "mpc5121-rtc", &op->dev);
296 if (err) { 296 if (err) {
@@ -299,7 +299,7 @@ static int __devinit mpc5121_rtc_probe(struct of_device *op,
299 goto out_dispose; 299 goto out_dispose;
300 } 300 }
301 301
302 rtc->irq_periodic = irq_of_parse_and_map(op->node, 0); 302 rtc->irq_periodic = irq_of_parse_and_map(op->dev.of_node, 0);
303 err = request_irq(rtc->irq_periodic, mpc5121_rtc_handler_upd, 303 err = request_irq(rtc->irq_periodic, mpc5121_rtc_handler_upd,
304 IRQF_DISABLED, "mpc5121-rtc_upd", &op->dev); 304 IRQF_DISABLED, "mpc5121-rtc_upd", &op->dev);
305 if (err) { 305 if (err) {
@@ -365,9 +365,11 @@ static struct of_device_id mpc5121_rtc_match[] __devinitdata = {
365}; 365};
366 366
367static struct of_platform_driver mpc5121_rtc_driver = { 367static struct of_platform_driver mpc5121_rtc_driver = {
368 .owner = THIS_MODULE, 368 .driver = {
369 .name = "mpc5121-rtc", 369 .name = "mpc5121-rtc",
370 .match_table = mpc5121_rtc_match, 370 .owner = THIS_MODULE,
371 .of_match_table = mpc5121_rtc_match,
372 },
371 .probe = mpc5121_rtc_probe, 373 .probe = mpc5121_rtc_probe,
372 .remove = __devexit_p(mpc5121_rtc_remove), 374 .remove = __devexit_p(mpc5121_rtc_remove),
373}; 375};
diff --git a/drivers/rtc/rtc-rx8025.c b/drivers/rtc/rtc-rx8025.c
index b65c82f792d9..789f62f9b47d 100644
--- a/drivers/rtc/rtc-rx8025.c
+++ b/drivers/rtc/rtc-rx8025.c
@@ -632,7 +632,6 @@ errout_reg:
632 rtc_device_unregister(rx8025->rtc); 632 rtc_device_unregister(rx8025->rtc);
633 633
634errout_free: 634errout_free:
635 i2c_set_clientdata(client, NULL);
636 kfree(rx8025); 635 kfree(rx8025);
637 636
638errout: 637errout:
@@ -656,7 +655,6 @@ static int __devexit rx8025_remove(struct i2c_client *client)
656 655
657 rx8025_sysfs_unregister(&client->dev); 656 rx8025_sysfs_unregister(&client->dev);
658 rtc_device_unregister(rx8025->rtc); 657 rtc_device_unregister(rx8025->rtc);
659 i2c_set_clientdata(client, NULL);
660 kfree(rx8025); 658 kfree(rx8025);
661 return 0; 659 return 0;
662} 660}
diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c
index def4d396d0b0..f789e002c9b0 100644
--- a/drivers/rtc/rtc-s35390a.c
+++ b/drivers/rtc/rtc-s35390a.c
@@ -275,7 +275,6 @@ exit_dummy:
275 if (s35390a->client[i]) 275 if (s35390a->client[i])
276 i2c_unregister_device(s35390a->client[i]); 276 i2c_unregister_device(s35390a->client[i]);
277 kfree(s35390a); 277 kfree(s35390a);
278 i2c_set_clientdata(client, NULL);
279 278
280exit: 279exit:
281 return err; 280 return err;
@@ -292,7 +291,6 @@ static int s35390a_remove(struct i2c_client *client)
292 291
293 rtc_device_unregister(s35390a->rtc); 292 rtc_device_unregister(s35390a->rtc);
294 kfree(s35390a); 293 kfree(s35390a);
295 i2c_set_clientdata(client, NULL);
296 294
297 return 0; 295 return 0;
298} 296}
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index e5972b2c17b7..70b68d35f969 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -495,8 +495,6 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
495 pr_debug("s3c2410_rtc: RTCCON=%02x\n", 495 pr_debug("s3c2410_rtc: RTCCON=%02x\n",
496 readb(s3c_rtc_base + S3C2410_RTCCON)); 496 readb(s3c_rtc_base + S3C2410_RTCCON));
497 497
498 s3c_rtc_setfreq(&pdev->dev, 1);
499
500 device_init_wakeup(&pdev->dev, 1); 498 device_init_wakeup(&pdev->dev, 1);
501 499
502 /* register RTC and exit */ 500 /* register RTC and exit */
@@ -510,14 +508,17 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
510 goto err_nortc; 508 goto err_nortc;
511 } 509 }
512 510
511 s3c_rtc_cpu_type = platform_get_device_id(pdev)->driver_data;
512
513 if (s3c_rtc_cpu_type == TYPE_S3C64XX) 513 if (s3c_rtc_cpu_type == TYPE_S3C64XX)
514 rtc->max_user_freq = 32768; 514 rtc->max_user_freq = 32768;
515 else 515 else
516 rtc->max_user_freq = 128; 516 rtc->max_user_freq = 128;
517 517
518 s3c_rtc_cpu_type = platform_get_device_id(pdev)->driver_data;
519
520 platform_set_drvdata(pdev, rtc); 518 platform_set_drvdata(pdev, rtc);
519
520 s3c_rtc_setfreq(&pdev->dev, 1);
521
521 return 0; 522 return 0;
522 523
523 err_nortc: 524 err_nortc:
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 0e86247d791e..33975e922d65 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -1186,6 +1186,29 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
1186 dasd_schedule_device_bh(device); 1186 dasd_schedule_device_bh(device);
1187} 1187}
1188 1188
1189enum uc_todo dasd_generic_uc_handler(struct ccw_device *cdev, struct irb *irb)
1190{
1191 struct dasd_device *device;
1192
1193 device = dasd_device_from_cdev_locked(cdev);
1194
1195 if (IS_ERR(device))
1196 goto out;
1197 if (test_bit(DASD_FLAG_OFFLINE, &device->flags) ||
1198 device->state != device->target ||
1199 !device->discipline->handle_unsolicited_interrupt){
1200 dasd_put_device(device);
1201 goto out;
1202 }
1203
1204 dasd_device_clear_timer(device);
1205 device->discipline->handle_unsolicited_interrupt(device, irb);
1206 dasd_put_device(device);
1207out:
1208 return UC_TODO_RETRY;
1209}
1210EXPORT_SYMBOL_GPL(dasd_generic_uc_handler);
1211
1189/* 1212/*
1190 * If we have an error on a dasd_block layer request then we cancel 1213 * If we have an error on a dasd_block layer request then we cancel
1191 * and return all further requests from the same dasd_block as well. 1214 * and return all further requests from the same dasd_block as well.
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 5b1cd8d6e971..ab84da5592e8 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -3436,6 +3436,7 @@ static struct ccw_driver dasd_eckd_driver = {
3436 .freeze = dasd_generic_pm_freeze, 3436 .freeze = dasd_generic_pm_freeze,
3437 .thaw = dasd_generic_restore_device, 3437 .thaw = dasd_generic_restore_device,
3438 .restore = dasd_generic_restore_device, 3438 .restore = dasd_generic_restore_device,
3439 .uc_handler = dasd_generic_uc_handler,
3439}; 3440};
3440 3441
3441/* 3442/*
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index 32fac186ba3f..49b431d135e0 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -617,6 +617,7 @@ int dasd_generic_notify(struct ccw_device *, int);
617void dasd_generic_handle_state_change(struct dasd_device *); 617void dasd_generic_handle_state_change(struct dasd_device *);
618int dasd_generic_pm_freeze(struct ccw_device *); 618int dasd_generic_pm_freeze(struct ccw_device *);
619int dasd_generic_restore_device(struct ccw_device *); 619int dasd_generic_restore_device(struct ccw_device *);
620enum uc_todo dasd_generic_uc_handler(struct ccw_device *, struct irb *);
620 621
621int dasd_generic_read_dev_chars(struct dasd_device *, int, void *, int); 622int dasd_generic_read_dev_chars(struct dasd_device *, int, void *, int);
622char *dasd_get_sense(struct irb *); 623char *dasd_get_sense(struct irb *);
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index 5f97ea2ee6b1..97b25d68e3e7 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -123,8 +123,10 @@ ccwgroup_release (struct device *dev)
123 123
124 for (i = 0; i < gdev->count; i++) { 124 for (i = 0; i < gdev->count; i++) {
125 if (gdev->cdev[i]) { 125 if (gdev->cdev[i]) {
126 spin_lock_irq(gdev->cdev[i]->ccwlock);
126 if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev) 127 if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev)
127 dev_set_drvdata(&gdev->cdev[i]->dev, NULL); 128 dev_set_drvdata(&gdev->cdev[i]->dev, NULL);
129 spin_unlock_irq(gdev->cdev[i]->ccwlock);
128 put_device(&gdev->cdev[i]->dev); 130 put_device(&gdev->cdev[i]->dev);
129 } 131 }
130 } 132 }
@@ -262,11 +264,14 @@ int ccwgroup_create_from_string(struct device *root, unsigned int creator_id,
262 goto error; 264 goto error;
263 } 265 }
264 /* Don't allow a device to belong to more than one group. */ 266 /* Don't allow a device to belong to more than one group. */
267 spin_lock_irq(gdev->cdev[i]->ccwlock);
265 if (dev_get_drvdata(&gdev->cdev[i]->dev)) { 268 if (dev_get_drvdata(&gdev->cdev[i]->dev)) {
269 spin_unlock_irq(gdev->cdev[i]->ccwlock);
266 rc = -EINVAL; 270 rc = -EINVAL;
267 goto error; 271 goto error;
268 } 272 }
269 dev_set_drvdata(&gdev->cdev[i]->dev, gdev); 273 dev_set_drvdata(&gdev->cdev[i]->dev, gdev);
274 spin_unlock_irq(gdev->cdev[i]->ccwlock);
270 } 275 }
271 /* Check for sufficient number of bus ids. */ 276 /* Check for sufficient number of bus ids. */
272 if (i < num_devices && !curr_buf) { 277 if (i < num_devices && !curr_buf) {
@@ -303,8 +308,10 @@ int ccwgroup_create_from_string(struct device *root, unsigned int creator_id,
303error: 308error:
304 for (i = 0; i < num_devices; i++) 309 for (i = 0; i < num_devices; i++)
305 if (gdev->cdev[i]) { 310 if (gdev->cdev[i]) {
311 spin_lock_irq(gdev->cdev[i]->ccwlock);
306 if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev) 312 if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev)
307 dev_set_drvdata(&gdev->cdev[i]->dev, NULL); 313 dev_set_drvdata(&gdev->cdev[i]->dev, NULL);
314 spin_unlock_irq(gdev->cdev[i]->ccwlock);
308 put_device(&gdev->cdev[i]->dev); 315 put_device(&gdev->cdev[i]->dev);
309 gdev->cdev[i] = NULL; 316 gdev->cdev[i] = NULL;
310 } 317 }
diff --git a/drivers/s390/cio/ccwreq.c b/drivers/s390/cio/ccwreq.c
index 37df42af05ec..7f206ed44fdf 100644
--- a/drivers/s390/cio/ccwreq.c
+++ b/drivers/s390/cio/ccwreq.c
@@ -159,6 +159,7 @@ static enum io_status ccwreq_status(struct ccw_device *cdev, struct irb *lcirb)
159{ 159{
160 struct irb *irb = &cdev->private->irb; 160 struct irb *irb = &cdev->private->irb;
161 struct cmd_scsw *scsw = &irb->scsw.cmd; 161 struct cmd_scsw *scsw = &irb->scsw.cmd;
162 enum uc_todo todo;
162 163
163 /* Perform BASIC SENSE if needed. */ 164 /* Perform BASIC SENSE if needed. */
164 if (ccw_device_accumulate_and_sense(cdev, lcirb)) 165 if (ccw_device_accumulate_and_sense(cdev, lcirb))
@@ -178,6 +179,20 @@ static enum io_status ccwreq_status(struct ccw_device *cdev, struct irb *lcirb)
178 /* Check for command reject. */ 179 /* Check for command reject. */
179 if (irb->ecw[0] & SNS0_CMD_REJECT) 180 if (irb->ecw[0] & SNS0_CMD_REJECT)
180 return IO_REJECTED; 181 return IO_REJECTED;
182 /* Ask the driver what to do */
183 if (cdev->drv && cdev->drv->uc_handler) {
184 todo = cdev->drv->uc_handler(cdev, lcirb);
185 switch (todo) {
186 case UC_TODO_RETRY:
187 return IO_STATUS_ERROR;
188 case UC_TODO_RETRY_ON_NEW_PATH:
189 return IO_PATH_ERROR;
190 case UC_TODO_STOP:
191 return IO_REJECTED;
192 default:
193 return IO_STATUS_ERROR;
194 }
195 }
181 /* Assume that unexpected SENSE data implies an error. */ 196 /* Assume that unexpected SENSE data implies an error. */
182 return IO_STATUS_ERROR; 197 return IO_STATUS_ERROR;
183 } 198 }
diff --git a/drivers/s390/cio/ioasm.h b/drivers/s390/cio/ioasm.h
index 759262792633..fac06155773f 100644
--- a/drivers/s390/cio/ioasm.h
+++ b/drivers/s390/cio/ioasm.h
@@ -23,21 +23,6 @@ struct tpi_info {
23 * Some S390 specific IO instructions as inline 23 * Some S390 specific IO instructions as inline
24 */ 24 */
25 25
26static inline int stsch(struct subchannel_id schid, struct schib *addr)
27{
28 register struct subchannel_id reg1 asm ("1") = schid;
29 int ccode;
30
31 asm volatile(
32 " stsch 0(%3)\n"
33 " ipm %0\n"
34 " srl %0,28"
35 : "=d" (ccode), "=m" (*addr)
36 : "d" (reg1), "a" (addr)
37 : "cc");
38 return ccode;
39}
40
41static inline int stsch_err(struct subchannel_id schid, struct schib *addr) 26static inline int stsch_err(struct subchannel_id schid, struct schib *addr)
42{ 27{
43 register struct subchannel_id reg1 asm ("1") = schid; 28 register struct subchannel_id reg1 asm ("1") = schid;
diff --git a/drivers/s390/cio/itcw.c b/drivers/s390/cio/itcw.c
index 17da9ab932ed..a0ae29564774 100644
--- a/drivers/s390/cio/itcw.c
+++ b/drivers/s390/cio/itcw.c
@@ -42,7 +42,7 @@
42 * size_t size; 42 * size_t size;
43 * 43 *
44 * size = itcw_calc_size(1, 2, 0); 44 * size = itcw_calc_size(1, 2, 0);
45 * buffer = kmalloc(size, GFP_DMA); 45 * buffer = kmalloc(size, GFP_KERNEL | GFP_DMA);
46 * if (!buffer) 46 * if (!buffer)
47 * return -ENOMEM; 47 * return -ENOMEM;
48 * itcw = itcw_init(buffer, size, ITCW_OP_READ, 1, 2, 0); 48 * itcw = itcw_init(buffer, size, ITCW_OP_READ, 1, 2, 0);
diff --git a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c
index 308541ff85cf..1bb5d3f0e260 100644
--- a/drivers/scsi/a2091.c
+++ b/drivers/scsi/a2091.c
@@ -1,34 +1,31 @@
1#include <linux/types.h> 1#include <linux/types.h>
2#include <linux/mm.h>
3#include <linux/slab.h>
4#include <linux/blkdev.h>
5#include <linux/init.h> 2#include <linux/init.h>
6#include <linux/interrupt.h> 3#include <linux/interrupt.h>
4#include <linux/mm.h>
5#include <linux/slab.h>
6#include <linux/spinlock.h>
7#include <linux/zorro.h>
7 8
8#include <asm/setup.h>
9#include <asm/page.h> 9#include <asm/page.h>
10#include <asm/pgtable.h> 10#include <asm/pgtable.h>
11#include <asm/amigaints.h> 11#include <asm/amigaints.h>
12#include <asm/amigahw.h> 12#include <asm/amigahw.h>
13#include <linux/zorro.h>
14#include <asm/irq.h>
15#include <linux/spinlock.h>
16 13
17#include "scsi.h" 14#include "scsi.h"
18#include <scsi/scsi_host.h>
19#include "wd33c93.h" 15#include "wd33c93.h"
20#include "a2091.h" 16#include "a2091.h"
21 17
22#include <linux/stat.h>
23
24 18
25static int a2091_release(struct Scsi_Host *instance); 19struct a2091_hostdata {
20 struct WD33C93_hostdata wh;
21 struct a2091_scsiregs *regs;
22};
26 23
27static irqreturn_t a2091_intr(int irq, void *data) 24static irqreturn_t a2091_intr(int irq, void *data)
28{ 25{
29 struct Scsi_Host *instance = data; 26 struct Scsi_Host *instance = data;
30 a2091_scsiregs *regs = (a2091_scsiregs *)(instance->base); 27 struct a2091_hostdata *hdata = shost_priv(instance);
31 unsigned int status = regs->ISTR; 28 unsigned int status = hdata->regs->ISTR;
32 unsigned long flags; 29 unsigned long flags;
33 30
34 if (!(status & (ISTR_INT_F | ISTR_INT_P)) || !(status & ISTR_INTS)) 31 if (!(status & (ISTR_INT_F | ISTR_INT_P)) || !(status & ISTR_INTS))
@@ -43,38 +40,39 @@ static irqreturn_t a2091_intr(int irq, void *data)
43static int dma_setup(struct scsi_cmnd *cmd, int dir_in) 40static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
44{ 41{
45 struct Scsi_Host *instance = cmd->device->host; 42 struct Scsi_Host *instance = cmd->device->host;
46 struct WD33C93_hostdata *hdata = shost_priv(instance); 43 struct a2091_hostdata *hdata = shost_priv(instance);
47 a2091_scsiregs *regs = (a2091_scsiregs *)(instance->base); 44 struct WD33C93_hostdata *wh = &hdata->wh;
45 struct a2091_scsiregs *regs = hdata->regs;
48 unsigned short cntr = CNTR_PDMD | CNTR_INTEN; 46 unsigned short cntr = CNTR_PDMD | CNTR_INTEN;
49 unsigned long addr = virt_to_bus(cmd->SCp.ptr); 47 unsigned long addr = virt_to_bus(cmd->SCp.ptr);
50 48
51 /* don't allow DMA if the physical address is bad */ 49 /* don't allow DMA if the physical address is bad */
52 if (addr & A2091_XFER_MASK) { 50 if (addr & A2091_XFER_MASK) {
53 hdata->dma_bounce_len = (cmd->SCp.this_residual + 511) & ~0x1ff; 51 wh->dma_bounce_len = (cmd->SCp.this_residual + 511) & ~0x1ff;
54 hdata->dma_bounce_buffer = kmalloc(hdata->dma_bounce_len, 52 wh->dma_bounce_buffer = kmalloc(wh->dma_bounce_len,
55 GFP_KERNEL); 53 GFP_KERNEL);
56 54
57 /* can't allocate memory; use PIO */ 55 /* can't allocate memory; use PIO */
58 if (!hdata->dma_bounce_buffer) { 56 if (!wh->dma_bounce_buffer) {
59 hdata->dma_bounce_len = 0; 57 wh->dma_bounce_len = 0;
60 return 1; 58 return 1;
61 } 59 }
62 60
63 /* get the physical address of the bounce buffer */ 61 /* get the physical address of the bounce buffer */
64 addr = virt_to_bus(hdata->dma_bounce_buffer); 62 addr = virt_to_bus(wh->dma_bounce_buffer);
65 63
66 /* the bounce buffer may not be in the first 16M of physmem */ 64 /* the bounce buffer may not be in the first 16M of physmem */
67 if (addr & A2091_XFER_MASK) { 65 if (addr & A2091_XFER_MASK) {
68 /* we could use chipmem... maybe later */ 66 /* we could use chipmem... maybe later */
69 kfree(hdata->dma_bounce_buffer); 67 kfree(wh->dma_bounce_buffer);
70 hdata->dma_bounce_buffer = NULL; 68 wh->dma_bounce_buffer = NULL;
71 hdata->dma_bounce_len = 0; 69 wh->dma_bounce_len = 0;
72 return 1; 70 return 1;
73 } 71 }
74 72
75 if (!dir_in) { 73 if (!dir_in) {
76 /* copy to bounce buffer for a write */ 74 /* copy to bounce buffer for a write */
77 memcpy(hdata->dma_bounce_buffer, cmd->SCp.ptr, 75 memcpy(wh->dma_bounce_buffer, cmd->SCp.ptr,
78 cmd->SCp.this_residual); 76 cmd->SCp.this_residual);
79 } 77 }
80 } 78 }
@@ -84,7 +82,7 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
84 cntr |= CNTR_DDIR; 82 cntr |= CNTR_DDIR;
85 83
86 /* remember direction */ 84 /* remember direction */
87 hdata->dma_dir = dir_in; 85 wh->dma_dir = dir_in;
88 86
89 regs->CNTR = cntr; 87 regs->CNTR = cntr;
90 88
@@ -108,20 +106,21 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
108static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, 106static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt,
109 int status) 107 int status)
110{ 108{
111 struct WD33C93_hostdata *hdata = shost_priv(instance); 109 struct a2091_hostdata *hdata = shost_priv(instance);
112 a2091_scsiregs *regs = (a2091_scsiregs *)(instance->base); 110 struct WD33C93_hostdata *wh = &hdata->wh;
111 struct a2091_scsiregs *regs = hdata->regs;
113 112
114 /* disable SCSI interrupts */ 113 /* disable SCSI interrupts */
115 unsigned short cntr = CNTR_PDMD; 114 unsigned short cntr = CNTR_PDMD;
116 115
117 if (!hdata->dma_dir) 116 if (!wh->dma_dir)
118 cntr |= CNTR_DDIR; 117 cntr |= CNTR_DDIR;
119 118
120 /* disable SCSI interrupts */ 119 /* disable SCSI interrupts */
121 regs->CNTR = cntr; 120 regs->CNTR = cntr;
122 121
123 /* flush if we were reading */ 122 /* flush if we were reading */
124 if (hdata->dma_dir) { 123 if (wh->dma_dir) {
125 regs->FLUSH = 1; 124 regs->FLUSH = 1;
126 while (!(regs->ISTR & ISTR_FE_FLG)) 125 while (!(regs->ISTR & ISTR_FE_FLG))
127 ; 126 ;
@@ -137,95 +136,37 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt,
137 regs->CNTR = CNTR_PDMD | CNTR_INTEN; 136 regs->CNTR = CNTR_PDMD | CNTR_INTEN;
138 137
139 /* copy from a bounce buffer, if necessary */ 138 /* copy from a bounce buffer, if necessary */
140 if (status && hdata->dma_bounce_buffer) { 139 if (status && wh->dma_bounce_buffer) {
141 if (hdata->dma_dir) 140 if (wh->dma_dir)
142 memcpy(SCpnt->SCp.ptr, hdata->dma_bounce_buffer, 141 memcpy(SCpnt->SCp.ptr, wh->dma_bounce_buffer,
143 SCpnt->SCp.this_residual); 142 SCpnt->SCp.this_residual);
144 kfree(hdata->dma_bounce_buffer); 143 kfree(wh->dma_bounce_buffer);
145 hdata->dma_bounce_buffer = NULL; 144 wh->dma_bounce_buffer = NULL;
146 hdata->dma_bounce_len = 0; 145 wh->dma_bounce_len = 0;
147 }
148}
149
150static int __init a2091_detect(struct scsi_host_template *tpnt)
151{
152 static unsigned char called = 0;
153 struct Scsi_Host *instance;
154 unsigned long address;
155 struct zorro_dev *z = NULL;
156 wd33c93_regs wdregs;
157 a2091_scsiregs *regs;
158 struct WD33C93_hostdata *hdata;
159 int num_a2091 = 0;
160
161 if (!MACH_IS_AMIGA || called)
162 return 0;
163 called = 1;
164
165 tpnt->proc_name = "A2091";
166 tpnt->proc_info = &wd33c93_proc_info;
167
168 while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
169 if (z->id != ZORRO_PROD_CBM_A590_A2091_1 &&
170 z->id != ZORRO_PROD_CBM_A590_A2091_2)
171 continue;
172 address = z->resource.start;
173 if (!request_mem_region(address, 256, "wd33c93"))
174 continue;
175
176 instance = scsi_register(tpnt, sizeof(struct WD33C93_hostdata));
177 if (instance == NULL)
178 goto release;
179 instance->base = ZTWO_VADDR(address);
180 instance->irq = IRQ_AMIGA_PORTS;
181 instance->unique_id = z->slotaddr;
182 regs = (a2091_scsiregs *)(instance->base);
183 regs->DAWR = DAWR_A2091;
184 wdregs.SASR = &regs->SASR;
185 wdregs.SCMD = &regs->SCMD;
186 hdata = shost_priv(instance);
187 hdata->no_sync = 0xff;
188 hdata->fast = 0;
189 hdata->dma_mode = CTRL_DMA;
190 wd33c93_init(instance, wdregs, dma_setup, dma_stop,
191 WD33C93_FS_8_10);
192 if (request_irq(IRQ_AMIGA_PORTS, a2091_intr, IRQF_SHARED,
193 "A2091 SCSI", instance))
194 goto unregister;
195 regs->CNTR = CNTR_PDMD | CNTR_INTEN;
196 num_a2091++;
197 continue;
198
199unregister:
200 scsi_unregister(instance);
201release:
202 release_mem_region(address, 256);
203 } 146 }
204
205 return num_a2091;
206} 147}
207 148
208static int a2091_bus_reset(struct scsi_cmnd *cmd) 149static int a2091_bus_reset(struct scsi_cmnd *cmd)
209{ 150{
151 struct Scsi_Host *instance = cmd->device->host;
152
210 /* FIXME perform bus-specific reset */ 153 /* FIXME perform bus-specific reset */
211 154
212 /* FIXME 2: kill this function, and let midlayer fall back 155 /* FIXME 2: kill this function, and let midlayer fall back
213 to the same action, calling wd33c93_host_reset() */ 156 to the same action, calling wd33c93_host_reset() */
214 157
215 spin_lock_irq(cmd->device->host->host_lock); 158 spin_lock_irq(instance->host_lock);
216 wd33c93_host_reset(cmd); 159 wd33c93_host_reset(cmd);
217 spin_unlock_irq(cmd->device->host->host_lock); 160 spin_unlock_irq(instance->host_lock);
218 161
219 return SUCCESS; 162 return SUCCESS;
220} 163}
221 164
222#define HOSTS_C 165static struct scsi_host_template a2091_scsi_template = {
223 166 .module = THIS_MODULE,
224static struct scsi_host_template driver_template = {
225 .proc_name = "A2901",
226 .name = "Commodore A2091/A590 SCSI", 167 .name = "Commodore A2091/A590 SCSI",
227 .detect = a2091_detect, 168 .proc_info = wd33c93_proc_info,
228 .release = a2091_release, 169 .proc_name = "A2901",
229 .queuecommand = wd33c93_queuecommand, 170 .queuecommand = wd33c93_queuecommand,
230 .eh_abort_handler = wd33c93_abort, 171 .eh_abort_handler = wd33c93_abort,
231 .eh_bus_reset_handler = a2091_bus_reset, 172 .eh_bus_reset_handler = a2091_bus_reset,
@@ -237,19 +178,103 @@ static struct scsi_host_template driver_template = {
237 .use_clustering = DISABLE_CLUSTERING 178 .use_clustering = DISABLE_CLUSTERING
238}; 179};
239 180
181static int __devinit a2091_probe(struct zorro_dev *z,
182 const struct zorro_device_id *ent)
183{
184 struct Scsi_Host *instance;
185 int error;
186 struct a2091_scsiregs *regs;
187 wd33c93_regs wdregs;
188 struct a2091_hostdata *hdata;
240 189
241#include "scsi_module.c" 190 if (!request_mem_region(z->resource.start, 256, "wd33c93"))
191 return -EBUSY;
242 192
243static int a2091_release(struct Scsi_Host *instance) 193 instance = scsi_host_alloc(&a2091_scsi_template,
194 sizeof(struct a2091_hostdata));
195 if (!instance) {
196 error = -ENOMEM;
197 goto fail_alloc;
198 }
199
200 instance->irq = IRQ_AMIGA_PORTS;
201 instance->unique_id = z->slotaddr;
202
203 regs = (struct a2091_scsiregs *)ZTWO_VADDR(z->resource.start);
204 regs->DAWR = DAWR_A2091;
205
206 wdregs.SASR = &regs->SASR;
207 wdregs.SCMD = &regs->SCMD;
208
209 hdata = shost_priv(instance);
210 hdata->wh.no_sync = 0xff;
211 hdata->wh.fast = 0;
212 hdata->wh.dma_mode = CTRL_DMA;
213 hdata->regs = regs;
214
215 wd33c93_init(instance, wdregs, dma_setup, dma_stop, WD33C93_FS_8_10);
216 error = request_irq(IRQ_AMIGA_PORTS, a2091_intr, IRQF_SHARED,
217 "A2091 SCSI", instance);
218 if (error)
219 goto fail_irq;
220
221 regs->CNTR = CNTR_PDMD | CNTR_INTEN;
222
223 error = scsi_add_host(instance, NULL);
224 if (error)
225 goto fail_host;
226
227 zorro_set_drvdata(z, instance);
228
229 scsi_scan_host(instance);
230 return 0;
231
232fail_host:
233 free_irq(IRQ_AMIGA_PORTS, instance);
234fail_irq:
235 scsi_host_put(instance);
236fail_alloc:
237 release_mem_region(z->resource.start, 256);
238 return error;
239}
240
241static void __devexit a2091_remove(struct zorro_dev *z)
244{ 242{
245#ifdef MODULE 243 struct Scsi_Host *instance = zorro_get_drvdata(z);
246 a2091_scsiregs *regs = (a2091_scsiregs *)(instance->base); 244 struct a2091_hostdata *hdata = shost_priv(instance);
247 245
248 regs->CNTR = 0; 246 hdata->regs->CNTR = 0;
249 release_mem_region(ZTWO_PADDR(instance->base), 256); 247 scsi_remove_host(instance);
250 free_irq(IRQ_AMIGA_PORTS, instance); 248 free_irq(IRQ_AMIGA_PORTS, instance);
251#endif 249 scsi_host_put(instance);
252 return 1; 250 release_mem_region(z->resource.start, 256);
251}
252
253static struct zorro_device_id a2091_zorro_tbl[] __devinitdata = {
254 { ZORRO_PROD_CBM_A590_A2091_1 },
255 { ZORRO_PROD_CBM_A590_A2091_2 },
256 { 0 }
257};
258MODULE_DEVICE_TABLE(zorro, a2091_zorro_tbl);
259
260static struct zorro_driver a2091_driver = {
261 .name = "a2091",
262 .id_table = a2091_zorro_tbl,
263 .probe = a2091_probe,
264 .remove = __devexit_p(a2091_remove),
265};
266
267static int __init a2091_init(void)
268{
269 return zorro_register_driver(&a2091_driver);
270}
271module_init(a2091_init);
272
273static void __exit a2091_exit(void)
274{
275 zorro_unregister_driver(&a2091_driver);
253} 276}
277module_exit(a2091_exit);
254 278
279MODULE_DESCRIPTION("Commodore A2091/A590 SCSI");
255MODULE_LICENSE("GPL"); 280MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/a2091.h b/drivers/scsi/a2091.h
index 1c3daa1fd754..794b8e65c711 100644
--- a/drivers/scsi/a2091.h
+++ b/drivers/scsi/a2091.h
@@ -25,7 +25,7 @@
25 */ 25 */
26#define A2091_XFER_MASK (0xff000001) 26#define A2091_XFER_MASK (0xff000001)
27 27
28typedef struct { 28struct a2091_scsiregs {
29 unsigned char pad1[64]; 29 unsigned char pad1[64];
30 volatile unsigned short ISTR; 30 volatile unsigned short ISTR;
31 volatile unsigned short CNTR; 31 volatile unsigned short CNTR;
@@ -44,7 +44,7 @@ typedef struct {
44 volatile unsigned short CINT; 44 volatile unsigned short CINT;
45 unsigned char pad7[2]; 45 unsigned char pad7[2];
46 volatile unsigned short FLUSH; 46 volatile unsigned short FLUSH;
47} a2091_scsiregs; 47};
48 48
49#define DAWR_A2091 (3) 49#define DAWR_A2091 (3)
50 50
diff --git a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c
index bc6eb69f5fd0..d9468027fb61 100644
--- a/drivers/scsi/a3000.c
+++ b/drivers/scsi/a3000.c
@@ -1,53 +1,52 @@
1#include <linux/types.h> 1#include <linux/types.h>
2#include <linux/mm.h> 2#include <linux/mm.h>
3#include <linux/slab.h>
4#include <linux/blkdev.h>
5#include <linux/ioport.h> 3#include <linux/ioport.h>
6#include <linux/init.h> 4#include <linux/init.h>
5#include <linux/slab.h>
7#include <linux/spinlock.h> 6#include <linux/spinlock.h>
8#include <linux/interrupt.h> 7#include <linux/interrupt.h>
8#include <linux/platform_device.h>
9 9
10#include <asm/setup.h>
11#include <asm/page.h> 10#include <asm/page.h>
12#include <asm/pgtable.h> 11#include <asm/pgtable.h>
13#include <asm/amigaints.h> 12#include <asm/amigaints.h>
14#include <asm/amigahw.h> 13#include <asm/amigahw.h>
15#include <asm/irq.h>
16 14
17#include "scsi.h" 15#include "scsi.h"
18#include <scsi/scsi_host.h>
19#include "wd33c93.h" 16#include "wd33c93.h"
20#include "a3000.h" 17#include "a3000.h"
21 18
22#include <linux/stat.h>
23
24 19
25#define DMA(ptr) ((a3000_scsiregs *)((ptr)->base)) 20struct a3000_hostdata {
26 21 struct WD33C93_hostdata wh;
27static struct Scsi_Host *a3000_host = NULL; 22 struct a3000_scsiregs *regs;
28 23};
29static int a3000_release(struct Scsi_Host *instance);
30 24
31static irqreturn_t a3000_intr(int irq, void *dummy) 25static irqreturn_t a3000_intr(int irq, void *data)
32{ 26{
27 struct Scsi_Host *instance = data;
28 struct a3000_hostdata *hdata = shost_priv(instance);
29 unsigned int status = hdata->regs->ISTR;
33 unsigned long flags; 30 unsigned long flags;
34 unsigned int status = DMA(a3000_host)->ISTR;
35 31
36 if (!(status & ISTR_INT_P)) 32 if (!(status & ISTR_INT_P))
37 return IRQ_NONE; 33 return IRQ_NONE;
38 if (status & ISTR_INTS) { 34 if (status & ISTR_INTS) {
39 spin_lock_irqsave(a3000_host->host_lock, flags); 35 spin_lock_irqsave(instance->host_lock, flags);
40 wd33c93_intr(a3000_host); 36 wd33c93_intr(instance);
41 spin_unlock_irqrestore(a3000_host->host_lock, flags); 37 spin_unlock_irqrestore(instance->host_lock, flags);
42 return IRQ_HANDLED; 38 return IRQ_HANDLED;
43 } 39 }
44 printk("Non-serviced A3000 SCSI-interrupt? ISTR = %02x\n", status); 40 pr_warning("Non-serviced A3000 SCSI-interrupt? ISTR = %02x\n", status);
45 return IRQ_NONE; 41 return IRQ_NONE;
46} 42}
47 43
48static int dma_setup(struct scsi_cmnd *cmd, int dir_in) 44static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
49{ 45{
50 struct WD33C93_hostdata *hdata = shost_priv(a3000_host); 46 struct Scsi_Host *instance = cmd->device->host;
47 struct a3000_hostdata *hdata = shost_priv(instance);
48 struct WD33C93_hostdata *wh = &hdata->wh;
49 struct a3000_scsiregs *regs = hdata->regs;
51 unsigned short cntr = CNTR_PDMD | CNTR_INTEN; 50 unsigned short cntr = CNTR_PDMD | CNTR_INTEN;
52 unsigned long addr = virt_to_bus(cmd->SCp.ptr); 51 unsigned long addr = virt_to_bus(cmd->SCp.ptr);
53 52
@@ -58,23 +57,23 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
58 * buffer 57 * buffer
59 */ 58 */
60 if (addr & A3000_XFER_MASK) { 59 if (addr & A3000_XFER_MASK) {
61 hdata->dma_bounce_len = (cmd->SCp.this_residual + 511) & ~0x1ff; 60 wh->dma_bounce_len = (cmd->SCp.this_residual + 511) & ~0x1ff;
62 hdata->dma_bounce_buffer = kmalloc(hdata->dma_bounce_len, 61 wh->dma_bounce_buffer = kmalloc(wh->dma_bounce_len,
63 GFP_KERNEL); 62 GFP_KERNEL);
64 63
65 /* can't allocate memory; use PIO */ 64 /* can't allocate memory; use PIO */
66 if (!hdata->dma_bounce_buffer) { 65 if (!wh->dma_bounce_buffer) {
67 hdata->dma_bounce_len = 0; 66 wh->dma_bounce_len = 0;
68 return 1; 67 return 1;
69 } 68 }
70 69
71 if (!dir_in) { 70 if (!dir_in) {
72 /* copy to bounce buffer for a write */ 71 /* copy to bounce buffer for a write */
73 memcpy(hdata->dma_bounce_buffer, cmd->SCp.ptr, 72 memcpy(wh->dma_bounce_buffer, cmd->SCp.ptr,
74 cmd->SCp.this_residual); 73 cmd->SCp.this_residual);
75 } 74 }
76 75
77 addr = virt_to_bus(hdata->dma_bounce_buffer); 76 addr = virt_to_bus(wh->dma_bounce_buffer);
78 } 77 }
79 78
80 /* setup dma direction */ 79 /* setup dma direction */
@@ -82,12 +81,12 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
82 cntr |= CNTR_DDIR; 81 cntr |= CNTR_DDIR;
83 82
84 /* remember direction */ 83 /* remember direction */
85 hdata->dma_dir = dir_in; 84 wh->dma_dir = dir_in;
86 85
87 DMA(a3000_host)->CNTR = cntr; 86 regs->CNTR = cntr;
88 87
89 /* setup DMA *physical* address */ 88 /* setup DMA *physical* address */
90 DMA(a3000_host)->ACR = addr; 89 regs->ACR = addr;
91 90
92 if (dir_in) { 91 if (dir_in) {
93 /* invalidate any cache */ 92 /* invalidate any cache */
@@ -99,7 +98,7 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
99 98
100 /* start DMA */ 99 /* start DMA */
101 mb(); /* make sure setup is completed */ 100 mb(); /* make sure setup is completed */
102 DMA(a3000_host)->ST_DMA = 1; 101 regs->ST_DMA = 1;
103 mb(); /* make sure DMA has started before next IO */ 102 mb(); /* make sure DMA has started before next IO */
104 103
105 /* return success */ 104 /* return success */
@@ -109,22 +108,24 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
109static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, 108static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt,
110 int status) 109 int status)
111{ 110{
112 struct WD33C93_hostdata *hdata = shost_priv(instance); 111 struct a3000_hostdata *hdata = shost_priv(instance);
112 struct WD33C93_hostdata *wh = &hdata->wh;
113 struct a3000_scsiregs *regs = hdata->regs;
113 114
114 /* disable SCSI interrupts */ 115 /* disable SCSI interrupts */
115 unsigned short cntr = CNTR_PDMD; 116 unsigned short cntr = CNTR_PDMD;
116 117
117 if (!hdata->dma_dir) 118 if (!wh->dma_dir)
118 cntr |= CNTR_DDIR; 119 cntr |= CNTR_DDIR;
119 120
120 DMA(instance)->CNTR = cntr; 121 regs->CNTR = cntr;
121 mb(); /* make sure CNTR is updated before next IO */ 122 mb(); /* make sure CNTR is updated before next IO */
122 123
123 /* flush if we were reading */ 124 /* flush if we were reading */
124 if (hdata->dma_dir) { 125 if (wh->dma_dir) {
125 DMA(instance)->FLUSH = 1; 126 regs->FLUSH = 1;
126 mb(); /* don't allow prefetch */ 127 mb(); /* don't allow prefetch */
127 while (!(DMA(instance)->ISTR & ISTR_FE_FLG)) 128 while (!(regs->ISTR & ISTR_FE_FLG))
128 barrier(); 129 barrier();
129 mb(); /* no IO until FLUSH is done */ 130 mb(); /* no IO until FLUSH is done */
130 } 131 }
@@ -133,96 +134,54 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt,
133 /* I think that this CINT is only necessary if you are 134 /* I think that this CINT is only necessary if you are
134 * using the terminal count features. HM 7 Mar 1994 135 * using the terminal count features. HM 7 Mar 1994
135 */ 136 */
136 DMA(instance)->CINT = 1; 137 regs->CINT = 1;
137 138
138 /* stop DMA */ 139 /* stop DMA */
139 DMA(instance)->SP_DMA = 1; 140 regs->SP_DMA = 1;
140 mb(); /* make sure DMA is stopped before next IO */ 141 mb(); /* make sure DMA is stopped before next IO */
141 142
142 /* restore the CONTROL bits (minus the direction flag) */ 143 /* restore the CONTROL bits (minus the direction flag) */
143 DMA(instance)->CNTR = CNTR_PDMD | CNTR_INTEN; 144 regs->CNTR = CNTR_PDMD | CNTR_INTEN;
144 mb(); /* make sure CNTR is updated before next IO */ 145 mb(); /* make sure CNTR is updated before next IO */
145 146
146 /* copy from a bounce buffer, if necessary */ 147 /* copy from a bounce buffer, if necessary */
147 if (status && hdata->dma_bounce_buffer) { 148 if (status && wh->dma_bounce_buffer) {
148 if (SCpnt) { 149 if (SCpnt) {
149 if (hdata->dma_dir && SCpnt) 150 if (wh->dma_dir && SCpnt)
150 memcpy(SCpnt->SCp.ptr, 151 memcpy(SCpnt->SCp.ptr, wh->dma_bounce_buffer,
151 hdata->dma_bounce_buffer,
152 SCpnt->SCp.this_residual); 152 SCpnt->SCp.this_residual);
153 kfree(hdata->dma_bounce_buffer); 153 kfree(wh->dma_bounce_buffer);
154 hdata->dma_bounce_buffer = NULL; 154 wh->dma_bounce_buffer = NULL;
155 hdata->dma_bounce_len = 0; 155 wh->dma_bounce_len = 0;
156 } else { 156 } else {
157 kfree(hdata->dma_bounce_buffer); 157 kfree(wh->dma_bounce_buffer);
158 hdata->dma_bounce_buffer = NULL; 158 wh->dma_bounce_buffer = NULL;
159 hdata->dma_bounce_len = 0; 159 wh->dma_bounce_len = 0;
160 } 160 }
161 } 161 }
162} 162}
163 163
164static int __init a3000_detect(struct scsi_host_template *tpnt)
165{
166 wd33c93_regs regs;
167 struct WD33C93_hostdata *hdata;
168
169 if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(A3000_SCSI))
170 return 0;
171 if (!request_mem_region(0xDD0000, 256, "wd33c93"))
172 return 0;
173
174 tpnt->proc_name = "A3000";
175 tpnt->proc_info = &wd33c93_proc_info;
176
177 a3000_host = scsi_register(tpnt, sizeof(struct WD33C93_hostdata));
178 if (a3000_host == NULL)
179 goto fail_register;
180
181 a3000_host->base = ZTWO_VADDR(0xDD0000);
182 a3000_host->irq = IRQ_AMIGA_PORTS;
183 DMA(a3000_host)->DAWR = DAWR_A3000;
184 regs.SASR = &(DMA(a3000_host)->SASR);
185 regs.SCMD = &(DMA(a3000_host)->SCMD);
186 hdata = shost_priv(a3000_host);
187 hdata->no_sync = 0xff;
188 hdata->fast = 0;
189 hdata->dma_mode = CTRL_DMA;
190 wd33c93_init(a3000_host, regs, dma_setup, dma_stop, WD33C93_FS_12_15);
191 if (request_irq(IRQ_AMIGA_PORTS, a3000_intr, IRQF_SHARED, "A3000 SCSI",
192 a3000_intr))
193 goto fail_irq;
194 DMA(a3000_host)->CNTR = CNTR_PDMD | CNTR_INTEN;
195
196 return 1;
197
198fail_irq:
199 scsi_unregister(a3000_host);
200fail_register:
201 release_mem_region(0xDD0000, 256);
202 return 0;
203}
204
205static int a3000_bus_reset(struct scsi_cmnd *cmd) 164static int a3000_bus_reset(struct scsi_cmnd *cmd)
206{ 165{
166 struct Scsi_Host *instance = cmd->device->host;
167
207 /* FIXME perform bus-specific reset */ 168 /* FIXME perform bus-specific reset */
208 169
209 /* FIXME 2: kill this entire function, which should 170 /* FIXME 2: kill this entire function, which should
210 cause mid-layer to call wd33c93_host_reset anyway? */ 171 cause mid-layer to call wd33c93_host_reset anyway? */
211 172
212 spin_lock_irq(cmd->device->host->host_lock); 173 spin_lock_irq(instance->host_lock);
213 wd33c93_host_reset(cmd); 174 wd33c93_host_reset(cmd);
214 spin_unlock_irq(cmd->device->host->host_lock); 175 spin_unlock_irq(instance->host_lock);
215 176
216 return SUCCESS; 177 return SUCCESS;
217} 178}
218 179
219#define HOSTS_C 180static struct scsi_host_template amiga_a3000_scsi_template = {
220 181 .module = THIS_MODULE,
221static struct scsi_host_template driver_template = {
222 .proc_name = "A3000",
223 .name = "Amiga 3000 built-in SCSI", 182 .name = "Amiga 3000 built-in SCSI",
224 .detect = a3000_detect, 183 .proc_info = wd33c93_proc_info,
225 .release = a3000_release, 184 .proc_name = "A3000",
226 .queuecommand = wd33c93_queuecommand, 185 .queuecommand = wd33c93_queuecommand,
227 .eh_abort_handler = wd33c93_abort, 186 .eh_abort_handler = wd33c93_abort,
228 .eh_bus_reset_handler = a3000_bus_reset, 187 .eh_bus_reset_handler = a3000_bus_reset,
@@ -234,15 +193,104 @@ static struct scsi_host_template driver_template = {
234 .use_clustering = ENABLE_CLUSTERING 193 .use_clustering = ENABLE_CLUSTERING
235}; 194};
236 195
196static int __init amiga_a3000_scsi_probe(struct platform_device *pdev)
197{
198 struct resource *res;
199 struct Scsi_Host *instance;
200 int error;
201 struct a3000_scsiregs *regs;
202 wd33c93_regs wdregs;
203 struct a3000_hostdata *hdata;
204
205 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
206 if (!res)
207 return -ENODEV;
208
209 if (!request_mem_region(res->start, resource_size(res), "wd33c93"))
210 return -EBUSY;
211
212 instance = scsi_host_alloc(&amiga_a3000_scsi_template,
213 sizeof(struct a3000_hostdata));
214 if (!instance) {
215 error = -ENOMEM;
216 goto fail_alloc;
217 }
218
219 instance->irq = IRQ_AMIGA_PORTS;
237 220
238#include "scsi_module.c" 221 regs = (struct a3000_scsiregs *)ZTWO_VADDR(res->start);
222 regs->DAWR = DAWR_A3000;
223
224 wdregs.SASR = &regs->SASR;
225 wdregs.SCMD = &regs->SCMD;
226
227 hdata = shost_priv(instance);
228 hdata->wh.no_sync = 0xff;
229 hdata->wh.fast = 0;
230 hdata->wh.dma_mode = CTRL_DMA;
231 hdata->regs = regs;
232
233 wd33c93_init(instance, wdregs, dma_setup, dma_stop, WD33C93_FS_12_15);
234 error = request_irq(IRQ_AMIGA_PORTS, a3000_intr, IRQF_SHARED,
235 "A3000 SCSI", instance);
236 if (error)
237 goto fail_irq;
238
239 regs->CNTR = CNTR_PDMD | CNTR_INTEN;
240
241 error = scsi_add_host(instance, NULL);
242 if (error)
243 goto fail_host;
244
245 platform_set_drvdata(pdev, instance);
246
247 scsi_scan_host(instance);
248 return 0;
249
250fail_host:
251 free_irq(IRQ_AMIGA_PORTS, instance);
252fail_irq:
253 scsi_host_put(instance);
254fail_alloc:
255 release_mem_region(res->start, resource_size(res));
256 return error;
257}
258
259static int __exit amiga_a3000_scsi_remove(struct platform_device *pdev)
260{
261 struct Scsi_Host *instance = platform_get_drvdata(pdev);
262 struct a3000_hostdata *hdata = shost_priv(instance);
263 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
264
265 hdata->regs->CNTR = 0;
266 scsi_remove_host(instance);
267 free_irq(IRQ_AMIGA_PORTS, instance);
268 scsi_host_put(instance);
269 release_mem_region(res->start, resource_size(res));
270 return 0;
271}
272
273static struct platform_driver amiga_a3000_scsi_driver = {
274 .remove = __exit_p(amiga_a3000_scsi_remove),
275 .driver = {
276 .name = "amiga-a3000-scsi",
277 .owner = THIS_MODULE,
278 },
279};
280
281static int __init amiga_a3000_scsi_init(void)
282{
283 return platform_driver_probe(&amiga_a3000_scsi_driver,
284 amiga_a3000_scsi_probe);
285}
286module_init(amiga_a3000_scsi_init);
239 287
240static int a3000_release(struct Scsi_Host *instance) 288static void __exit amiga_a3000_scsi_exit(void)
241{ 289{
242 DMA(instance)->CNTR = 0; 290 platform_driver_unregister(&amiga_a3000_scsi_driver);
243 release_mem_region(0xDD0000, 256);
244 free_irq(IRQ_AMIGA_PORTS, a3000_intr);
245 return 1;
246} 291}
292module_exit(amiga_a3000_scsi_exit);
247 293
294MODULE_DESCRIPTION("Amiga 3000 built-in SCSI");
248MODULE_LICENSE("GPL"); 295MODULE_LICENSE("GPL");
296MODULE_ALIAS("platform:amiga-a3000-scsi");
diff --git a/drivers/scsi/a3000.h b/drivers/scsi/a3000.h
index 684813ee378c..49db4a335aab 100644
--- a/drivers/scsi/a3000.h
+++ b/drivers/scsi/a3000.h
@@ -25,7 +25,7 @@
25 */ 25 */
26#define A3000_XFER_MASK (0x00000003) 26#define A3000_XFER_MASK (0x00000003)
27 27
28typedef struct { 28struct a3000_scsiregs {
29 unsigned char pad1[2]; 29 unsigned char pad1[2];
30 volatile unsigned short DAWR; 30 volatile unsigned short DAWR;
31 volatile unsigned int WTC; 31 volatile unsigned int WTC;
@@ -46,7 +46,7 @@ typedef struct {
46 volatile unsigned char SASR; 46 volatile unsigned char SASR;
47 unsigned char pad9; 47 unsigned char pad9;
48 volatile unsigned char SCMD; 48 volatile unsigned char SCMD;
49} a3000_scsiregs; 49};
50 50
51#define DAWR_A3000 (3) 51#define DAWR_A3000 (3)
52 52
diff --git a/drivers/scsi/a4000t.c b/drivers/scsi/a4000t.c
index 11ae6be8aeaf..23c76f41883c 100644
--- a/drivers/scsi/a4000t.c
+++ b/drivers/scsi/a4000t.c
@@ -20,10 +20,6 @@
20 20
21#include "53c700.h" 21#include "53c700.h"
22 22
23MODULE_AUTHOR("Alan Hourihane <alanh@fairlite.demon.co.uk> / Kars de Jong <jongk@linux-m68k.org>");
24MODULE_DESCRIPTION("Amiga A4000T NCR53C710 driver");
25MODULE_LICENSE("GPL");
26
27 23
28static struct scsi_host_template a4000t_scsi_driver_template = { 24static struct scsi_host_template a4000t_scsi_driver_template = {
29 .name = "A4000T builtin SCSI", 25 .name = "A4000T builtin SCSI",
@@ -32,30 +28,35 @@ static struct scsi_host_template a4000t_scsi_driver_template = {
32 .module = THIS_MODULE, 28 .module = THIS_MODULE,
33}; 29};
34 30
35static struct platform_device *a4000t_scsi_device;
36 31
37#define A4000T_SCSI_ADDR 0xdd0040 32#define A4000T_SCSI_OFFSET 0x40
38 33
39static int __devinit a4000t_probe(struct platform_device *dev) 34static int __init amiga_a4000t_scsi_probe(struct platform_device *pdev)
40{ 35{
41 struct Scsi_Host *host; 36 struct resource *res;
37 phys_addr_t scsi_addr;
42 struct NCR_700_Host_Parameters *hostdata; 38 struct NCR_700_Host_Parameters *hostdata;
39 struct Scsi_Host *host;
43 40
44 if (!(MACH_IS_AMIGA && AMIGAHW_PRESENT(A4000_SCSI))) 41 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
45 goto out; 42 if (!res)
43 return -ENODEV;
46 44
47 if (!request_mem_region(A4000T_SCSI_ADDR, 0x1000, 45 if (!request_mem_region(res->start, resource_size(res),
48 "A4000T builtin SCSI")) 46 "A4000T builtin SCSI"))
49 goto out; 47 return -EBUSY;
50 48
51 hostdata = kzalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL); 49 hostdata = kzalloc(sizeof(struct NCR_700_Host_Parameters),
50 GFP_KERNEL);
52 if (!hostdata) { 51 if (!hostdata) {
53 printk(KERN_ERR "a4000t-scsi: Failed to allocate host data\n"); 52 dev_err(&pdev->dev, "Failed to allocate host data\n");
54 goto out_release; 53 goto out_release;
55 } 54 }
56 55
56 scsi_addr = res->start + A4000T_SCSI_OFFSET;
57
57 /* Fill in the required pieces of hostdata */ 58 /* Fill in the required pieces of hostdata */
58 hostdata->base = (void __iomem *)ZTWO_VADDR(A4000T_SCSI_ADDR); 59 hostdata->base = (void __iomem *)ZTWO_VADDR(scsi_addr);
59 hostdata->clock = 50; 60 hostdata->clock = 50;
60 hostdata->chip710 = 1; 61 hostdata->chip710 = 1;
61 hostdata->dmode_extra = DMODE_FC2; 62 hostdata->dmode_extra = DMODE_FC2;
@@ -63,26 +64,25 @@ static int __devinit a4000t_probe(struct platform_device *dev)
63 64
64 /* and register the chip */ 65 /* and register the chip */
65 host = NCR_700_detect(&a4000t_scsi_driver_template, hostdata, 66 host = NCR_700_detect(&a4000t_scsi_driver_template, hostdata,
66 &dev->dev); 67 &pdev->dev);
67 if (!host) { 68 if (!host) {
68 printk(KERN_ERR "a4000t-scsi: No host detected; " 69 dev_err(&pdev->dev,
69 "board configuration problem?\n"); 70 "No host detected; board configuration problem?\n");
70 goto out_free; 71 goto out_free;
71 } 72 }
72 73
73 host->this_id = 7; 74 host->this_id = 7;
74 host->base = A4000T_SCSI_ADDR; 75 host->base = scsi_addr;
75 host->irq = IRQ_AMIGA_PORTS; 76 host->irq = IRQ_AMIGA_PORTS;
76 77
77 if (request_irq(host->irq, NCR_700_intr, IRQF_SHARED, "a4000t-scsi", 78 if (request_irq(host->irq, NCR_700_intr, IRQF_SHARED, "a4000t-scsi",
78 host)) { 79 host)) {
79 printk(KERN_ERR "a4000t-scsi: request_irq failed\n"); 80 dev_err(&pdev->dev, "request_irq failed\n");
80 goto out_put_host; 81 goto out_put_host;
81 } 82 }
82 83
83 platform_set_drvdata(dev, host); 84 platform_set_drvdata(pdev, host);
84 scsi_scan_host(host); 85 scsi_scan_host(host);
85
86 return 0; 86 return 0;
87 87
88 out_put_host: 88 out_put_host:
@@ -90,58 +90,49 @@ static int __devinit a4000t_probe(struct platform_device *dev)
90 out_free: 90 out_free:
91 kfree(hostdata); 91 kfree(hostdata);
92 out_release: 92 out_release:
93 release_mem_region(A4000T_SCSI_ADDR, 0x1000); 93 release_mem_region(res->start, resource_size(res));
94 out:
95 return -ENODEV; 94 return -ENODEV;
96} 95}
97 96
98static __devexit int a4000t_device_remove(struct platform_device *dev) 97static int __exit amiga_a4000t_scsi_remove(struct platform_device *pdev)
99{ 98{
100 struct Scsi_Host *host = platform_get_drvdata(dev); 99 struct Scsi_Host *host = platform_get_drvdata(pdev);
101 struct NCR_700_Host_Parameters *hostdata = shost_priv(host); 100 struct NCR_700_Host_Parameters *hostdata = shost_priv(host);
101 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
102 102
103 scsi_remove_host(host); 103 scsi_remove_host(host);
104
105 NCR_700_release(host); 104 NCR_700_release(host);
106 kfree(hostdata); 105 kfree(hostdata);
107 free_irq(host->irq, host); 106 free_irq(host->irq, host);
108 release_mem_region(A4000T_SCSI_ADDR, 0x1000); 107 release_mem_region(res->start, resource_size(res));
109
110 return 0; 108 return 0;
111} 109}
112 110
113static struct platform_driver a4000t_scsi_driver = { 111static struct platform_driver amiga_a4000t_scsi_driver = {
114 .driver = { 112 .remove = __exit_p(amiga_a4000t_scsi_remove),
115 .name = "a4000t-scsi", 113 .driver = {
116 .owner = THIS_MODULE, 114 .name = "amiga-a4000t-scsi",
115 .owner = THIS_MODULE,
117 }, 116 },
118 .probe = a4000t_probe,
119 .remove = __devexit_p(a4000t_device_remove),
120}; 117};
121 118
122static int __init a4000t_scsi_init(void) 119static int __init amiga_a4000t_scsi_init(void)
123{ 120{
124 int err; 121 return platform_driver_probe(&amiga_a4000t_scsi_driver,
125 122 amiga_a4000t_scsi_probe);
126 err = platform_driver_register(&a4000t_scsi_driver);
127 if (err)
128 return err;
129
130 a4000t_scsi_device = platform_device_register_simple("a4000t-scsi",
131 -1, NULL, 0);
132 if (IS_ERR(a4000t_scsi_device)) {
133 platform_driver_unregister(&a4000t_scsi_driver);
134 return PTR_ERR(a4000t_scsi_device);
135 }
136
137 return err;
138} 123}
139 124
140static void __exit a4000t_scsi_exit(void) 125module_init(amiga_a4000t_scsi_init);
126
127static void __exit amiga_a4000t_scsi_exit(void)
141{ 128{
142 platform_device_unregister(a4000t_scsi_device); 129 platform_driver_unregister(&amiga_a4000t_scsi_driver);
143 platform_driver_unregister(&a4000t_scsi_driver);
144} 130}
145 131
146module_init(a4000t_scsi_init); 132module_exit(amiga_a4000t_scsi_exit);
147module_exit(a4000t_scsi_exit); 133
134MODULE_AUTHOR("Alan Hourihane <alanh@fairlite.demon.co.uk> / "
135 "Kars de Jong <jongk@linux-m68k.org>");
136MODULE_DESCRIPTION("Amiga A4000T NCR53C710 driver");
137MODULE_LICENSE("GPL");
138MODULE_ALIAS("platform:amiga-a4000t-scsi");
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index 9c0c91178538..1a5bf5724750 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -655,9 +655,9 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
655 /* Does this really need to be GFP_DMA? */ 655 /* Does this really need to be GFP_DMA? */
656 p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA); 656 p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA);
657 if(!p) { 657 if(!p) {
658 kfree (usg); 658 dprintk((KERN_DEBUG "aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
659 dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
660 usg->sg[i].count,i,usg->count)); 659 usg->sg[i].count,i,usg->count));
660 kfree(usg);
661 rcode = -ENOMEM; 661 rcode = -ENOMEM;
662 goto cleanup; 662 goto cleanup;
663 } 663 }
diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h
index ab646e580d64..ce5371b3cdd5 100644
--- a/drivers/scsi/arcmsr/arcmsr.h
+++ b/drivers/scsi/arcmsr/arcmsr.h
@@ -48,7 +48,7 @@ struct device_attribute;
48/*The limit of outstanding scsi command that firmware can handle*/ 48/*The limit of outstanding scsi command that firmware can handle*/
49#define ARCMSR_MAX_OUTSTANDING_CMD 256 49#define ARCMSR_MAX_OUTSTANDING_CMD 256
50#define ARCMSR_MAX_FREECCB_NUM 320 50#define ARCMSR_MAX_FREECCB_NUM 320
51#define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.15 2008/02/27" 51#define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.15 2008/11/03"
52#define ARCMSR_SCSI_INITIATOR_ID 255 52#define ARCMSR_SCSI_INITIATOR_ID 255
53#define ARCMSR_MAX_XFER_SECTORS 512 53#define ARCMSR_MAX_XFER_SECTORS 512
54#define ARCMSR_MAX_XFER_SECTORS_B 4096 54#define ARCMSR_MAX_XFER_SECTORS_B 4096
@@ -110,6 +110,8 @@ struct CMD_MESSAGE_FIELD
110#define FUNCTION_SAY_HELLO 0x0807 110#define FUNCTION_SAY_HELLO 0x0807
111#define FUNCTION_SAY_GOODBYE 0x0808 111#define FUNCTION_SAY_GOODBYE 0x0808
112#define FUNCTION_FLUSH_ADAPTER_CACHE 0x0809 112#define FUNCTION_FLUSH_ADAPTER_CACHE 0x0809
113#define FUNCTION_GET_FIRMWARE_STATUS 0x080A
114#define FUNCTION_HARDWARE_RESET 0x080B
113/* ARECA IO CONTROL CODE*/ 115/* ARECA IO CONTROL CODE*/
114#define ARCMSR_MESSAGE_READ_RQBUFFER \ 116#define ARCMSR_MESSAGE_READ_RQBUFFER \
115 ARECA_SATA_RAID | FUNCTION_READ_RQBUFFER 117 ARECA_SATA_RAID | FUNCTION_READ_RQBUFFER
@@ -133,6 +135,7 @@ struct CMD_MESSAGE_FIELD
133#define ARCMSR_MESSAGE_RETURNCODE_OK 0x00000001 135#define ARCMSR_MESSAGE_RETURNCODE_OK 0x00000001
134#define ARCMSR_MESSAGE_RETURNCODE_ERROR 0x00000006 136#define ARCMSR_MESSAGE_RETURNCODE_ERROR 0x00000006
135#define ARCMSR_MESSAGE_RETURNCODE_3F 0x0000003F 137#define ARCMSR_MESSAGE_RETURNCODE_3F 0x0000003F
138#define ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON 0x00000088
136/* 139/*
137************************************************************* 140*************************************************************
138** structure for holding DMA address data 141** structure for holding DMA address data
@@ -341,13 +344,13 @@ struct MessageUnit_B
341 uint32_t done_qbuffer[ARCMSR_MAX_HBB_POSTQUEUE]; 344 uint32_t done_qbuffer[ARCMSR_MAX_HBB_POSTQUEUE];
342 uint32_t postq_index; 345 uint32_t postq_index;
343 uint32_t doneq_index; 346 uint32_t doneq_index;
344 void __iomem *drv2iop_doorbell_reg; 347 uint32_t __iomem *drv2iop_doorbell_reg;
345 void __iomem *drv2iop_doorbell_mask_reg; 348 uint32_t __iomem *drv2iop_doorbell_mask_reg;
346 void __iomem *iop2drv_doorbell_reg; 349 uint32_t __iomem *iop2drv_doorbell_reg;
347 void __iomem *iop2drv_doorbell_mask_reg; 350 uint32_t __iomem *iop2drv_doorbell_mask_reg;
348 void __iomem *msgcode_rwbuffer_reg; 351 uint32_t __iomem *msgcode_rwbuffer_reg;
349 void __iomem *ioctl_wbuffer_reg; 352 uint32_t __iomem *ioctl_wbuffer_reg;
350 void __iomem *ioctl_rbuffer_reg; 353 uint32_t __iomem *ioctl_rbuffer_reg;
351}; 354};
352 355
353/* 356/*
@@ -375,6 +378,7 @@ struct AdapterControlBlock
375 /* message unit ATU inbound base address0 */ 378 /* message unit ATU inbound base address0 */
376 379
377 uint32_t acb_flags; 380 uint32_t acb_flags;
381 uint8_t adapter_index;
378 #define ACB_F_SCSISTOPADAPTER 0x0001 382 #define ACB_F_SCSISTOPADAPTER 0x0001
379 #define ACB_F_MSG_STOP_BGRB 0x0002 383 #define ACB_F_MSG_STOP_BGRB 0x0002
380 /* stop RAID background rebuild */ 384 /* stop RAID background rebuild */
@@ -390,7 +394,7 @@ struct AdapterControlBlock
390 #define ACB_F_BUS_RESET 0x0080 394 #define ACB_F_BUS_RESET 0x0080
391 #define ACB_F_IOP_INITED 0x0100 395 #define ACB_F_IOP_INITED 0x0100
392 /* iop init */ 396 /* iop init */
393 397 #define ACB_F_FIRMWARE_TRAP 0x0400
394 struct CommandControlBlock * pccb_pool[ARCMSR_MAX_FREECCB_NUM]; 398 struct CommandControlBlock * pccb_pool[ARCMSR_MAX_FREECCB_NUM];
395 /* used for memory free */ 399 /* used for memory free */
396 struct list_head ccb_free_list; 400 struct list_head ccb_free_list;
@@ -423,12 +427,19 @@ struct AdapterControlBlock
423#define ARECA_RAID_GOOD 0xaa 427#define ARECA_RAID_GOOD 0xaa
424 uint32_t num_resets; 428 uint32_t num_resets;
425 uint32_t num_aborts; 429 uint32_t num_aborts;
430 uint32_t signature;
426 uint32_t firm_request_len; 431 uint32_t firm_request_len;
427 uint32_t firm_numbers_queue; 432 uint32_t firm_numbers_queue;
428 uint32_t firm_sdram_size; 433 uint32_t firm_sdram_size;
429 uint32_t firm_hd_channels; 434 uint32_t firm_hd_channels;
430 char firm_model[12]; 435 char firm_model[12];
431 char firm_version[20]; 436 char firm_version[20];
437 char device_map[20]; /*21,84-99*/
438 struct work_struct arcmsr_do_message_isr_bh;
439 struct timer_list eternal_timer;
440 unsigned short fw_state;
441 atomic_t rq_map_token;
442 int ante_token_value;
432};/* HW_DEVICE_EXTENSION */ 443};/* HW_DEVICE_EXTENSION */
433/* 444/*
434******************************************************************************* 445*******************************************************************************
diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c
index a4e04c50c436..07fdfe57e38e 100644
--- a/drivers/scsi/arcmsr/arcmsr_attr.c
+++ b/drivers/scsi/arcmsr/arcmsr_attr.c
@@ -192,6 +192,7 @@ static struct bin_attribute arcmsr_sysfs_message_read_attr = {
192 .attr = { 192 .attr = {
193 .name = "mu_read", 193 .name = "mu_read",
194 .mode = S_IRUSR , 194 .mode = S_IRUSR ,
195 .owner = THIS_MODULE,
195 }, 196 },
196 .size = 1032, 197 .size = 1032,
197 .read = arcmsr_sysfs_iop_message_read, 198 .read = arcmsr_sysfs_iop_message_read,
@@ -201,6 +202,7 @@ static struct bin_attribute arcmsr_sysfs_message_write_attr = {
201 .attr = { 202 .attr = {
202 .name = "mu_write", 203 .name = "mu_write",
203 .mode = S_IWUSR, 204 .mode = S_IWUSR,
205 .owner = THIS_MODULE,
204 }, 206 },
205 .size = 1032, 207 .size = 1032,
206 .write = arcmsr_sysfs_iop_message_write, 208 .write = arcmsr_sysfs_iop_message_write,
@@ -210,6 +212,7 @@ static struct bin_attribute arcmsr_sysfs_message_clear_attr = {
210 .attr = { 212 .attr = {
211 .name = "mu_clear", 213 .name = "mu_clear",
212 .mode = S_IWUSR, 214 .mode = S_IWUSR,
215 .owner = THIS_MODULE,
213 }, 216 },
214 .size = 1, 217 .size = 1,
215 .write = arcmsr_sysfs_iop_message_clear, 218 .write = arcmsr_sysfs_iop_message_clear,
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
index ffbe2192da3c..ffa54792bb33 100644
--- a/drivers/scsi/arcmsr/arcmsr_hba.c
+++ b/drivers/scsi/arcmsr/arcmsr_hba.c
@@ -72,8 +72,16 @@
72#include <scsi/scsicam.h> 72#include <scsi/scsicam.h>
73#include "arcmsr.h" 73#include "arcmsr.h"
74 74
75#ifdef CONFIG_SCSI_ARCMSR_RESET
76 static int sleeptime = 20;
77 static int retrycount = 12;
78 module_param(sleeptime, int, S_IRUGO|S_IWUSR);
79 MODULE_PARM_DESC(sleeptime, "The waiting period for FW ready while bus reset");
80 module_param(retrycount, int, S_IRUGO|S_IWUSR);
81 MODULE_PARM_DESC(retrycount, "The retry count for FW ready while bus reset");
82#endif
75MODULE_AUTHOR("Erich Chen <support@areca.com.tw>"); 83MODULE_AUTHOR("Erich Chen <support@areca.com.tw>");
76MODULE_DESCRIPTION("ARECA (ARC11xx/12xx/13xx/16xx) SATA/SAS RAID HOST Adapter"); 84MODULE_DESCRIPTION("ARECA (ARC11xx/12xx/13xx/16xx) SATA/SAS RAID Host Bus Adapter");
77MODULE_LICENSE("Dual BSD/GPL"); 85MODULE_LICENSE("Dual BSD/GPL");
78MODULE_VERSION(ARCMSR_DRIVER_VERSION); 86MODULE_VERSION(ARCMSR_DRIVER_VERSION);
79 87
@@ -96,6 +104,13 @@ static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb);
96static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb); 104static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb);
97static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb); 105static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb);
98static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb); 106static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb);
107static void arcmsr_request_device_map(unsigned long pacb);
108static void arcmsr_request_hba_device_map(struct AdapterControlBlock *acb);
109static void arcmsr_request_hbb_device_map(struct AdapterControlBlock *acb);
110static void arcmsr_message_isr_bh_fn(struct work_struct *work);
111static void *arcmsr_get_firmware_spec(struct AdapterControlBlock *acb, int mode);
112static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb);
113
99static const char *arcmsr_info(struct Scsi_Host *); 114static const char *arcmsr_info(struct Scsi_Host *);
100static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb); 115static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb);
101static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev, 116static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev,
@@ -112,7 +127,7 @@ static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev,
112 127
113static struct scsi_host_template arcmsr_scsi_host_template = { 128static struct scsi_host_template arcmsr_scsi_host_template = {
114 .module = THIS_MODULE, 129 .module = THIS_MODULE,
115 .name = "ARCMSR ARECA SATA/SAS RAID HOST Adapter" 130 .name = "ARCMSR ARECA SATA/SAS RAID Host Bus Adapter"
116 ARCMSR_DRIVER_VERSION, 131 ARCMSR_DRIVER_VERSION,
117 .info = arcmsr_info, 132 .info = arcmsr_info,
118 .queuecommand = arcmsr_queue_command, 133 .queuecommand = arcmsr_queue_command,
@@ -128,16 +143,6 @@ static struct scsi_host_template arcmsr_scsi_host_template = {
128 .use_clustering = ENABLE_CLUSTERING, 143 .use_clustering = ENABLE_CLUSTERING,
129 .shost_attrs = arcmsr_host_attrs, 144 .shost_attrs = arcmsr_host_attrs,
130}; 145};
131#ifdef CONFIG_SCSI_ARCMSR_AER
132static pci_ers_result_t arcmsr_pci_slot_reset(struct pci_dev *pdev);
133static pci_ers_result_t arcmsr_pci_error_detected(struct pci_dev *pdev,
134 pci_channel_state_t state);
135
136static struct pci_error_handlers arcmsr_pci_error_handlers = {
137 .error_detected = arcmsr_pci_error_detected,
138 .slot_reset = arcmsr_pci_slot_reset,
139};
140#endif
141static struct pci_device_id arcmsr_device_id_table[] = { 146static struct pci_device_id arcmsr_device_id_table[] = {
142 {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1110)}, 147 {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1110)},
143 {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1120)}, 148 {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1120)},
@@ -166,9 +171,6 @@ static struct pci_driver arcmsr_pci_driver = {
166 .probe = arcmsr_probe, 171 .probe = arcmsr_probe,
167 .remove = arcmsr_remove, 172 .remove = arcmsr_remove,
168 .shutdown = arcmsr_shutdown, 173 .shutdown = arcmsr_shutdown,
169 #ifdef CONFIG_SCSI_ARCMSR_AER
170 .err_handler = &arcmsr_pci_error_handlers,
171 #endif
172}; 174};
173 175
174static irqreturn_t arcmsr_do_interrupt(int irq, void *dev_id) 176static irqreturn_t arcmsr_do_interrupt(int irq, void *dev_id)
@@ -236,10 +238,9 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb)
236 void *dma_coherent; 238 void *dma_coherent;
237 dma_addr_t dma_coherent_handle, dma_addr; 239 dma_addr_t dma_coherent_handle, dma_addr;
238 struct CommandControlBlock *ccb_tmp; 240 struct CommandControlBlock *ccb_tmp;
239 uint32_t intmask_org;
240 int i, j; 241 int i, j;
241 242
242 acb->pmuA = pci_ioremap_bar(pdev, 0); 243 acb->pmuA = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
243 if (!acb->pmuA) { 244 if (!acb->pmuA) {
244 printk(KERN_NOTICE "arcmsr%d: memory mapping region fail \n", 245 printk(KERN_NOTICE "arcmsr%d: memory mapping region fail \n",
245 acb->host->host_no); 246 acb->host->host_no);
@@ -281,12 +282,6 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb)
281 for (i = 0; i < ARCMSR_MAX_TARGETID; i++) 282 for (i = 0; i < ARCMSR_MAX_TARGETID; i++)
282 for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++) 283 for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++)
283 acb->devstate[i][j] = ARECA_RAID_GONE; 284 acb->devstate[i][j] = ARECA_RAID_GONE;
284
285 /*
286 ** here we need to tell iop 331 our ccb_tmp.HighPart
287 ** if ccb_tmp.HighPart is not zero
288 */
289 intmask_org = arcmsr_disable_outbound_ints(acb);
290 } 285 }
291 break; 286 break;
292 287
@@ -297,7 +292,6 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb)
297 void __iomem *mem_base0, *mem_base1; 292 void __iomem *mem_base0, *mem_base1;
298 void *dma_coherent; 293 void *dma_coherent;
299 dma_addr_t dma_coherent_handle, dma_addr; 294 dma_addr_t dma_coherent_handle, dma_addr;
300 uint32_t intmask_org;
301 struct CommandControlBlock *ccb_tmp; 295 struct CommandControlBlock *ccb_tmp;
302 int i, j; 296 int i, j;
303 297
@@ -333,11 +327,13 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb)
333 reg = (struct MessageUnit_B *)(dma_coherent + 327 reg = (struct MessageUnit_B *)(dma_coherent +
334 ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock)); 328 ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock));
335 acb->pmuB = reg; 329 acb->pmuB = reg;
336 mem_base0 = pci_ioremap_bar(pdev, 0); 330 mem_base0 = ioremap(pci_resource_start(pdev, 0),
331 pci_resource_len(pdev, 0));
337 if (!mem_base0) 332 if (!mem_base0)
338 goto out; 333 goto out;
339 334
340 mem_base1 = pci_ioremap_bar(pdev, 2); 335 mem_base1 = ioremap(pci_resource_start(pdev, 2),
336 pci_resource_len(pdev, 2));
341 if (!mem_base1) { 337 if (!mem_base1) {
342 iounmap(mem_base0); 338 iounmap(mem_base0);
343 goto out; 339 goto out;
@@ -357,12 +353,6 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb)
357 for (i = 0; i < ARCMSR_MAX_TARGETID; i++) 353 for (i = 0; i < ARCMSR_MAX_TARGETID; i++)
358 for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++) 354 for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++)
359 acb->devstate[i][j] = ARECA_RAID_GOOD; 355 acb->devstate[i][j] = ARECA_RAID_GOOD;
360
361 /*
362 ** here we need to tell iop 331 our ccb_tmp.HighPart
363 ** if ccb_tmp.HighPart is not zero
364 */
365 intmask_org = arcmsr_disable_outbound_ints(acb);
366 } 356 }
367 break; 357 break;
368 } 358 }
@@ -374,6 +364,88 @@ out:
374 sizeof(struct MessageUnit_B)), acb->dma_coherent, acb->dma_coherent_handle); 364 sizeof(struct MessageUnit_B)), acb->dma_coherent, acb->dma_coherent_handle);
375 return -ENOMEM; 365 return -ENOMEM;
376} 366}
367static void arcmsr_message_isr_bh_fn(struct work_struct *work)
368{
369 struct AdapterControlBlock *acb = container_of(work, struct AdapterControlBlock, arcmsr_do_message_isr_bh);
370
371 switch (acb->adapter_type) {
372 case ACB_ADAPTER_TYPE_A: {
373
374 struct MessageUnit_A __iomem *reg = acb->pmuA;
375 char *acb_dev_map = (char *)acb->device_map;
376 uint32_t __iomem *signature = (uint32_t __iomem *) (&reg->message_rwbuffer[0]);
377 char __iomem *devicemap = (char __iomem *) (&reg->message_rwbuffer[21]);
378 int target, lun;
379 struct scsi_device *psdev;
380 char diff;
381
382 atomic_inc(&acb->rq_map_token);
383 if (readl(signature) == ARCMSR_SIGNATURE_GET_CONFIG) {
384 for (target = 0; target < ARCMSR_MAX_TARGETID - 1; target++) {
385 diff = (*acb_dev_map)^readb(devicemap);
386 if (diff != 0) {
387 char temp;
388 *acb_dev_map = readb(devicemap);
389 temp = *acb_dev_map;
390 for (lun = 0; lun < ARCMSR_MAX_TARGETLUN; lun++) {
391 if ((temp & 0x01) == 1 && (diff & 0x01) == 1) {
392 scsi_add_device(acb->host, 0, target, lun);
393 } else if ((temp & 0x01) == 0 && (diff & 0x01) == 1) {
394 psdev = scsi_device_lookup(acb->host, 0, target, lun);
395 if (psdev != NULL) {
396 scsi_remove_device(psdev);
397 scsi_device_put(psdev);
398 }
399 }
400 temp >>= 1;
401 diff >>= 1;
402 }
403 }
404 devicemap++;
405 acb_dev_map++;
406 }
407 }
408 break;
409 }
410
411 case ACB_ADAPTER_TYPE_B: {
412 struct MessageUnit_B *reg = acb->pmuB;
413 char *acb_dev_map = (char *)acb->device_map;
414 uint32_t __iomem *signature = (uint32_t __iomem *)(&reg->msgcode_rwbuffer_reg[0]);
415 char __iomem *devicemap = (char __iomem *)(&reg->msgcode_rwbuffer_reg[21]);
416 int target, lun;
417 struct scsi_device *psdev;
418 char diff;
419
420 atomic_inc(&acb->rq_map_token);
421 if (readl(signature) == ARCMSR_SIGNATURE_GET_CONFIG) {
422 for (target = 0; target < ARCMSR_MAX_TARGETID - 1; target++) {
423 diff = (*acb_dev_map)^readb(devicemap);
424 if (diff != 0) {
425 char temp;
426 *acb_dev_map = readb(devicemap);
427 temp = *acb_dev_map;
428 for (lun = 0; lun < ARCMSR_MAX_TARGETLUN; lun++) {
429 if ((temp & 0x01) == 1 && (diff & 0x01) == 1) {
430 scsi_add_device(acb->host, 0, target, lun);
431 } else if ((temp & 0x01) == 0 && (diff & 0x01) == 1) {
432 psdev = scsi_device_lookup(acb->host, 0, target, lun);
433 if (psdev != NULL) {
434 scsi_remove_device(psdev);
435 scsi_device_put(psdev);
436 }
437 }
438 temp >>= 1;
439 diff >>= 1;
440 }
441 }
442 devicemap++;
443 acb_dev_map++;
444 }
445 }
446 }
447 }
448}
377 449
378static int arcmsr_probe(struct pci_dev *pdev, 450static int arcmsr_probe(struct pci_dev *pdev,
379 const struct pci_device_id *id) 451 const struct pci_device_id *id)
@@ -432,17 +504,17 @@ static int arcmsr_probe(struct pci_dev *pdev,
432 ACB_F_MESSAGE_WQBUFFER_READED); 504 ACB_F_MESSAGE_WQBUFFER_READED);
433 acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER; 505 acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER;
434 INIT_LIST_HEAD(&acb->ccb_free_list); 506 INIT_LIST_HEAD(&acb->ccb_free_list);
435 507 INIT_WORK(&acb->arcmsr_do_message_isr_bh, arcmsr_message_isr_bh_fn);
436 error = arcmsr_alloc_ccb_pool(acb); 508 error = arcmsr_alloc_ccb_pool(acb);
437 if (error) 509 if (error)
438 goto out_release_regions; 510 goto out_release_regions;
439 511
512 arcmsr_iop_init(acb);
440 error = request_irq(pdev->irq, arcmsr_do_interrupt, 513 error = request_irq(pdev->irq, arcmsr_do_interrupt,
441 IRQF_SHARED, "arcmsr", acb); 514 IRQF_SHARED, "arcmsr", acb);
442 if (error) 515 if (error)
443 goto out_free_ccb_pool; 516 goto out_free_ccb_pool;
444 517
445 arcmsr_iop_init(acb);
446 pci_set_drvdata(pdev, host); 518 pci_set_drvdata(pdev, host);
447 if (strncmp(acb->firm_version, "V1.42", 5) >= 0) 519 if (strncmp(acb->firm_version, "V1.42", 5) >= 0)
448 host->max_sectors= ARCMSR_MAX_XFER_SECTORS_B; 520 host->max_sectors= ARCMSR_MAX_XFER_SECTORS_B;
@@ -459,6 +531,14 @@ static int arcmsr_probe(struct pci_dev *pdev,
459 #ifdef CONFIG_SCSI_ARCMSR_AER 531 #ifdef CONFIG_SCSI_ARCMSR_AER
460 pci_enable_pcie_error_reporting(pdev); 532 pci_enable_pcie_error_reporting(pdev);
461 #endif 533 #endif
534 atomic_set(&acb->rq_map_token, 16);
535 acb->fw_state = true;
536 init_timer(&acb->eternal_timer);
537 acb->eternal_timer.expires = jiffies + msecs_to_jiffies(10*HZ);
538 acb->eternal_timer.data = (unsigned long) acb;
539 acb->eternal_timer.function = &arcmsr_request_device_map;
540 add_timer(&acb->eternal_timer);
541
462 return 0; 542 return 0;
463 out_free_sysfs: 543 out_free_sysfs:
464 out_free_irq: 544 out_free_irq:
@@ -518,40 +598,48 @@ static uint8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb)
518 return 0xff; 598 return 0xff;
519} 599}
520 600
521static void arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb) 601static uint8_t arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb)
522{ 602{
523 struct MessageUnit_A __iomem *reg = acb->pmuA; 603 struct MessageUnit_A __iomem *reg = acb->pmuA;
524 604
525 writel(ARCMSR_INBOUND_MESG0_ABORT_CMD, &reg->inbound_msgaddr0); 605 writel(ARCMSR_INBOUND_MESG0_ABORT_CMD, &reg->inbound_msgaddr0);
526 if (arcmsr_hba_wait_msgint_ready(acb)) 606 if (arcmsr_hba_wait_msgint_ready(acb)) {
527 printk(KERN_NOTICE 607 printk(KERN_NOTICE
528 "arcmsr%d: wait 'abort all outstanding command' timeout \n" 608 "arcmsr%d: wait 'abort all outstanding command' timeout \n"
529 , acb->host->host_no); 609 , acb->host->host_no);
610 return 0xff;
611 }
612 return 0x00;
530} 613}
531 614
532static void arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb) 615static uint8_t arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb)
533{ 616{
534 struct MessageUnit_B *reg = acb->pmuB; 617 struct MessageUnit_B *reg = acb->pmuB;
535 618
536 writel(ARCMSR_MESSAGE_ABORT_CMD, reg->drv2iop_doorbell_reg); 619 writel(ARCMSR_MESSAGE_ABORT_CMD, reg->drv2iop_doorbell_reg);
537 if (arcmsr_hbb_wait_msgint_ready(acb)) 620 if (arcmsr_hbb_wait_msgint_ready(acb)) {
538 printk(KERN_NOTICE 621 printk(KERN_NOTICE
539 "arcmsr%d: wait 'abort all outstanding command' timeout \n" 622 "arcmsr%d: wait 'abort all outstanding command' timeout \n"
540 , acb->host->host_no); 623 , acb->host->host_no);
624 return 0xff;
625 }
626 return 0x00;
541} 627}
542 628
543static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb) 629static uint8_t arcmsr_abort_allcmd(struct AdapterControlBlock *acb)
544{ 630{
631 uint8_t rtnval = 0;
545 switch (acb->adapter_type) { 632 switch (acb->adapter_type) {
546 case ACB_ADAPTER_TYPE_A: { 633 case ACB_ADAPTER_TYPE_A: {
547 arcmsr_abort_hba_allcmd(acb); 634 rtnval = arcmsr_abort_hba_allcmd(acb);
548 } 635 }
549 break; 636 break;
550 637
551 case ACB_ADAPTER_TYPE_B: { 638 case ACB_ADAPTER_TYPE_B: {
552 arcmsr_abort_hbb_allcmd(acb); 639 rtnval = arcmsr_abort_hbb_allcmd(acb);
553 } 640 }
554 } 641 }
642 return rtnval;
555} 643}
556 644
557static void arcmsr_pci_unmap_dma(struct CommandControlBlock *ccb) 645static void arcmsr_pci_unmap_dma(struct CommandControlBlock *ccb)
@@ -649,8 +737,7 @@ static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb)
649 737
650 case ACB_ADAPTER_TYPE_A : { 738 case ACB_ADAPTER_TYPE_A : {
651 struct MessageUnit_A __iomem *reg = acb->pmuA; 739 struct MessageUnit_A __iomem *reg = acb->pmuA;
652 orig_mask = readl(&reg->outbound_intmask)|\ 740 orig_mask = readl(&reg->outbound_intmask);
653 ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE;
654 writel(orig_mask|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE, \ 741 writel(orig_mask|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE, \
655 &reg->outbound_intmask); 742 &reg->outbound_intmask);
656 } 743 }
@@ -658,8 +745,7 @@ static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb)
658 745
659 case ACB_ADAPTER_TYPE_B : { 746 case ACB_ADAPTER_TYPE_B : {
660 struct MessageUnit_B *reg = acb->pmuB; 747 struct MessageUnit_B *reg = acb->pmuB;
661 orig_mask = readl(reg->iop2drv_doorbell_mask_reg) & \ 748 orig_mask = readl(reg->iop2drv_doorbell_mask_reg);
662 (~ARCMSR_IOP2DRV_MESSAGE_CMD_DONE);
663 writel(0, reg->iop2drv_doorbell_mask_reg); 749 writel(0, reg->iop2drv_doorbell_mask_reg);
664 } 750 }
665 break; 751 break;
@@ -795,12 +881,13 @@ static void arcmsr_remove(struct pci_dev *pdev)
795 struct AdapterControlBlock *acb = 881 struct AdapterControlBlock *acb =
796 (struct AdapterControlBlock *) host->hostdata; 882 (struct AdapterControlBlock *) host->hostdata;
797 int poll_count = 0; 883 int poll_count = 0;
798
799 arcmsr_free_sysfs_attr(acb); 884 arcmsr_free_sysfs_attr(acb);
800 scsi_remove_host(host); 885 scsi_remove_host(host);
886 flush_scheduled_work();
887 del_timer_sync(&acb->eternal_timer);
888 arcmsr_disable_outbound_ints(acb);
801 arcmsr_stop_adapter_bgrb(acb); 889 arcmsr_stop_adapter_bgrb(acb);
802 arcmsr_flush_adapter_cache(acb); 890 arcmsr_flush_adapter_cache(acb);
803 arcmsr_disable_outbound_ints(acb);
804 acb->acb_flags |= ACB_F_SCSISTOPADAPTER; 891 acb->acb_flags |= ACB_F_SCSISTOPADAPTER;
805 acb->acb_flags &= ~ACB_F_IOP_INITED; 892 acb->acb_flags &= ~ACB_F_IOP_INITED;
806 893
@@ -841,7 +928,9 @@ static void arcmsr_shutdown(struct pci_dev *pdev)
841 struct Scsi_Host *host = pci_get_drvdata(pdev); 928 struct Scsi_Host *host = pci_get_drvdata(pdev);
842 struct AdapterControlBlock *acb = 929 struct AdapterControlBlock *acb =
843 (struct AdapterControlBlock *)host->hostdata; 930 (struct AdapterControlBlock *)host->hostdata;
844 931 del_timer_sync(&acb->eternal_timer);
932 arcmsr_disable_outbound_ints(acb);
933 flush_scheduled_work();
845 arcmsr_stop_adapter_bgrb(acb); 934 arcmsr_stop_adapter_bgrb(acb);
846 arcmsr_flush_adapter_cache(acb); 935 arcmsr_flush_adapter_cache(acb);
847} 936}
@@ -861,7 +950,7 @@ static void arcmsr_module_exit(void)
861module_init(arcmsr_module_init); 950module_init(arcmsr_module_init);
862module_exit(arcmsr_module_exit); 951module_exit(arcmsr_module_exit);
863 952
864static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, \ 953static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb,
865 u32 intmask_org) 954 u32 intmask_org)
866{ 955{
867 u32 mask; 956 u32 mask;
@@ -871,7 +960,8 @@ static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, \
871 case ACB_ADAPTER_TYPE_A : { 960 case ACB_ADAPTER_TYPE_A : {
872 struct MessageUnit_A __iomem *reg = acb->pmuA; 961 struct MessageUnit_A __iomem *reg = acb->pmuA;
873 mask = intmask_org & ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE | 962 mask = intmask_org & ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE |
874 ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE); 963 ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE|
964 ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE);
875 writel(mask, &reg->outbound_intmask); 965 writel(mask, &reg->outbound_intmask);
876 acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff; 966 acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff;
877 } 967 }
@@ -879,8 +969,10 @@ static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, \
879 969
880 case ACB_ADAPTER_TYPE_B : { 970 case ACB_ADAPTER_TYPE_B : {
881 struct MessageUnit_B *reg = acb->pmuB; 971 struct MessageUnit_B *reg = acb->pmuB;
882 mask = intmask_org | (ARCMSR_IOP2DRV_DATA_WRITE_OK | \ 972 mask = intmask_org | (ARCMSR_IOP2DRV_DATA_WRITE_OK |
883 ARCMSR_IOP2DRV_DATA_READ_OK | ARCMSR_IOP2DRV_CDB_DONE); 973 ARCMSR_IOP2DRV_DATA_READ_OK |
974 ARCMSR_IOP2DRV_CDB_DONE |
975 ARCMSR_IOP2DRV_MESSAGE_CMD_DONE);
884 writel(mask, reg->iop2drv_doorbell_mask_reg); 976 writel(mask, reg->iop2drv_doorbell_mask_reg);
885 acb->outbound_int_enable = (intmask_org | mask) & 0x0000000f; 977 acb->outbound_int_enable = (intmask_org | mask) & 0x0000000f;
886 } 978 }
@@ -1048,8 +1140,8 @@ static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb)
1048 } 1140 }
1049 case ACB_ADAPTER_TYPE_B: { 1141 case ACB_ADAPTER_TYPE_B: {
1050 struct MessageUnit_B *reg = acb->pmuB; 1142 struct MessageUnit_B *reg = acb->pmuB;
1051 iounmap(reg->drv2iop_doorbell_reg - ARCMSR_DRV2IOP_DOORBELL); 1143 iounmap((u8 *)reg->drv2iop_doorbell_reg - ARCMSR_DRV2IOP_DOORBELL);
1052 iounmap(reg->ioctl_wbuffer_reg - ARCMSR_IOCTL_WBUFFER); 1144 iounmap((u8 *)reg->ioctl_wbuffer_reg - ARCMSR_IOCTL_WBUFFER);
1053 dma_free_coherent(&acb->pdev->dev, 1145 dma_free_coherent(&acb->pdev->dev,
1054 (ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock) + 0x20 + 1146 (ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock) + 0x20 +
1055 sizeof(struct MessageUnit_B)), acb->dma_coherent, acb->dma_coherent_handle); 1147 sizeof(struct MessageUnit_B)), acb->dma_coherent, acb->dma_coherent_handle);
@@ -1249,13 +1341,36 @@ static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb)
1249 reg->doneq_index = index; 1341 reg->doneq_index = index;
1250 } 1342 }
1251} 1343}
1344/*
1345**********************************************************************************
1346** Handle a message interrupt
1347**
1348** The only message interrupt we expect is in response to a query for the current adapter config.
1349** We want this in order to compare the drivemap so that we can detect newly-attached drives.
1350**********************************************************************************
1351*/
1352static void arcmsr_hba_message_isr(struct AdapterControlBlock *acb)
1353{
1354 struct MessageUnit_A *reg = acb->pmuA;
1355
1356 /*clear interrupt and message state*/
1357 writel(ARCMSR_MU_OUTBOUND_MESSAGE0_INT, &reg->outbound_intstatus);
1358 schedule_work(&acb->arcmsr_do_message_isr_bh);
1359}
1360static void arcmsr_hbb_message_isr(struct AdapterControlBlock *acb)
1361{
1362 struct MessageUnit_B *reg = acb->pmuB;
1252 1363
1364 /*clear interrupt and message state*/
1365 writel(ARCMSR_MESSAGE_INT_CLEAR_PATTERN, reg->iop2drv_doorbell_reg);
1366 schedule_work(&acb->arcmsr_do_message_isr_bh);
1367}
1253static int arcmsr_handle_hba_isr(struct AdapterControlBlock *acb) 1368static int arcmsr_handle_hba_isr(struct AdapterControlBlock *acb)
1254{ 1369{
1255 uint32_t outbound_intstatus; 1370 uint32_t outbound_intstatus;
1256 struct MessageUnit_A __iomem *reg = acb->pmuA; 1371 struct MessageUnit_A __iomem *reg = acb->pmuA;
1257 1372
1258 outbound_intstatus = readl(&reg->outbound_intstatus) & \ 1373 outbound_intstatus = readl(&reg->outbound_intstatus) &
1259 acb->outbound_int_enable; 1374 acb->outbound_int_enable;
1260 if (!(outbound_intstatus & ARCMSR_MU_OUTBOUND_HANDLE_INT)) { 1375 if (!(outbound_intstatus & ARCMSR_MU_OUTBOUND_HANDLE_INT)) {
1261 return 1; 1376 return 1;
@@ -1267,6 +1382,10 @@ static int arcmsr_handle_hba_isr(struct AdapterControlBlock *acb)
1267 if (outbound_intstatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) { 1382 if (outbound_intstatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) {
1268 arcmsr_hba_postqueue_isr(acb); 1383 arcmsr_hba_postqueue_isr(acb);
1269 } 1384 }
1385 if (outbound_intstatus & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) {
1386 /* messenger of "driver to iop commands" */
1387 arcmsr_hba_message_isr(acb);
1388 }
1270 return 0; 1389 return 0;
1271} 1390}
1272 1391
@@ -1275,13 +1394,14 @@ static int arcmsr_handle_hbb_isr(struct AdapterControlBlock *acb)
1275 uint32_t outbound_doorbell; 1394 uint32_t outbound_doorbell;
1276 struct MessageUnit_B *reg = acb->pmuB; 1395 struct MessageUnit_B *reg = acb->pmuB;
1277 1396
1278 outbound_doorbell = readl(reg->iop2drv_doorbell_reg) & \ 1397 outbound_doorbell = readl(reg->iop2drv_doorbell_reg) &
1279 acb->outbound_int_enable; 1398 acb->outbound_int_enable;
1280 if (!outbound_doorbell) 1399 if (!outbound_doorbell)
1281 return 1; 1400 return 1;
1282 1401
1283 writel(~outbound_doorbell, reg->iop2drv_doorbell_reg); 1402 writel(~outbound_doorbell, reg->iop2drv_doorbell_reg);
1284 /*in case the last action of doorbell interrupt clearance is cached, this action can push HW to write down the clear bit*/ 1403 /*in case the last action of doorbell interrupt clearance is cached,
1404 this action can push HW to write down the clear bit*/
1285 readl(reg->iop2drv_doorbell_reg); 1405 readl(reg->iop2drv_doorbell_reg);
1286 writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT, reg->drv2iop_doorbell_reg); 1406 writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT, reg->drv2iop_doorbell_reg);
1287 if (outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) { 1407 if (outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) {
@@ -1293,6 +1413,10 @@ static int arcmsr_handle_hbb_isr(struct AdapterControlBlock *acb)
1293 if (outbound_doorbell & ARCMSR_IOP2DRV_CDB_DONE) { 1413 if (outbound_doorbell & ARCMSR_IOP2DRV_CDB_DONE) {
1294 arcmsr_hbb_postqueue_isr(acb); 1414 arcmsr_hbb_postqueue_isr(acb);
1295 } 1415 }
1416 if (outbound_doorbell & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) {
1417 /* messenger of "driver to iop commands" */
1418 arcmsr_hbb_message_isr(acb);
1419 }
1296 1420
1297 return 0; 1421 return 0;
1298} 1422}
@@ -1360,7 +1484,7 @@ void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *acb)
1360 } 1484 }
1361} 1485}
1362 1486
1363static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \ 1487static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb,
1364 struct scsi_cmnd *cmd) 1488 struct scsi_cmnd *cmd)
1365{ 1489{
1366 struct CMD_MESSAGE_FIELD *pcmdmessagefld; 1490 struct CMD_MESSAGE_FIELD *pcmdmessagefld;
@@ -1398,6 +1522,13 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \
1398 retvalue = ARCMSR_MESSAGE_FAIL; 1522 retvalue = ARCMSR_MESSAGE_FAIL;
1399 goto message_out; 1523 goto message_out;
1400 } 1524 }
1525
1526 if (!acb->fw_state) {
1527 pcmdmessagefld->cmdmessage.ReturnCode =
1528 ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON;
1529 goto message_out;
1530 }
1531
1401 ptmpQbuffer = ver_addr; 1532 ptmpQbuffer = ver_addr;
1402 while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex) 1533 while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex)
1403 && (allxfer_len < 1031)) { 1534 && (allxfer_len < 1031)) {
@@ -1444,6 +1575,12 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \
1444 retvalue = ARCMSR_MESSAGE_FAIL; 1575 retvalue = ARCMSR_MESSAGE_FAIL;
1445 goto message_out; 1576 goto message_out;
1446 } 1577 }
1578 if (!acb->fw_state) {
1579 pcmdmessagefld->cmdmessage.ReturnCode =
1580 ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON;
1581 goto message_out;
1582 }
1583
1447 ptmpuserbuffer = ver_addr; 1584 ptmpuserbuffer = ver_addr;
1448 user_len = pcmdmessagefld->cmdmessage.Length; 1585 user_len = pcmdmessagefld->cmdmessage.Length;
1449 memcpy(ptmpuserbuffer, pcmdmessagefld->messagedatabuffer, user_len); 1586 memcpy(ptmpuserbuffer, pcmdmessagefld->messagedatabuffer, user_len);
@@ -1496,6 +1633,11 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \
1496 1633
1497 case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { 1634 case ARCMSR_MESSAGE_CLEAR_RQBUFFER: {
1498 uint8_t *pQbuffer = acb->rqbuffer; 1635 uint8_t *pQbuffer = acb->rqbuffer;
1636 if (!acb->fw_state) {
1637 pcmdmessagefld->cmdmessage.ReturnCode =
1638 ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON;
1639 goto message_out;
1640 }
1499 1641
1500 if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 1642 if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
1501 acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 1643 acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
@@ -1511,6 +1653,11 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \
1511 1653
1512 case ARCMSR_MESSAGE_CLEAR_WQBUFFER: { 1654 case ARCMSR_MESSAGE_CLEAR_WQBUFFER: {
1513 uint8_t *pQbuffer = acb->wqbuffer; 1655 uint8_t *pQbuffer = acb->wqbuffer;
1656 if (!acb->fw_state) {
1657 pcmdmessagefld->cmdmessage.ReturnCode =
1658 ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON;
1659 goto message_out;
1660 }
1514 1661
1515 if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 1662 if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
1516 acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 1663 acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
@@ -1529,6 +1676,11 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \
1529 1676
1530 case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { 1677 case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: {
1531 uint8_t *pQbuffer; 1678 uint8_t *pQbuffer;
1679 if (!acb->fw_state) {
1680 pcmdmessagefld->cmdmessage.ReturnCode =
1681 ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON;
1682 goto message_out;
1683 }
1532 1684
1533 if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 1685 if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
1534 acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 1686 acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
@@ -1551,13 +1703,22 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \
1551 break; 1703 break;
1552 1704
1553 case ARCMSR_MESSAGE_RETURN_CODE_3F: { 1705 case ARCMSR_MESSAGE_RETURN_CODE_3F: {
1706 if (!acb->fw_state) {
1707 pcmdmessagefld->cmdmessage.ReturnCode =
1708 ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON;
1709 goto message_out;
1710 }
1554 pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F; 1711 pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F;
1555 } 1712 }
1556 break; 1713 break;
1557 1714
1558 case ARCMSR_MESSAGE_SAY_HELLO: { 1715 case ARCMSR_MESSAGE_SAY_HELLO: {
1559 int8_t *hello_string = "Hello! I am ARCMSR"; 1716 int8_t *hello_string = "Hello! I am ARCMSR";
1560 1717 if (!acb->fw_state) {
1718 pcmdmessagefld->cmdmessage.ReturnCode =
1719 ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON;
1720 goto message_out;
1721 }
1561 memcpy(pcmdmessagefld->messagedatabuffer, hello_string 1722 memcpy(pcmdmessagefld->messagedatabuffer, hello_string
1562 , (int16_t)strlen(hello_string)); 1723 , (int16_t)strlen(hello_string));
1563 pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 1724 pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
@@ -1565,10 +1726,20 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \
1565 break; 1726 break;
1566 1727
1567 case ARCMSR_MESSAGE_SAY_GOODBYE: 1728 case ARCMSR_MESSAGE_SAY_GOODBYE:
1729 if (!acb->fw_state) {
1730 pcmdmessagefld->cmdmessage.ReturnCode =
1731 ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON;
1732 goto message_out;
1733 }
1568 arcmsr_iop_parking(acb); 1734 arcmsr_iop_parking(acb);
1569 break; 1735 break;
1570 1736
1571 case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: 1737 case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE:
1738 if (!acb->fw_state) {
1739 pcmdmessagefld->cmdmessage.ReturnCode =
1740 ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON;
1741 goto message_out;
1742 }
1572 arcmsr_flush_adapter_cache(acb); 1743 arcmsr_flush_adapter_cache(acb);
1573 break; 1744 break;
1574 1745
@@ -1651,16 +1822,57 @@ static int arcmsr_queue_command(struct scsi_cmnd *cmd,
1651 struct CommandControlBlock *ccb; 1822 struct CommandControlBlock *ccb;
1652 int target = cmd->device->id; 1823 int target = cmd->device->id;
1653 int lun = cmd->device->lun; 1824 int lun = cmd->device->lun;
1654 1825 uint8_t scsicmd = cmd->cmnd[0];
1655 cmd->scsi_done = done; 1826 cmd->scsi_done = done;
1656 cmd->host_scribble = NULL; 1827 cmd->host_scribble = NULL;
1657 cmd->result = 0; 1828 cmd->result = 0;
1829
1830 if ((scsicmd == SYNCHRONIZE_CACHE) || (scsicmd == SEND_DIAGNOSTIC)) {
1831 if (acb->devstate[target][lun] == ARECA_RAID_GONE) {
1832 cmd->result = (DID_NO_CONNECT << 16);
1833 }
1834 cmd->scsi_done(cmd);
1835 return 0;
1836 }
1837
1658 if (acb->acb_flags & ACB_F_BUS_RESET) { 1838 if (acb->acb_flags & ACB_F_BUS_RESET) {
1659 printk(KERN_NOTICE "arcmsr%d: bus reset" 1839 switch (acb->adapter_type) {
1660 " and return busy \n" 1840 case ACB_ADAPTER_TYPE_A: {
1661 , acb->host->host_no); 1841 struct MessageUnit_A __iomem *reg = acb->pmuA;
1842 uint32_t intmask_org, outbound_doorbell;
1843
1844 if ((readl(&reg->outbound_msgaddr1) &
1845 ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0) {
1846 printk(KERN_NOTICE "arcmsr%d: bus reset and return busy\n",
1847 acb->host->host_no);
1662 return SCSI_MLQUEUE_HOST_BUSY; 1848 return SCSI_MLQUEUE_HOST_BUSY;
1663 } 1849 }
1850
1851 acb->acb_flags &= ~ACB_F_FIRMWARE_TRAP;
1852 printk(KERN_NOTICE "arcmsr%d: hardware bus reset and reset ok\n",
1853 acb->host->host_no);
1854 /* disable all outbound interrupt */
1855 intmask_org = arcmsr_disable_outbound_ints(acb);
1856 arcmsr_get_firmware_spec(acb, 1);
1857 /*start background rebuild*/
1858 arcmsr_start_adapter_bgrb(acb);
1859 /* clear Qbuffer if door bell ringed */
1860 outbound_doorbell = readl(&reg->outbound_doorbell);
1861 /*clear interrupt */
1862 writel(outbound_doorbell, &reg->outbound_doorbell);
1863 writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK,
1864 &reg->inbound_doorbell);
1865 /* enable outbound Post Queue,outbound doorbell Interrupt */
1866 arcmsr_enable_outbound_ints(acb, intmask_org);
1867 acb->acb_flags |= ACB_F_IOP_INITED;
1868 acb->acb_flags &= ~ACB_F_BUS_RESET;
1869 }
1870 break;
1871 case ACB_ADAPTER_TYPE_B: {
1872 }
1873 }
1874 }
1875
1664 if (target == 16) { 1876 if (target == 16) {
1665 /* virtual device for iop message transfer */ 1877 /* virtual device for iop message transfer */
1666 arcmsr_handle_virtual_command(acb, cmd); 1878 arcmsr_handle_virtual_command(acb, cmd);
@@ -1699,21 +1911,25 @@ static int arcmsr_queue_command(struct scsi_cmnd *cmd,
1699 return 0; 1911 return 0;
1700} 1912}
1701 1913
1702static void arcmsr_get_hba_config(struct AdapterControlBlock *acb) 1914static void *arcmsr_get_hba_config(struct AdapterControlBlock *acb, int mode)
1703{ 1915{
1704 struct MessageUnit_A __iomem *reg = acb->pmuA; 1916 struct MessageUnit_A __iomem *reg = acb->pmuA;
1705 char *acb_firm_model = acb->firm_model; 1917 char *acb_firm_model = acb->firm_model;
1706 char *acb_firm_version = acb->firm_version; 1918 char *acb_firm_version = acb->firm_version;
1919 char *acb_device_map = acb->device_map;
1707 char __iomem *iop_firm_model = (char __iomem *)(&reg->message_rwbuffer[15]); 1920 char __iomem *iop_firm_model = (char __iomem *)(&reg->message_rwbuffer[15]);
1708 char __iomem *iop_firm_version = (char __iomem *)(&reg->message_rwbuffer[17]); 1921 char __iomem *iop_firm_version = (char __iomem *)(&reg->message_rwbuffer[17]);
1922 char __iomem *iop_device_map = (char __iomem *) (&reg->message_rwbuffer[21]);
1709 int count; 1923 int count;
1710 1924
1711 writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, &reg->inbound_msgaddr0); 1925 writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, &reg->inbound_msgaddr0);
1712 if (arcmsr_hba_wait_msgint_ready(acb)) { 1926 if (arcmsr_hba_wait_msgint_ready(acb)) {
1713 printk(KERN_NOTICE "arcmsr%d: wait 'get adapter firmware \ 1927 printk(KERN_NOTICE "arcmsr%d: wait 'get adapter firmware \
1714 miscellaneous data' timeout \n", acb->host->host_no); 1928 miscellaneous data' timeout \n", acb->host->host_no);
1929 return NULL;
1715 } 1930 }
1716 1931
1932 if (mode == 1) {
1717 count = 8; 1933 count = 8;
1718 while (count) { 1934 while (count) {
1719 *acb_firm_model = readb(iop_firm_model); 1935 *acb_firm_model = readb(iop_firm_model);
@@ -1730,34 +1946,48 @@ static void arcmsr_get_hba_config(struct AdapterControlBlock *acb)
1730 count--; 1946 count--;
1731 } 1947 }
1732 1948
1949 count = 16;
1950 while (count) {
1951 *acb_device_map = readb(iop_device_map);
1952 acb_device_map++;
1953 iop_device_map++;
1954 count--;
1955 }
1956
1733 printk(KERN_INFO "ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n" 1957 printk(KERN_INFO "ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n"
1734 , acb->host->host_no 1958 , acb->host->host_no
1735 , acb->firm_version); 1959 , acb->firm_version);
1736 1960 acb->signature = readl(&reg->message_rwbuffer[0]);
1737 acb->firm_request_len = readl(&reg->message_rwbuffer[1]); 1961 acb->firm_request_len = readl(&reg->message_rwbuffer[1]);
1738 acb->firm_numbers_queue = readl(&reg->message_rwbuffer[2]); 1962 acb->firm_numbers_queue = readl(&reg->message_rwbuffer[2]);
1739 acb->firm_sdram_size = readl(&reg->message_rwbuffer[3]); 1963 acb->firm_sdram_size = readl(&reg->message_rwbuffer[3]);
1740 acb->firm_hd_channels = readl(&reg->message_rwbuffer[4]); 1964 acb->firm_hd_channels = readl(&reg->message_rwbuffer[4]);
1741} 1965}
1742 1966 return reg->message_rwbuffer;
1743static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb) 1967}
1968static void __iomem *arcmsr_get_hbb_config(struct AdapterControlBlock *acb, int mode)
1744{ 1969{
1745 struct MessageUnit_B *reg = acb->pmuB; 1970 struct MessageUnit_B *reg = acb->pmuB;
1746 uint32_t __iomem *lrwbuffer = reg->msgcode_rwbuffer_reg; 1971 uint32_t __iomem *lrwbuffer = reg->msgcode_rwbuffer_reg;
1747 char *acb_firm_model = acb->firm_model; 1972 char *acb_firm_model = acb->firm_model;
1748 char *acb_firm_version = acb->firm_version; 1973 char *acb_firm_version = acb->firm_version;
1974 char *acb_device_map = acb->device_map;
1749 char __iomem *iop_firm_model = (char __iomem *)(&lrwbuffer[15]); 1975 char __iomem *iop_firm_model = (char __iomem *)(&lrwbuffer[15]);
1750 /*firm_model,15,60-67*/ 1976 /*firm_model,15,60-67*/
1751 char __iomem *iop_firm_version = (char __iomem *)(&lrwbuffer[17]); 1977 char __iomem *iop_firm_version = (char __iomem *)(&lrwbuffer[17]);
1752 /*firm_version,17,68-83*/ 1978 /*firm_version,17,68-83*/
1979 char __iomem *iop_device_map = (char __iomem *) (&lrwbuffer[21]);
1980 /*firm_version,21,84-99*/
1753 int count; 1981 int count;
1754 1982
1755 writel(ARCMSR_MESSAGE_GET_CONFIG, reg->drv2iop_doorbell_reg); 1983 writel(ARCMSR_MESSAGE_GET_CONFIG, reg->drv2iop_doorbell_reg);
1756 if (arcmsr_hbb_wait_msgint_ready(acb)) { 1984 if (arcmsr_hbb_wait_msgint_ready(acb)) {
1757 printk(KERN_NOTICE "arcmsr%d: wait 'get adapter firmware \ 1985 printk(KERN_NOTICE "arcmsr%d: wait 'get adapter firmware \
1758 miscellaneous data' timeout \n", acb->host->host_no); 1986 miscellaneous data' timeout \n", acb->host->host_no);
1987 return NULL;
1759 } 1988 }
1760 1989
1990 if (mode == 1) {
1761 count = 8; 1991 count = 8;
1762 while (count) 1992 while (count)
1763 { 1993 {
@@ -1776,11 +2006,20 @@ static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb)
1776 count--; 2006 count--;
1777 } 2007 }
1778 2008
2009 count = 16;
2010 while (count) {
2011 *acb_device_map = readb(iop_device_map);
2012 acb_device_map++;
2013 iop_device_map++;
2014 count--;
2015 }
2016
1779 printk(KERN_INFO "ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", 2017 printk(KERN_INFO "ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n",
1780 acb->host->host_no, 2018 acb->host->host_no,
1781 acb->firm_version); 2019 acb->firm_version);
1782 2020
1783 lrwbuffer++; 2021 acb->signature = readl(lrwbuffer++);
2022 /*firm_signature,1,00-03*/
1784 acb->firm_request_len = readl(lrwbuffer++); 2023 acb->firm_request_len = readl(lrwbuffer++);
1785 /*firm_request_len,1,04-07*/ 2024 /*firm_request_len,1,04-07*/
1786 acb->firm_numbers_queue = readl(lrwbuffer++); 2025 acb->firm_numbers_queue = readl(lrwbuffer++);
@@ -1790,20 +2029,23 @@ static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb)
1790 acb->firm_hd_channels = readl(lrwbuffer); 2029 acb->firm_hd_channels = readl(lrwbuffer);
1791 /*firm_ide_channels,4,16-19*/ 2030 /*firm_ide_channels,4,16-19*/
1792} 2031}
1793 2032 return reg->msgcode_rwbuffer_reg;
1794static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) 2033}
2034static void *arcmsr_get_firmware_spec(struct AdapterControlBlock *acb, int mode)
1795{ 2035{
2036 void *rtnval = 0;
1796 switch (acb->adapter_type) { 2037 switch (acb->adapter_type) {
1797 case ACB_ADAPTER_TYPE_A: { 2038 case ACB_ADAPTER_TYPE_A: {
1798 arcmsr_get_hba_config(acb); 2039 rtnval = arcmsr_get_hba_config(acb, mode);
1799 } 2040 }
1800 break; 2041 break;
1801 2042
1802 case ACB_ADAPTER_TYPE_B: { 2043 case ACB_ADAPTER_TYPE_B: {
1803 arcmsr_get_hbb_config(acb); 2044 rtnval = arcmsr_get_hbb_config(acb, mode);
1804 } 2045 }
1805 break; 2046 break;
1806 } 2047 }
2048 return rtnval;
1807} 2049}
1808 2050
1809static void arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb, 2051static void arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb,
@@ -2043,6 +2285,66 @@ static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb)
2043 } 2285 }
2044} 2286}
2045 2287
2288static void arcmsr_request_hba_device_map(struct AdapterControlBlock *acb)
2289{
2290 struct MessageUnit_A __iomem *reg = acb->pmuA;
2291
2292 if (unlikely(atomic_read(&acb->rq_map_token) == 0)) {
2293 acb->fw_state = false;
2294 } else {
2295 /*to prevent rq_map_token from changing by other interrupt, then
2296 avoid the dead-lock*/
2297 acb->fw_state = true;
2298 atomic_dec(&acb->rq_map_token);
2299 if (!(acb->fw_state) ||
2300 (acb->ante_token_value == atomic_read(&acb->rq_map_token))) {
2301 atomic_set(&acb->rq_map_token, 16);
2302 }
2303 acb->ante_token_value = atomic_read(&acb->rq_map_token);
2304 writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, &reg->inbound_msgaddr0);
2305 }
2306 mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6000));
2307 return;
2308}
2309
2310static void arcmsr_request_hbb_device_map(struct AdapterControlBlock *acb)
2311{
2312 struct MessageUnit_B __iomem *reg = acb->pmuB;
2313
2314 if (unlikely(atomic_read(&acb->rq_map_token) == 0)) {
2315 acb->fw_state = false;
2316 } else {
2317 /*to prevent rq_map_token from changing by other interrupt, then
2318 avoid the dead-lock*/
2319 acb->fw_state = true;
2320 atomic_dec(&acb->rq_map_token);
2321 if (!(acb->fw_state) ||
2322 (acb->ante_token_value == atomic_read(&acb->rq_map_token))) {
2323 atomic_set(&acb->rq_map_token, 16);
2324 }
2325 acb->ante_token_value = atomic_read(&acb->rq_map_token);
2326 writel(ARCMSR_MESSAGE_GET_CONFIG, reg->drv2iop_doorbell_reg);
2327 }
2328 mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6000));
2329 return;
2330}
2331
2332static void arcmsr_request_device_map(unsigned long pacb)
2333{
2334 struct AdapterControlBlock *acb = (struct AdapterControlBlock *)pacb;
2335
2336 switch (acb->adapter_type) {
2337 case ACB_ADAPTER_TYPE_A: {
2338 arcmsr_request_hba_device_map(acb);
2339 }
2340 break;
2341 case ACB_ADAPTER_TYPE_B: {
2342 arcmsr_request_hbb_device_map(acb);
2343 }
2344 break;
2345 }
2346}
2347
2046static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb) 2348static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb)
2047{ 2349{
2048 struct MessageUnit_A __iomem *reg = acb->pmuA; 2350 struct MessageUnit_A __iomem *reg = acb->pmuA;
@@ -2121,6 +2423,60 @@ static void arcmsr_enable_eoi_mode(struct AdapterControlBlock *acb)
2121 return; 2423 return;
2122} 2424}
2123 2425
2426static void arcmsr_hardware_reset(struct AdapterControlBlock *acb)
2427{
2428 uint8_t value[64];
2429 int i;
2430
2431 /* backup pci config data */
2432 for (i = 0; i < 64; i++) {
2433 pci_read_config_byte(acb->pdev, i, &value[i]);
2434 }
2435 /* hardware reset signal */
2436 pci_write_config_byte(acb->pdev, 0x84, 0x20);
2437 msleep(1000);
2438 /* write back pci config data */
2439 for (i = 0; i < 64; i++) {
2440 pci_write_config_byte(acb->pdev, i, value[i]);
2441 }
2442 msleep(1000);
2443 return;
2444}
2445/*
2446****************************************************************************
2447****************************************************************************
2448*/
2449#ifdef CONFIG_SCSI_ARCMSR_RESET
2450 int arcmsr_sleep_for_bus_reset(struct scsi_cmnd *cmd)
2451 {
2452 struct Scsi_Host *shost = NULL;
2453 spinlock_t *host_lock = NULL;
2454 int i, isleep;
2455
2456 shost = cmd->device->host;
2457 host_lock = shost->host_lock;
2458
2459 printk(KERN_NOTICE "Host %d bus reset over, sleep %d seconds (busy %d, can queue %d) ...........\n",
2460 shost->host_no, sleeptime, shost->host_busy, shost->can_queue);
2461 isleep = sleeptime / 10;
2462 spin_unlock_irq(host_lock);
2463 if (isleep > 0) {
2464 for (i = 0; i < isleep; i++) {
2465 msleep(10000);
2466 printk(KERN_NOTICE "^%d^\n", i);
2467 }
2468 }
2469
2470 isleep = sleeptime % 10;
2471 if (isleep > 0) {
2472 msleep(isleep * 1000);
2473 printk(KERN_NOTICE "^v^\n");
2474 }
2475 spin_lock_irq(host_lock);
2476 printk(KERN_NOTICE "***** wake up *****\n");
2477 return 0;
2478 }
2479#endif
2124static void arcmsr_iop_init(struct AdapterControlBlock *acb) 2480static void arcmsr_iop_init(struct AdapterControlBlock *acb)
2125{ 2481{
2126 uint32_t intmask_org; 2482 uint32_t intmask_org;
@@ -2129,7 +2485,7 @@ static void arcmsr_iop_init(struct AdapterControlBlock *acb)
2129 intmask_org = arcmsr_disable_outbound_ints(acb); 2485 intmask_org = arcmsr_disable_outbound_ints(acb);
2130 arcmsr_wait_firmware_ready(acb); 2486 arcmsr_wait_firmware_ready(acb);
2131 arcmsr_iop_confirm(acb); 2487 arcmsr_iop_confirm(acb);
2132 arcmsr_get_firmware_spec(acb); 2488 arcmsr_get_firmware_spec(acb, 1);
2133 /*start background rebuild*/ 2489 /*start background rebuild*/
2134 arcmsr_start_adapter_bgrb(acb); 2490 arcmsr_start_adapter_bgrb(acb);
2135 /* empty doorbell Qbuffer if door bell ringed */ 2491 /* empty doorbell Qbuffer if door bell ringed */
@@ -2140,51 +2496,110 @@ static void arcmsr_iop_init(struct AdapterControlBlock *acb)
2140 acb->acb_flags |= ACB_F_IOP_INITED; 2496 acb->acb_flags |= ACB_F_IOP_INITED;
2141} 2497}
2142 2498
2143static void arcmsr_iop_reset(struct AdapterControlBlock *acb) 2499static uint8_t arcmsr_iop_reset(struct AdapterControlBlock *acb)
2144{ 2500{
2145 struct CommandControlBlock *ccb; 2501 struct CommandControlBlock *ccb;
2146 uint32_t intmask_org; 2502 uint32_t intmask_org;
2503 uint8_t rtnval = 0x00;
2147 int i = 0; 2504 int i = 0;
2148 2505
2149 if (atomic_read(&acb->ccboutstandingcount) != 0) { 2506 if (atomic_read(&acb->ccboutstandingcount) != 0) {
2507 /* disable all outbound interrupt */
2508 intmask_org = arcmsr_disable_outbound_ints(acb);
2150 /* talk to iop 331 outstanding command aborted */ 2509 /* talk to iop 331 outstanding command aborted */
2151 arcmsr_abort_allcmd(acb); 2510 rtnval = arcmsr_abort_allcmd(acb);
2152
2153 /* wait for 3 sec for all command aborted*/ 2511 /* wait for 3 sec for all command aborted*/
2154 ssleep(3); 2512 ssleep(3);
2155
2156 /* disable all outbound interrupt */
2157 intmask_org = arcmsr_disable_outbound_ints(acb);
2158 /* clear all outbound posted Q */ 2513 /* clear all outbound posted Q */
2159 arcmsr_done4abort_postqueue(acb); 2514 arcmsr_done4abort_postqueue(acb);
2160 for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { 2515 for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) {
2161 ccb = acb->pccb_pool[i]; 2516 ccb = acb->pccb_pool[i];
2162 if (ccb->startdone == ARCMSR_CCB_START) { 2517 if (ccb->startdone == ARCMSR_CCB_START) {
2163 ccb->startdone = ARCMSR_CCB_ABORTED;
2164 arcmsr_ccb_complete(ccb, 1); 2518 arcmsr_ccb_complete(ccb, 1);
2165 } 2519 }
2166 } 2520 }
2521 atomic_set(&acb->ccboutstandingcount, 0);
2167 /* enable all outbound interrupt */ 2522 /* enable all outbound interrupt */
2168 arcmsr_enable_outbound_ints(acb, intmask_org); 2523 arcmsr_enable_outbound_ints(acb, intmask_org);
2524 return rtnval;
2169 } 2525 }
2526 return rtnval;
2170} 2527}
2171 2528
2172static int arcmsr_bus_reset(struct scsi_cmnd *cmd) 2529static int arcmsr_bus_reset(struct scsi_cmnd *cmd)
2173{ 2530{
2174 struct AdapterControlBlock *acb = 2531 struct AdapterControlBlock *acb =
2175 (struct AdapterControlBlock *)cmd->device->host->hostdata; 2532 (struct AdapterControlBlock *)cmd->device->host->hostdata;
2176 int i; 2533 int retry = 0;
2177 2534
2178 acb->num_resets++; 2535 if (acb->acb_flags & ACB_F_BUS_RESET)
2536 return SUCCESS;
2537
2538 printk(KERN_NOTICE "arcmsr%d: bus reset ..... \n", acb->adapter_index);
2179 acb->acb_flags |= ACB_F_BUS_RESET; 2539 acb->acb_flags |= ACB_F_BUS_RESET;
2180 for (i = 0; i < 400; i++) { 2540 acb->num_resets++;
2181 if (!atomic_read(&acb->ccboutstandingcount)) 2541 while (atomic_read(&acb->ccboutstandingcount) != 0 && retry < 4) {
2542 arcmsr_interrupt(acb);
2543 retry++;
2544 }
2545
2546 if (arcmsr_iop_reset(acb)) {
2547 switch (acb->adapter_type) {
2548 case ACB_ADAPTER_TYPE_A: {
2549 printk(KERN_NOTICE "arcmsr%d: do hardware bus reset, num_resets = %d num_aborts = %d \n",
2550 acb->adapter_index, acb->num_resets, acb->num_aborts);
2551 arcmsr_hardware_reset(acb);
2552 acb->acb_flags |= ACB_F_FIRMWARE_TRAP;
2553 acb->acb_flags &= ~ACB_F_IOP_INITED;
2554 #ifdef CONFIG_SCSI_ARCMSR_RESET
2555 struct MessageUnit_A __iomem *reg = acb->pmuA;
2556 uint32_t intmask_org, outbound_doorbell;
2557 int retry_count = 0;
2558sleep_again:
2559 arcmsr_sleep_for_bus_reset(cmd);
2560 if ((readl(&reg->outbound_msgaddr1) &
2561 ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0) {
2562 printk(KERN_NOTICE "arcmsr%d: hardware bus reset and return busy, retry=%d \n",
2563 acb->host->host_no, retry_count);
2564 if (retry_count > retrycount) {
2565 printk(KERN_NOTICE "arcmsr%d: hardware bus reset and return busy, retry aborted \n",
2566 acb->host->host_no);
2567 return SUCCESS;
2568 }
2569 retry_count++;
2570 goto sleep_again;
2571 }
2572 acb->acb_flags &= ~ACB_F_FIRMWARE_TRAP;
2573 acb->acb_flags |= ACB_F_IOP_INITED;
2574 acb->acb_flags &= ~ACB_F_BUS_RESET;
2575 printk(KERN_NOTICE "arcmsr%d: hardware bus reset and reset ok \n",
2576 acb->host->host_no);
2577 /* disable all outbound interrupt */
2578 intmask_org = arcmsr_disable_outbound_ints(acb);
2579 arcmsr_get_firmware_spec(acb, 1);
2580 /*start background rebuild*/
2581 arcmsr_start_adapter_bgrb(acb);
2582 /* clear Qbuffer if door bell ringed */
2583 outbound_doorbell = readl(&reg->outbound_doorbell);
2584 writel(outbound_doorbell, &reg->outbound_doorbell); /*clear interrupt */
2585 writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, &reg->inbound_doorbell);
2586 /* enable outbound Post Queue,outbound doorbell Interrupt */
2587 arcmsr_enable_outbound_ints(acb, intmask_org);
2588 atomic_set(&acb->rq_map_token, 16);
2589 init_timer(&acb->eternal_timer);
2590 acb->eternal_timer.expires = jiffies + msecs_to_jiffies(20*HZ);
2591 acb->eternal_timer.data = (unsigned long) acb;
2592 acb->eternal_timer.function = &arcmsr_request_device_map;
2593 add_timer(&acb->eternal_timer);
2594 #endif
2595 }
2182 break; 2596 break;
2183 arcmsr_interrupt(acb);/* FIXME: need spinlock */ 2597 case ACB_ADAPTER_TYPE_B: {
2184 msleep(25);
2185 } 2598 }
2186 arcmsr_iop_reset(acb); 2599 }
2600 } else {
2187 acb->acb_flags &= ~ACB_F_BUS_RESET; 2601 acb->acb_flags &= ~ACB_F_BUS_RESET;
2602 }
2188 return SUCCESS; 2603 return SUCCESS;
2189} 2604}
2190 2605
@@ -2277,98 +2692,3 @@ static const char *arcmsr_info(struct Scsi_Host *host)
2277 ARCMSR_DRIVER_VERSION); 2692 ARCMSR_DRIVER_VERSION);
2278 return buf; 2693 return buf;
2279} 2694}
2280#ifdef CONFIG_SCSI_ARCMSR_AER
2281static pci_ers_result_t arcmsr_pci_slot_reset(struct pci_dev *pdev)
2282{
2283 struct Scsi_Host *host = pci_get_drvdata(pdev);
2284 struct AdapterControlBlock *acb =
2285 (struct AdapterControlBlock *) host->hostdata;
2286 uint32_t intmask_org;
2287 int i, j;
2288
2289 if (pci_enable_device(pdev)) {
2290 return PCI_ERS_RESULT_DISCONNECT;
2291 }
2292 pci_set_master(pdev);
2293 intmask_org = arcmsr_disable_outbound_ints(acb);
2294 acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED |
2295 ACB_F_MESSAGE_RQBUFFER_CLEARED |
2296 ACB_F_MESSAGE_WQBUFFER_READED);
2297 acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER;
2298 for (i = 0; i < ARCMSR_MAX_TARGETID; i++)
2299 for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++)
2300 acb->devstate[i][j] = ARECA_RAID_GONE;
2301
2302 arcmsr_wait_firmware_ready(acb);
2303 arcmsr_iop_confirm(acb);
2304 /* disable all outbound interrupt */
2305 arcmsr_get_firmware_spec(acb);
2306 /*start background rebuild*/
2307 arcmsr_start_adapter_bgrb(acb);
2308 /* empty doorbell Qbuffer if door bell ringed */
2309 arcmsr_clear_doorbell_queue_buffer(acb);
2310 arcmsr_enable_eoi_mode(acb);
2311 /* enable outbound Post Queue,outbound doorbell Interrupt */
2312 arcmsr_enable_outbound_ints(acb, intmask_org);
2313 acb->acb_flags |= ACB_F_IOP_INITED;
2314
2315 pci_enable_pcie_error_reporting(pdev);
2316 return PCI_ERS_RESULT_RECOVERED;
2317}
2318
2319static void arcmsr_pci_ers_need_reset_forepart(struct pci_dev *pdev)
2320{
2321 struct Scsi_Host *host = pci_get_drvdata(pdev);
2322 struct AdapterControlBlock *acb = (struct AdapterControlBlock *)host->hostdata;
2323 struct CommandControlBlock *ccb;
2324 uint32_t intmask_org;
2325 int i = 0;
2326
2327 if (atomic_read(&acb->ccboutstandingcount) != 0) {
2328 /* talk to iop 331 outstanding command aborted */
2329 arcmsr_abort_allcmd(acb);
2330 /* wait for 3 sec for all command aborted*/
2331 ssleep(3);
2332 /* disable all outbound interrupt */
2333 intmask_org = arcmsr_disable_outbound_ints(acb);
2334 /* clear all outbound posted Q */
2335 arcmsr_done4abort_postqueue(acb);
2336 for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) {
2337 ccb = acb->pccb_pool[i];
2338 if (ccb->startdone == ARCMSR_CCB_START) {
2339 ccb->startdone = ARCMSR_CCB_ABORTED;
2340 arcmsr_ccb_complete(ccb, 1);
2341 }
2342 }
2343 /* enable all outbound interrupt */
2344 arcmsr_enable_outbound_ints(acb, intmask_org);
2345 }
2346 pci_disable_device(pdev);
2347}
2348
2349static void arcmsr_pci_ers_disconnect_forepart(struct pci_dev *pdev)
2350{
2351 struct Scsi_Host *host = pci_get_drvdata(pdev);
2352 struct AdapterControlBlock *acb = \
2353 (struct AdapterControlBlock *)host->hostdata;
2354
2355 arcmsr_stop_adapter_bgrb(acb);
2356 arcmsr_flush_adapter_cache(acb);
2357}
2358
2359static pci_ers_result_t arcmsr_pci_error_detected(struct pci_dev *pdev,
2360 pci_channel_state_t state)
2361{
2362 switch (state) {
2363 case pci_channel_io_frozen:
2364 arcmsr_pci_ers_need_reset_forepart(pdev);
2365 return PCI_ERS_RESULT_NEED_RESET;
2366 case pci_channel_io_perm_failure:
2367 arcmsr_pci_ers_disconnect_forepart(pdev);
2368 return PCI_ERS_RESULT_DISCONNECT;
2369 break;
2370 default:
2371 return PCI_ERS_RESULT_NEED_RESET;
2372 }
2373}
2374#endif
diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c
index e641922f20bc..350cbeaae160 100644
--- a/drivers/scsi/be2iscsi/be_mgmt.c
+++ b/drivers/scsi/be2iscsi/be_mgmt.c
@@ -167,10 +167,9 @@ unsigned char mgmt_invalidate_icds(struct beiscsi_hba *phba,
167 &nonemb_cmd.dma); 167 &nonemb_cmd.dma);
168 if (nonemb_cmd.va == NULL) { 168 if (nonemb_cmd.va == NULL) {
169 SE_DEBUG(DBG_LVL_1, 169 SE_DEBUG(DBG_LVL_1,
170 "Failed to allocate memory for" 170 "Failed to allocate memory for mgmt_invalidate_icds\n");
171 "mgmt_invalidate_icds \n");
172 spin_unlock(&ctrl->mbox_lock); 171 spin_unlock(&ctrl->mbox_lock);
173 return -1; 172 return 0;
174 } 173 }
175 nonemb_cmd.size = sizeof(struct invalidate_commands_params_in); 174 nonemb_cmd.size = sizeof(struct invalidate_commands_params_in);
176 req = nonemb_cmd.va; 175 req = nonemb_cmd.va;
diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c
index 0c08e185a766..3a7b3f88932f 100644
--- a/drivers/scsi/bfa/bfa_core.c
+++ b/drivers/scsi/bfa/bfa_core.c
@@ -84,11 +84,32 @@ bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo)
84 for (i = 0; hal_mods[i]; i++) 84 for (i = 0; hal_mods[i]; i++)
85 hal_mods[i]->meminfo(cfg, &km_len, &dm_len); 85 hal_mods[i]->meminfo(cfg, &km_len, &dm_len);
86 86
87 dm_len += bfa_port_meminfo();
87 88
88 meminfo->meminfo[BFA_MEM_TYPE_KVA - 1].mem_len = km_len; 89 meminfo->meminfo[BFA_MEM_TYPE_KVA - 1].mem_len = km_len;
89 meminfo->meminfo[BFA_MEM_TYPE_DMA - 1].mem_len = dm_len; 90 meminfo->meminfo[BFA_MEM_TYPE_DMA - 1].mem_len = dm_len;
90} 91}
91 92
93static void
94bfa_com_port_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi)
95{
96 struct bfa_port_s *port = &bfa->modules.port;
97 uint32_t dm_len;
98 uint8_t *dm_kva;
99 uint64_t dm_pa;
100
101 dm_len = bfa_port_meminfo();
102 dm_kva = bfa_meminfo_dma_virt(mi);
103 dm_pa = bfa_meminfo_dma_phys(mi);
104
105 memset(port, 0, sizeof(struct bfa_port_s));
106 bfa_port_attach(port, &bfa->ioc, bfa, bfa->trcmod, bfa->logm);
107 bfa_port_mem_claim(port, dm_kva, dm_pa);
108
109 bfa_meminfo_dma_virt(mi) = dm_kva + dm_len;
110 bfa_meminfo_dma_phys(mi) = dm_pa + dm_len;
111}
112
92/** 113/**
93 * Use this function to do attach the driver instance with the BFA 114 * Use this function to do attach the driver instance with the BFA
94 * library. This function will not trigger any HW initialization 115 * library. This function will not trigger any HW initialization
@@ -140,6 +161,7 @@ bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
140 for (i = 0; hal_mods[i]; i++) 161 for (i = 0; hal_mods[i]; i++)
141 hal_mods[i]->attach(bfa, bfad, cfg, meminfo, pcidev); 162 hal_mods[i]->attach(bfa, bfad, cfg, meminfo, pcidev);
142 163
164 bfa_com_port_attach(bfa, meminfo);
143} 165}
144 166
145/** 167/**
diff --git a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c
index 18b7102bb80e..2ce26eb7a1ec 100644
--- a/drivers/scsi/gvp11.c
+++ b/drivers/scsi/gvp11.c
@@ -1,36 +1,35 @@
1#include <linux/types.h> 1#include <linux/types.h>
2#include <linux/mm.h>
3#include <linux/slab.h>
4#include <linux/blkdev.h>
5#include <linux/init.h> 2#include <linux/init.h>
6#include <linux/interrupt.h> 3#include <linux/interrupt.h>
4#include <linux/mm.h>
5#include <linux/slab.h>
6#include <linux/spinlock.h>
7#include <linux/zorro.h>
7 8
8#include <asm/setup.h>
9#include <asm/page.h> 9#include <asm/page.h>
10#include <asm/pgtable.h> 10#include <asm/pgtable.h>
11#include <asm/amigaints.h> 11#include <asm/amigaints.h>
12#include <asm/amigahw.h> 12#include <asm/amigahw.h>
13#include <linux/zorro.h>
14#include <asm/irq.h>
15#include <linux/spinlock.h>
16 13
17#include "scsi.h" 14#include "scsi.h"
18#include <scsi/scsi_host.h>
19#include "wd33c93.h" 15#include "wd33c93.h"
20#include "gvp11.h" 16#include "gvp11.h"
21 17
22#include <linux/stat.h>
23 18
19#define CHECK_WD33C93
24 20
25#define DMA(ptr) ((gvp11_scsiregs *)((ptr)->base)) 21struct gvp11_hostdata {
22 struct WD33C93_hostdata wh;
23 struct gvp11_scsiregs *regs;
24};
26 25
27static irqreturn_t gvp11_intr(int irq, void *_instance) 26static irqreturn_t gvp11_intr(int irq, void *data)
28{ 27{
28 struct Scsi_Host *instance = data;
29 struct gvp11_hostdata *hdata = shost_priv(instance);
30 unsigned int status = hdata->regs->CNTR;
29 unsigned long flags; 31 unsigned long flags;
30 unsigned int status;
31 struct Scsi_Host *instance = (struct Scsi_Host *)_instance;
32 32
33 status = DMA(instance)->CNTR;
34 if (!(status & GVP11_DMAC_INT_PENDING)) 33 if (!(status & GVP11_DMAC_INT_PENDING))
35 return IRQ_NONE; 34 return IRQ_NONE;
36 35
@@ -50,64 +49,66 @@ void gvp11_setup(char *str, int *ints)
50static int dma_setup(struct scsi_cmnd *cmd, int dir_in) 49static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
51{ 50{
52 struct Scsi_Host *instance = cmd->device->host; 51 struct Scsi_Host *instance = cmd->device->host;
53 struct WD33C93_hostdata *hdata = shost_priv(instance); 52 struct gvp11_hostdata *hdata = shost_priv(instance);
53 struct WD33C93_hostdata *wh = &hdata->wh;
54 struct gvp11_scsiregs *regs = hdata->regs;
54 unsigned short cntr = GVP11_DMAC_INT_ENABLE; 55 unsigned short cntr = GVP11_DMAC_INT_ENABLE;
55 unsigned long addr = virt_to_bus(cmd->SCp.ptr); 56 unsigned long addr = virt_to_bus(cmd->SCp.ptr);
56 int bank_mask; 57 int bank_mask;
57 static int scsi_alloc_out_of_range = 0; 58 static int scsi_alloc_out_of_range = 0;
58 59
59 /* use bounce buffer if the physical address is bad */ 60 /* use bounce buffer if the physical address is bad */
60 if (addr & hdata->dma_xfer_mask) { 61 if (addr & wh->dma_xfer_mask) {
61 hdata->dma_bounce_len = (cmd->SCp.this_residual + 511) & ~0x1ff; 62 wh->dma_bounce_len = (cmd->SCp.this_residual + 511) & ~0x1ff;
62 63
63 if (!scsi_alloc_out_of_range) { 64 if (!scsi_alloc_out_of_range) {
64 hdata->dma_bounce_buffer = 65 wh->dma_bounce_buffer =
65 kmalloc(hdata->dma_bounce_len, GFP_KERNEL); 66 kmalloc(wh->dma_bounce_len, GFP_KERNEL);
66 hdata->dma_buffer_pool = BUF_SCSI_ALLOCED; 67 wh->dma_buffer_pool = BUF_SCSI_ALLOCED;
67 } 68 }
68 69
69 if (scsi_alloc_out_of_range || 70 if (scsi_alloc_out_of_range ||
70 !hdata->dma_bounce_buffer) { 71 !wh->dma_bounce_buffer) {
71 hdata->dma_bounce_buffer = 72 wh->dma_bounce_buffer =
72 amiga_chip_alloc(hdata->dma_bounce_len, 73 amiga_chip_alloc(wh->dma_bounce_len,
73 "GVP II SCSI Bounce Buffer"); 74 "GVP II SCSI Bounce Buffer");
74 75
75 if (!hdata->dma_bounce_buffer) { 76 if (!wh->dma_bounce_buffer) {
76 hdata->dma_bounce_len = 0; 77 wh->dma_bounce_len = 0;
77 return 1; 78 return 1;
78 } 79 }
79 80
80 hdata->dma_buffer_pool = BUF_CHIP_ALLOCED; 81 wh->dma_buffer_pool = BUF_CHIP_ALLOCED;
81 } 82 }
82 83
83 /* check if the address of the bounce buffer is OK */ 84 /* check if the address of the bounce buffer is OK */
84 addr = virt_to_bus(hdata->dma_bounce_buffer); 85 addr = virt_to_bus(wh->dma_bounce_buffer);
85 86
86 if (addr & hdata->dma_xfer_mask) { 87 if (addr & wh->dma_xfer_mask) {
87 /* fall back to Chip RAM if address out of range */ 88 /* fall back to Chip RAM if address out of range */
88 if (hdata->dma_buffer_pool == BUF_SCSI_ALLOCED) { 89 if (wh->dma_buffer_pool == BUF_SCSI_ALLOCED) {
89 kfree(hdata->dma_bounce_buffer); 90 kfree(wh->dma_bounce_buffer);
90 scsi_alloc_out_of_range = 1; 91 scsi_alloc_out_of_range = 1;
91 } else { 92 } else {
92 amiga_chip_free(hdata->dma_bounce_buffer); 93 amiga_chip_free(wh->dma_bounce_buffer);
93 } 94 }
94 95
95 hdata->dma_bounce_buffer = 96 wh->dma_bounce_buffer =
96 amiga_chip_alloc(hdata->dma_bounce_len, 97 amiga_chip_alloc(wh->dma_bounce_len,
97 "GVP II SCSI Bounce Buffer"); 98 "GVP II SCSI Bounce Buffer");
98 99
99 if (!hdata->dma_bounce_buffer) { 100 if (!wh->dma_bounce_buffer) {
100 hdata->dma_bounce_len = 0; 101 wh->dma_bounce_len = 0;
101 return 1; 102 return 1;
102 } 103 }
103 104
104 addr = virt_to_bus(hdata->dma_bounce_buffer); 105 addr = virt_to_bus(wh->dma_bounce_buffer);
105 hdata->dma_buffer_pool = BUF_CHIP_ALLOCED; 106 wh->dma_buffer_pool = BUF_CHIP_ALLOCED;
106 } 107 }
107 108
108 if (!dir_in) { 109 if (!dir_in) {
109 /* copy to bounce buffer for a write */ 110 /* copy to bounce buffer for a write */
110 memcpy(hdata->dma_bounce_buffer, cmd->SCp.ptr, 111 memcpy(wh->dma_bounce_buffer, cmd->SCp.ptr,
111 cmd->SCp.this_residual); 112 cmd->SCp.this_residual);
112 } 113 }
113 } 114 }
@@ -116,11 +117,11 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
116 if (!dir_in) 117 if (!dir_in)
117 cntr |= GVP11_DMAC_DIR_WRITE; 118 cntr |= GVP11_DMAC_DIR_WRITE;
118 119
119 hdata->dma_dir = dir_in; 120 wh->dma_dir = dir_in;
120 DMA(cmd->device->host)->CNTR = cntr; 121 regs->CNTR = cntr;
121 122
122 /* setup DMA *physical* address */ 123 /* setup DMA *physical* address */
123 DMA(cmd->device->host)->ACR = addr; 124 regs->ACR = addr;
124 125
125 if (dir_in) { 126 if (dir_in) {
126 /* invalidate any cache */ 127 /* invalidate any cache */
@@ -130,12 +131,12 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
130 cache_push(addr, cmd->SCp.this_residual); 131 cache_push(addr, cmd->SCp.this_residual);
131 } 132 }
132 133
133 bank_mask = (~hdata->dma_xfer_mask >> 18) & 0x01c0; 134 bank_mask = (~wh->dma_xfer_mask >> 18) & 0x01c0;
134 if (bank_mask) 135 if (bank_mask)
135 DMA(cmd->device->host)->BANK = bank_mask & (addr >> 18); 136 regs->BANK = bank_mask & (addr >> 18);
136 137
137 /* start DMA */ 138 /* start DMA */
138 DMA(cmd->device->host)->ST_DMA = 1; 139 regs->ST_DMA = 1;
139 140
140 /* return success */ 141 /* return success */
141 return 0; 142 return 0;
@@ -144,236 +145,53 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
144static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, 145static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt,
145 int status) 146 int status)
146{ 147{
147 struct WD33C93_hostdata *hdata = shost_priv(instance); 148 struct gvp11_hostdata *hdata = shost_priv(instance);
149 struct WD33C93_hostdata *wh = &hdata->wh;
150 struct gvp11_scsiregs *regs = hdata->regs;
148 151
149 /* stop DMA */ 152 /* stop DMA */
150 DMA(instance)->SP_DMA = 1; 153 regs->SP_DMA = 1;
151 /* remove write bit from CONTROL bits */ 154 /* remove write bit from CONTROL bits */
152 DMA(instance)->CNTR = GVP11_DMAC_INT_ENABLE; 155 regs->CNTR = GVP11_DMAC_INT_ENABLE;
153 156
154 /* copy from a bounce buffer, if necessary */ 157 /* copy from a bounce buffer, if necessary */
155 if (status && hdata->dma_bounce_buffer) { 158 if (status && wh->dma_bounce_buffer) {
156 if (hdata->dma_dir && SCpnt) 159 if (wh->dma_dir && SCpnt)
157 memcpy(SCpnt->SCp.ptr, hdata->dma_bounce_buffer, 160 memcpy(SCpnt->SCp.ptr, wh->dma_bounce_buffer,
158 SCpnt->SCp.this_residual); 161 SCpnt->SCp.this_residual);
159 162
160 if (hdata->dma_buffer_pool == BUF_SCSI_ALLOCED) 163 if (wh->dma_buffer_pool == BUF_SCSI_ALLOCED)
161 kfree(hdata->dma_bounce_buffer); 164 kfree(wh->dma_bounce_buffer);
162 else
163 amiga_chip_free(hdata->dma_bounce_buffer);
164
165 hdata->dma_bounce_buffer = NULL;
166 hdata->dma_bounce_len = 0;
167 }
168}
169
170#define CHECK_WD33C93
171
172int __init gvp11_detect(struct scsi_host_template *tpnt)
173{
174 static unsigned char called = 0;
175 struct Scsi_Host *instance;
176 unsigned long address;
177 unsigned int epc;
178 struct zorro_dev *z = NULL;
179 unsigned int default_dma_xfer_mask;
180 struct WD33C93_hostdata *hdata;
181 wd33c93_regs regs;
182 int num_gvp11 = 0;
183#ifdef CHECK_WD33C93
184 volatile unsigned char *sasr_3393, *scmd_3393;
185 unsigned char save_sasr;
186 unsigned char q, qq;
187#endif
188
189 if (!MACH_IS_AMIGA || called)
190 return 0;
191 called = 1;
192
193 tpnt->proc_name = "GVP11";
194 tpnt->proc_info = &wd33c93_proc_info;
195
196 while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
197 /*
198 * This should (hopefully) be the correct way to identify
199 * all the different GVP SCSI controllers (except for the
200 * SERIES I though).
201 */
202
203 if (z->id == ZORRO_PROD_GVP_COMBO_030_R3_SCSI ||
204 z->id == ZORRO_PROD_GVP_SERIES_II)
205 default_dma_xfer_mask = ~0x00ffffff;
206 else if (z->id == ZORRO_PROD_GVP_GFORCE_030_SCSI ||
207 z->id == ZORRO_PROD_GVP_A530_SCSI ||
208 z->id == ZORRO_PROD_GVP_COMBO_030_R4_SCSI)
209 default_dma_xfer_mask = ~0x01ffffff;
210 else if (z->id == ZORRO_PROD_GVP_A1291 ||
211 z->id == ZORRO_PROD_GVP_GFORCE_040_SCSI_1)
212 default_dma_xfer_mask = ~0x07ffffff;
213 else 165 else
214 continue; 166 amiga_chip_free(wh->dma_bounce_buffer);
215
216 /*
217 * Rumors state that some GVP ram boards use the same product
218 * code as the SCSI controllers. Therefore if the board-size
219 * is not 64KB we asume it is a ram board and bail out.
220 */
221 if (z->resource.end - z->resource.start != 0xffff)
222 continue;
223 167
224 address = z->resource.start; 168 wh->dma_bounce_buffer = NULL;
225 if (!request_mem_region(address, 256, "wd33c93")) 169 wh->dma_bounce_len = 0;
226 continue;
227
228#ifdef CHECK_WD33C93
229
230 /*
231 * These darn GVP boards are a problem - it can be tough to tell
232 * whether or not they include a SCSI controller. This is the
233 * ultimate Yet-Another-GVP-Detection-Hack in that it actually
234 * probes for a WD33c93 chip: If we find one, it's extremely
235 * likely that this card supports SCSI, regardless of Product_
236 * Code, Board_Size, etc.
237 */
238
239 /* Get pointers to the presumed register locations and save contents */
240
241 sasr_3393 = &(((gvp11_scsiregs *)(ZTWO_VADDR(address)))->SASR);
242 scmd_3393 = &(((gvp11_scsiregs *)(ZTWO_VADDR(address)))->SCMD);
243 save_sasr = *sasr_3393;
244
245 /* First test the AuxStatus Reg */
246
247 q = *sasr_3393; /* read it */
248 if (q & 0x08) /* bit 3 should always be clear */
249 goto release;
250 *sasr_3393 = WD_AUXILIARY_STATUS; /* setup indirect address */
251 if (*sasr_3393 == WD_AUXILIARY_STATUS) { /* shouldn't retain the write */
252 *sasr_3393 = save_sasr; /* Oops - restore this byte */
253 goto release;
254 }
255 if (*sasr_3393 != q) { /* should still read the same */
256 *sasr_3393 = save_sasr; /* Oops - restore this byte */
257 goto release;
258 }
259 if (*scmd_3393 != q) /* and so should the image at 0x1f */
260 goto release;
261
262 /*
263 * Ok, we probably have a wd33c93, but let's check a few other places
264 * for good measure. Make sure that this works for both 'A and 'B
265 * chip versions.
266 */
267
268 *sasr_3393 = WD_SCSI_STATUS;
269 q = *scmd_3393;
270 *sasr_3393 = WD_SCSI_STATUS;
271 *scmd_3393 = ~q;
272 *sasr_3393 = WD_SCSI_STATUS;
273 qq = *scmd_3393;
274 *sasr_3393 = WD_SCSI_STATUS;
275 *scmd_3393 = q;
276 if (qq != q) /* should be read only */
277 goto release;
278 *sasr_3393 = 0x1e; /* this register is unimplemented */
279 q = *scmd_3393;
280 *sasr_3393 = 0x1e;
281 *scmd_3393 = ~q;
282 *sasr_3393 = 0x1e;
283 qq = *scmd_3393;
284 *sasr_3393 = 0x1e;
285 *scmd_3393 = q;
286 if (qq != q || qq != 0xff) /* should be read only, all 1's */
287 goto release;
288 *sasr_3393 = WD_TIMEOUT_PERIOD;
289 q = *scmd_3393;
290 *sasr_3393 = WD_TIMEOUT_PERIOD;
291 *scmd_3393 = ~q;
292 *sasr_3393 = WD_TIMEOUT_PERIOD;
293 qq = *scmd_3393;
294 *sasr_3393 = WD_TIMEOUT_PERIOD;
295 *scmd_3393 = q;
296 if (qq != (~q & 0xff)) /* should be read/write */
297 goto release;
298#endif
299
300 instance = scsi_register(tpnt, sizeof(struct WD33C93_hostdata));
301 if (instance == NULL)
302 goto release;
303 instance->base = ZTWO_VADDR(address);
304 instance->irq = IRQ_AMIGA_PORTS;
305 instance->unique_id = z->slotaddr;
306
307 hdata = shost_priv(instance);
308 if (gvp11_xfer_mask)
309 hdata->dma_xfer_mask = gvp11_xfer_mask;
310 else
311 hdata->dma_xfer_mask = default_dma_xfer_mask;
312
313 DMA(instance)->secret2 = 1;
314 DMA(instance)->secret1 = 0;
315 DMA(instance)->secret3 = 15;
316 while (DMA(instance)->CNTR & GVP11_DMAC_BUSY)
317 ;
318 DMA(instance)->CNTR = 0;
319
320 DMA(instance)->BANK = 0;
321
322 epc = *(unsigned short *)(ZTWO_VADDR(address) + 0x8000);
323
324 /*
325 * Check for 14MHz SCSI clock
326 */
327 regs.SASR = &(DMA(instance)->SASR);
328 regs.SCMD = &(DMA(instance)->SCMD);
329 hdata->no_sync = 0xff;
330 hdata->fast = 0;
331 hdata->dma_mode = CTRL_DMA;
332 wd33c93_init(instance, regs, dma_setup, dma_stop,
333 (epc & GVP_SCSICLKMASK) ? WD33C93_FS_8_10
334 : WD33C93_FS_12_15);
335
336 if (request_irq(IRQ_AMIGA_PORTS, gvp11_intr, IRQF_SHARED,
337 "GVP11 SCSI", instance))
338 goto unregister;
339 DMA(instance)->CNTR = GVP11_DMAC_INT_ENABLE;
340 num_gvp11++;
341 continue;
342
343unregister:
344 scsi_unregister(instance);
345release:
346 release_mem_region(address, 256);
347 } 170 }
348
349 return num_gvp11;
350} 171}
351 172
352static int gvp11_bus_reset(struct scsi_cmnd *cmd) 173static int gvp11_bus_reset(struct scsi_cmnd *cmd)
353{ 174{
175 struct Scsi_Host *instance = cmd->device->host;
176
354 /* FIXME perform bus-specific reset */ 177 /* FIXME perform bus-specific reset */
355 178
356 /* FIXME 2: shouldn't we no-op this function (return 179 /* FIXME 2: shouldn't we no-op this function (return
357 FAILED), and fall back to host reset function, 180 FAILED), and fall back to host reset function,
358 wd33c93_host_reset ? */ 181 wd33c93_host_reset ? */
359 182
360 spin_lock_irq(cmd->device->host->host_lock); 183 spin_lock_irq(instance->host_lock);
361 wd33c93_host_reset(cmd); 184 wd33c93_host_reset(cmd);
362 spin_unlock_irq(cmd->device->host->host_lock); 185 spin_unlock_irq(instance->host_lock);
363 186
364 return SUCCESS; 187 return SUCCESS;
365} 188}
366 189
367 190static struct scsi_host_template gvp11_scsi_template = {
368#define HOSTS_C 191 .module = THIS_MODULE,
369
370#include "gvp11.h"
371
372static struct scsi_host_template driver_template = {
373 .proc_name = "GVP11",
374 .name = "GVP Series II SCSI", 192 .name = "GVP Series II SCSI",
375 .detect = gvp11_detect, 193 .proc_info = wd33c93_proc_info,
376 .release = gvp11_release, 194 .proc_name = "GVP11",
377 .queuecommand = wd33c93_queuecommand, 195 .queuecommand = wd33c93_queuecommand,
378 .eh_abort_handler = wd33c93_abort, 196 .eh_abort_handler = wd33c93_abort,
379 .eh_bus_reset_handler = gvp11_bus_reset, 197 .eh_bus_reset_handler = gvp11_bus_reset,
@@ -385,17 +203,230 @@ static struct scsi_host_template driver_template = {
385 .use_clustering = DISABLE_CLUSTERING 203 .use_clustering = DISABLE_CLUSTERING
386}; 204};
387 205
206static int __devinit check_wd33c93(struct gvp11_scsiregs *regs)
207{
208#ifdef CHECK_WD33C93
209 volatile unsigned char *sasr_3393, *scmd_3393;
210 unsigned char save_sasr;
211 unsigned char q, qq;
388 212
389#include "scsi_module.c" 213 /*
214 * These darn GVP boards are a problem - it can be tough to tell
215 * whether or not they include a SCSI controller. This is the
216 * ultimate Yet-Another-GVP-Detection-Hack in that it actually
217 * probes for a WD33c93 chip: If we find one, it's extremely
218 * likely that this card supports SCSI, regardless of Product_
219 * Code, Board_Size, etc.
220 */
221
222 /* Get pointers to the presumed register locations and save contents */
223
224 sasr_3393 = &regs->SASR;
225 scmd_3393 = &regs->SCMD;
226 save_sasr = *sasr_3393;
227
228 /* First test the AuxStatus Reg */
229
230 q = *sasr_3393; /* read it */
231 if (q & 0x08) /* bit 3 should always be clear */
232 return -ENODEV;
233 *sasr_3393 = WD_AUXILIARY_STATUS; /* setup indirect address */
234 if (*sasr_3393 == WD_AUXILIARY_STATUS) { /* shouldn't retain the write */
235 *sasr_3393 = save_sasr; /* Oops - restore this byte */
236 return -ENODEV;
237 }
238 if (*sasr_3393 != q) { /* should still read the same */
239 *sasr_3393 = save_sasr; /* Oops - restore this byte */
240 return -ENODEV;
241 }
242 if (*scmd_3393 != q) /* and so should the image at 0x1f */
243 return -ENODEV;
244
245 /*
246 * Ok, we probably have a wd33c93, but let's check a few other places
247 * for good measure. Make sure that this works for both 'A and 'B
248 * chip versions.
249 */
250
251 *sasr_3393 = WD_SCSI_STATUS;
252 q = *scmd_3393;
253 *sasr_3393 = WD_SCSI_STATUS;
254 *scmd_3393 = ~q;
255 *sasr_3393 = WD_SCSI_STATUS;
256 qq = *scmd_3393;
257 *sasr_3393 = WD_SCSI_STATUS;
258 *scmd_3393 = q;
259 if (qq != q) /* should be read only */
260 return -ENODEV;
261 *sasr_3393 = 0x1e; /* this register is unimplemented */
262 q = *scmd_3393;
263 *sasr_3393 = 0x1e;
264 *scmd_3393 = ~q;
265 *sasr_3393 = 0x1e;
266 qq = *scmd_3393;
267 *sasr_3393 = 0x1e;
268 *scmd_3393 = q;
269 if (qq != q || qq != 0xff) /* should be read only, all 1's */
270 return -ENODEV;
271 *sasr_3393 = WD_TIMEOUT_PERIOD;
272 q = *scmd_3393;
273 *sasr_3393 = WD_TIMEOUT_PERIOD;
274 *scmd_3393 = ~q;
275 *sasr_3393 = WD_TIMEOUT_PERIOD;
276 qq = *scmd_3393;
277 *sasr_3393 = WD_TIMEOUT_PERIOD;
278 *scmd_3393 = q;
279 if (qq != (~q & 0xff)) /* should be read/write */
280 return -ENODEV;
281#endif /* CHECK_WD33C93 */
390 282
391int gvp11_release(struct Scsi_Host *instance) 283 return 0;
284}
285
286static int __devinit gvp11_probe(struct zorro_dev *z,
287 const struct zorro_device_id *ent)
392{ 288{
393#ifdef MODULE 289 struct Scsi_Host *instance;
394 DMA(instance)->CNTR = 0; 290 unsigned long address;
395 release_mem_region(ZTWO_PADDR(instance->base), 256); 291 int error;
292 unsigned int epc;
293 unsigned int default_dma_xfer_mask;
294 struct gvp11_hostdata *hdata;
295 struct gvp11_scsiregs *regs;
296 wd33c93_regs wdregs;
297
298 default_dma_xfer_mask = ent->driver_data;
299
300 /*
301 * Rumors state that some GVP ram boards use the same product
302 * code as the SCSI controllers. Therefore if the board-size
303 * is not 64KB we asume it is a ram board and bail out.
304 */
305 if (zorro_resource_len(z) != 0x10000)
306 return -ENODEV;
307
308 address = z->resource.start;
309 if (!request_mem_region(address, 256, "wd33c93"))
310 return -EBUSY;
311
312 regs = (struct gvp11_scsiregs *)(ZTWO_VADDR(address));
313
314 error = check_wd33c93(regs);
315 if (error)
316 goto fail_check_or_alloc;
317
318 instance = scsi_host_alloc(&gvp11_scsi_template,
319 sizeof(struct gvp11_hostdata));
320 if (!instance) {
321 error = -ENOMEM;
322 goto fail_check_or_alloc;
323 }
324
325 instance->irq = IRQ_AMIGA_PORTS;
326 instance->unique_id = z->slotaddr;
327
328 regs->secret2 = 1;
329 regs->secret1 = 0;
330 regs->secret3 = 15;
331 while (regs->CNTR & GVP11_DMAC_BUSY)
332 ;
333 regs->CNTR = 0;
334 regs->BANK = 0;
335
336 wdregs.SASR = &regs->SASR;
337 wdregs.SCMD = &regs->SCMD;
338
339 hdata = shost_priv(instance);
340 if (gvp11_xfer_mask)
341 hdata->wh.dma_xfer_mask = gvp11_xfer_mask;
342 else
343 hdata->wh.dma_xfer_mask = default_dma_xfer_mask;
344
345 hdata->wh.no_sync = 0xff;
346 hdata->wh.fast = 0;
347 hdata->wh.dma_mode = CTRL_DMA;
348 hdata->regs = regs;
349
350 /*
351 * Check for 14MHz SCSI clock
352 */
353 epc = *(unsigned short *)(ZTWO_VADDR(address) + 0x8000);
354 wd33c93_init(instance, wdregs, dma_setup, dma_stop,
355 (epc & GVP_SCSICLKMASK) ? WD33C93_FS_8_10
356 : WD33C93_FS_12_15);
357
358 error = request_irq(IRQ_AMIGA_PORTS, gvp11_intr, IRQF_SHARED,
359 "GVP11 SCSI", instance);
360 if (error)
361 goto fail_irq;
362
363 regs->CNTR = GVP11_DMAC_INT_ENABLE;
364
365 error = scsi_add_host(instance, NULL);
366 if (error)
367 goto fail_host;
368
369 zorro_set_drvdata(z, instance);
370 scsi_scan_host(instance);
371 return 0;
372
373fail_host:
396 free_irq(IRQ_AMIGA_PORTS, instance); 374 free_irq(IRQ_AMIGA_PORTS, instance);
397#endif 375fail_irq:
398 return 1; 376 scsi_host_put(instance);
377fail_check_or_alloc:
378 release_mem_region(address, 256);
379 return error;
380}
381
382static void __devexit gvp11_remove(struct zorro_dev *z)
383{
384 struct Scsi_Host *instance = zorro_get_drvdata(z);
385 struct gvp11_hostdata *hdata = shost_priv(instance);
386
387 hdata->regs->CNTR = 0;
388 scsi_remove_host(instance);
389 free_irq(IRQ_AMIGA_PORTS, instance);
390 scsi_host_put(instance);
391 release_mem_region(z->resource.start, 256);
392}
393
394 /*
395 * This should (hopefully) be the correct way to identify
396 * all the different GVP SCSI controllers (except for the
397 * SERIES I though).
398 */
399
400static struct zorro_device_id gvp11_zorro_tbl[] __devinitdata = {
401 { ZORRO_PROD_GVP_COMBO_030_R3_SCSI, ~0x00ffffff },
402 { ZORRO_PROD_GVP_SERIES_II, ~0x00ffffff },
403 { ZORRO_PROD_GVP_GFORCE_030_SCSI, ~0x01ffffff },
404 { ZORRO_PROD_GVP_A530_SCSI, ~0x01ffffff },
405 { ZORRO_PROD_GVP_COMBO_030_R4_SCSI, ~0x01ffffff },
406 { ZORRO_PROD_GVP_A1291, ~0x07ffffff },
407 { ZORRO_PROD_GVP_GFORCE_040_SCSI_1, ~0x07ffffff },
408 { 0 }
409};
410MODULE_DEVICE_TABLE(zorro, gvp11_zorro_tbl);
411
412static struct zorro_driver gvp11_driver = {
413 .name = "gvp11",
414 .id_table = gvp11_zorro_tbl,
415 .probe = gvp11_probe,
416 .remove = __devexit_p(gvp11_remove),
417};
418
419static int __init gvp11_init(void)
420{
421 return zorro_register_driver(&gvp11_driver);
422}
423module_init(gvp11_init);
424
425static void __exit gvp11_exit(void)
426{
427 zorro_unregister_driver(&gvp11_driver);
399} 428}
429module_exit(gvp11_exit);
400 430
431MODULE_DESCRIPTION("GVP Series II SCSI");
401MODULE_LICENSE("GPL"); 432MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/gvp11.h b/drivers/scsi/gvp11.h
index e2efdf9601ef..852913cde5dd 100644
--- a/drivers/scsi/gvp11.h
+++ b/drivers/scsi/gvp11.h
@@ -11,9 +11,6 @@
11 11
12#include <linux/types.h> 12#include <linux/types.h>
13 13
14int gvp11_detect(struct scsi_host_template *);
15int gvp11_release(struct Scsi_Host *);
16
17#ifndef CMD_PER_LUN 14#ifndef CMD_PER_LUN
18#define CMD_PER_LUN 2 15#define CMD_PER_LUN 2
19#endif 16#endif
@@ -22,15 +19,13 @@ int gvp11_release(struct Scsi_Host *);
22#define CAN_QUEUE 16 19#define CAN_QUEUE 16
23#endif 20#endif
24 21
25#ifndef HOSTS_C
26
27/* 22/*
28 * if the transfer address ANDed with this results in a non-zero 23 * if the transfer address ANDed with this results in a non-zero
29 * result, then we can't use DMA. 24 * result, then we can't use DMA.
30 */ 25 */
31#define GVP11_XFER_MASK (0xff000001) 26#define GVP11_XFER_MASK (0xff000001)
32 27
33typedef struct { 28struct gvp11_scsiregs {
34 unsigned char pad1[64]; 29 unsigned char pad1[64];
35 volatile unsigned short CNTR; 30 volatile unsigned short CNTR;
36 unsigned char pad2[31]; 31 unsigned char pad2[31];
@@ -46,7 +41,7 @@ typedef struct {
46 volatile unsigned short SP_DMA; 41 volatile unsigned short SP_DMA;
47 volatile unsigned short secret2; /* store 1 here */ 42 volatile unsigned short secret2; /* store 1 here */
48 volatile unsigned short secret3; /* store 15 here */ 43 volatile unsigned short secret3; /* store 15 here */
49} gvp11_scsiregs; 44};
50 45
51/* bits in CNTR */ 46/* bits in CNTR */
52#define GVP11_DMAC_BUSY (1<<0) 47#define GVP11_DMAC_BUSY (1<<0)
@@ -54,6 +49,4 @@ typedef struct {
54#define GVP11_DMAC_INT_ENABLE (1<<3) 49#define GVP11_DMAC_INT_ENABLE (1<<3)
55#define GVP11_DMAC_DIR_WRITE (1<<4) 50#define GVP11_DMAC_DIR_WRITE (1<<4)
56 51
57#endif /* else def HOSTS_C */
58
59#endif /* GVP11_H */ 52#endif /* GVP11_H */
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 6a6661c35b2f..82ea4a8226b0 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -567,7 +567,8 @@ static void ipr_trc_hook(struct ipr_cmnd *ipr_cmd,
567static void ipr_reinit_ipr_cmnd(struct ipr_cmnd *ipr_cmd) 567static void ipr_reinit_ipr_cmnd(struct ipr_cmnd *ipr_cmd)
568{ 568{
569 struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb; 569 struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb;
570 struct ipr_ioasa *ioasa = &ipr_cmd->ioasa; 570 struct ipr_ioasa *ioasa = &ipr_cmd->s.ioasa;
571 struct ipr_ioasa64 *ioasa64 = &ipr_cmd->s.ioasa64;
571 dma_addr_t dma_addr = ipr_cmd->dma_addr; 572 dma_addr_t dma_addr = ipr_cmd->dma_addr;
572 573
573 memset(&ioarcb->cmd_pkt, 0, sizeof(struct ipr_cmd_pkt)); 574 memset(&ioarcb->cmd_pkt, 0, sizeof(struct ipr_cmd_pkt));
@@ -576,19 +577,19 @@ static void ipr_reinit_ipr_cmnd(struct ipr_cmnd *ipr_cmd)
576 ioarcb->ioadl_len = 0; 577 ioarcb->ioadl_len = 0;
577 ioarcb->read_ioadl_len = 0; 578 ioarcb->read_ioadl_len = 0;
578 579
579 if (ipr_cmd->ioa_cfg->sis64) 580 if (ipr_cmd->ioa_cfg->sis64) {
580 ioarcb->u.sis64_addr_data.data_ioadl_addr = 581 ioarcb->u.sis64_addr_data.data_ioadl_addr =
581 cpu_to_be64(dma_addr + offsetof(struct ipr_cmnd, i.ioadl64)); 582 cpu_to_be64(dma_addr + offsetof(struct ipr_cmnd, i.ioadl64));
582 else { 583 ioasa64->u.gata.status = 0;
584 } else {
583 ioarcb->write_ioadl_addr = 585 ioarcb->write_ioadl_addr =
584 cpu_to_be32(dma_addr + offsetof(struct ipr_cmnd, i.ioadl)); 586 cpu_to_be32(dma_addr + offsetof(struct ipr_cmnd, i.ioadl));
585 ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr; 587 ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr;
588 ioasa->u.gata.status = 0;
586 } 589 }
587 590
588 ioasa->ioasc = 0; 591 ioasa->hdr.ioasc = 0;
589 ioasa->residual_data_len = 0; 592 ioasa->hdr.residual_data_len = 0;
590 ioasa->u.gata.status = 0;
591
592 ipr_cmd->scsi_cmd = NULL; 593 ipr_cmd->scsi_cmd = NULL;
593 ipr_cmd->qc = NULL; 594 ipr_cmd->qc = NULL;
594 ipr_cmd->sense_buffer[0] = 0; 595 ipr_cmd->sense_buffer[0] = 0;
@@ -768,8 +769,8 @@ static void ipr_fail_all_ops(struct ipr_ioa_cfg *ioa_cfg)
768 list_for_each_entry_safe(ipr_cmd, temp, &ioa_cfg->pending_q, queue) { 769 list_for_each_entry_safe(ipr_cmd, temp, &ioa_cfg->pending_q, queue) {
769 list_del(&ipr_cmd->queue); 770 list_del(&ipr_cmd->queue);
770 771
771 ipr_cmd->ioasa.ioasc = cpu_to_be32(IPR_IOASC_IOA_WAS_RESET); 772 ipr_cmd->s.ioasa.hdr.ioasc = cpu_to_be32(IPR_IOASC_IOA_WAS_RESET);
772 ipr_cmd->ioasa.ilid = cpu_to_be32(IPR_DRIVER_ILID); 773 ipr_cmd->s.ioasa.hdr.ilid = cpu_to_be32(IPR_DRIVER_ILID);
773 774
774 if (ipr_cmd->scsi_cmd) 775 if (ipr_cmd->scsi_cmd)
775 ipr_cmd->done = ipr_scsi_eh_done; 776 ipr_cmd->done = ipr_scsi_eh_done;
@@ -1040,7 +1041,7 @@ static void ipr_init_res_entry(struct ipr_resource_entry *res,
1040 proto = cfgtew->u.cfgte64->proto; 1041 proto = cfgtew->u.cfgte64->proto;
1041 res->res_flags = cfgtew->u.cfgte64->res_flags; 1042 res->res_flags = cfgtew->u.cfgte64->res_flags;
1042 res->qmodel = IPR_QUEUEING_MODEL64(res); 1043 res->qmodel = IPR_QUEUEING_MODEL64(res);
1043 res->type = cfgtew->u.cfgte64->res_type & 0x0f; 1044 res->type = cfgtew->u.cfgte64->res_type;
1044 1045
1045 memcpy(res->res_path, &cfgtew->u.cfgte64->res_path, 1046 memcpy(res->res_path, &cfgtew->u.cfgte64->res_path,
1046 sizeof(res->res_path)); 1047 sizeof(res->res_path));
@@ -1319,7 +1320,7 @@ static void ipr_process_ccn(struct ipr_cmnd *ipr_cmd)
1319{ 1320{
1320 struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; 1321 struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
1321 struct ipr_hostrcb *hostrcb = ipr_cmd->u.hostrcb; 1322 struct ipr_hostrcb *hostrcb = ipr_cmd->u.hostrcb;
1322 u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); 1323 u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
1323 1324
1324 list_del(&hostrcb->queue); 1325 list_del(&hostrcb->queue);
1325 list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q); 1326 list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
@@ -2354,7 +2355,7 @@ static void ipr_process_error(struct ipr_cmnd *ipr_cmd)
2354{ 2355{
2355 struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; 2356 struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
2356 struct ipr_hostrcb *hostrcb = ipr_cmd->u.hostrcb; 2357 struct ipr_hostrcb *hostrcb = ipr_cmd->u.hostrcb;
2357 u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); 2358 u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
2358 u32 fd_ioasc; 2359 u32 fd_ioasc;
2359 2360
2360 if (ioa_cfg->sis64) 2361 if (ioa_cfg->sis64)
@@ -4509,11 +4510,16 @@ static int ipr_device_reset(struct ipr_ioa_cfg *ioa_cfg,
4509 } 4510 }
4510 4511
4511 ipr_send_blocking_cmd(ipr_cmd, ipr_timeout, IPR_DEVICE_RESET_TIMEOUT); 4512 ipr_send_blocking_cmd(ipr_cmd, ipr_timeout, IPR_DEVICE_RESET_TIMEOUT);
4512 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); 4513 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
4513 list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q); 4514 list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
4514 if (ipr_is_gata(res) && res->sata_port && ioasc != IPR_IOASC_IOA_WAS_RESET) 4515 if (ipr_is_gata(res) && res->sata_port && ioasc != IPR_IOASC_IOA_WAS_RESET) {
4515 memcpy(&res->sata_port->ioasa, &ipr_cmd->ioasa.u.gata, 4516 if (ipr_cmd->ioa_cfg->sis64)
4516 sizeof(struct ipr_ioasa_gata)); 4517 memcpy(&res->sata_port->ioasa, &ipr_cmd->s.ioasa64.u.gata,
4518 sizeof(struct ipr_ioasa_gata));
4519 else
4520 memcpy(&res->sata_port->ioasa, &ipr_cmd->s.ioasa.u.gata,
4521 sizeof(struct ipr_ioasa_gata));
4522 }
4517 4523
4518 LEAVE; 4524 LEAVE;
4519 return (IPR_IOASC_SENSE_KEY(ioasc) ? -EIO : 0); 4525 return (IPR_IOASC_SENSE_KEY(ioasc) ? -EIO : 0);
@@ -4768,7 +4774,7 @@ static int ipr_cancel_op(struct scsi_cmnd * scsi_cmd)
4768 scmd_printk(KERN_ERR, scsi_cmd, "Aborting command: %02X\n", 4774 scmd_printk(KERN_ERR, scsi_cmd, "Aborting command: %02X\n",
4769 scsi_cmd->cmnd[0]); 4775 scsi_cmd->cmnd[0]);
4770 ipr_send_blocking_cmd(ipr_cmd, ipr_abort_timeout, IPR_CANCEL_ALL_TIMEOUT); 4776 ipr_send_blocking_cmd(ipr_cmd, ipr_abort_timeout, IPR_CANCEL_ALL_TIMEOUT);
4771 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); 4777 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
4772 4778
4773 /* 4779 /*
4774 * If the abort task timed out and we sent a bus reset, we will get 4780 * If the abort task timed out and we sent a bus reset, we will get
@@ -4812,15 +4818,39 @@ static int ipr_eh_abort(struct scsi_cmnd * scsi_cmd)
4812/** 4818/**
4813 * ipr_handle_other_interrupt - Handle "other" interrupts 4819 * ipr_handle_other_interrupt - Handle "other" interrupts
4814 * @ioa_cfg: ioa config struct 4820 * @ioa_cfg: ioa config struct
4815 * @int_reg: interrupt register
4816 * 4821 *
4817 * Return value: 4822 * Return value:
4818 * IRQ_NONE / IRQ_HANDLED 4823 * IRQ_NONE / IRQ_HANDLED
4819 **/ 4824 **/
4820static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg, 4825static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg)
4821 volatile u32 int_reg)
4822{ 4826{
4823 irqreturn_t rc = IRQ_HANDLED; 4827 irqreturn_t rc = IRQ_HANDLED;
4828 volatile u32 int_reg, int_mask_reg;
4829
4830 int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg32);
4831 int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg;
4832
4833 /* If an interrupt on the adapter did not occur, ignore it.
4834 * Or in the case of SIS 64, check for a stage change interrupt.
4835 */
4836 if ((int_reg & IPR_PCII_OPER_INTERRUPTS) == 0) {
4837 if (ioa_cfg->sis64) {
4838 int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg);
4839 int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg;
4840 if (int_reg & IPR_PCII_IPL_STAGE_CHANGE) {
4841
4842 /* clear stage change */
4843 writel(IPR_PCII_IPL_STAGE_CHANGE, ioa_cfg->regs.clr_interrupt_reg);
4844 int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg;
4845 list_del(&ioa_cfg->reset_cmd->queue);
4846 del_timer(&ioa_cfg->reset_cmd->timer);
4847 ipr_reset_ioa_job(ioa_cfg->reset_cmd);
4848 return IRQ_HANDLED;
4849 }
4850 }
4851
4852 return IRQ_NONE;
4853 }
4824 4854
4825 if (int_reg & IPR_PCII_IOA_TRANS_TO_OPER) { 4855 if (int_reg & IPR_PCII_IOA_TRANS_TO_OPER) {
4826 /* Mask the interrupt */ 4856 /* Mask the interrupt */
@@ -4881,7 +4911,7 @@ static irqreturn_t ipr_isr(int irq, void *devp)
4881{ 4911{
4882 struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)devp; 4912 struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)devp;
4883 unsigned long lock_flags = 0; 4913 unsigned long lock_flags = 0;
4884 volatile u32 int_reg, int_mask_reg; 4914 volatile u32 int_reg;
4885 u32 ioasc; 4915 u32 ioasc;
4886 u16 cmd_index; 4916 u16 cmd_index;
4887 int num_hrrq = 0; 4917 int num_hrrq = 0;
@@ -4896,33 +4926,6 @@ static irqreturn_t ipr_isr(int irq, void *devp)
4896 return IRQ_NONE; 4926 return IRQ_NONE;
4897 } 4927 }
4898 4928
4899 int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg32);
4900 int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg;
4901
4902 /* If an interrupt on the adapter did not occur, ignore it.
4903 * Or in the case of SIS 64, check for a stage change interrupt.
4904 */
4905 if (unlikely((int_reg & IPR_PCII_OPER_INTERRUPTS) == 0)) {
4906 if (ioa_cfg->sis64) {
4907 int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg);
4908 int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg;
4909 if (int_reg & IPR_PCII_IPL_STAGE_CHANGE) {
4910
4911 /* clear stage change */
4912 writel(IPR_PCII_IPL_STAGE_CHANGE, ioa_cfg->regs.clr_interrupt_reg);
4913 int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg;
4914 list_del(&ioa_cfg->reset_cmd->queue);
4915 del_timer(&ioa_cfg->reset_cmd->timer);
4916 ipr_reset_ioa_job(ioa_cfg->reset_cmd);
4917 spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
4918 return IRQ_HANDLED;
4919 }
4920 }
4921
4922 spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
4923 return IRQ_NONE;
4924 }
4925
4926 while (1) { 4929 while (1) {
4927 ipr_cmd = NULL; 4930 ipr_cmd = NULL;
4928 4931
@@ -4940,7 +4943,7 @@ static irqreturn_t ipr_isr(int irq, void *devp)
4940 4943
4941 ipr_cmd = ioa_cfg->ipr_cmnd_list[cmd_index]; 4944 ipr_cmd = ioa_cfg->ipr_cmnd_list[cmd_index];
4942 4945
4943 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); 4946 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
4944 4947
4945 ipr_trc_hook(ipr_cmd, IPR_TRACE_FINISH, ioasc); 4948 ipr_trc_hook(ipr_cmd, IPR_TRACE_FINISH, ioasc);
4946 4949
@@ -4962,7 +4965,7 @@ static irqreturn_t ipr_isr(int irq, void *devp)
4962 /* Clear the PCI interrupt */ 4965 /* Clear the PCI interrupt */
4963 do { 4966 do {
4964 writel(IPR_PCII_HRRQ_UPDATED, ioa_cfg->regs.clr_interrupt_reg32); 4967 writel(IPR_PCII_HRRQ_UPDATED, ioa_cfg->regs.clr_interrupt_reg32);
4965 int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg; 4968 int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32);
4966 } while (int_reg & IPR_PCII_HRRQ_UPDATED && 4969 } while (int_reg & IPR_PCII_HRRQ_UPDATED &&
4967 num_hrrq++ < IPR_MAX_HRRQ_RETRIES); 4970 num_hrrq++ < IPR_MAX_HRRQ_RETRIES);
4968 4971
@@ -4977,7 +4980,7 @@ static irqreturn_t ipr_isr(int irq, void *devp)
4977 } 4980 }
4978 4981
4979 if (unlikely(rc == IRQ_NONE)) 4982 if (unlikely(rc == IRQ_NONE))
4980 rc = ipr_handle_other_interrupt(ioa_cfg, int_reg); 4983 rc = ipr_handle_other_interrupt(ioa_cfg);
4981 4984
4982 spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); 4985 spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
4983 return rc; 4986 return rc;
@@ -5014,6 +5017,10 @@ static int ipr_build_ioadl64(struct ipr_ioa_cfg *ioa_cfg,
5014 5017
5015 ipr_cmd->dma_use_sg = nseg; 5018 ipr_cmd->dma_use_sg = nseg;
5016 5019
5020 ioarcb->data_transfer_length = cpu_to_be32(length);
5021 ioarcb->ioadl_len =
5022 cpu_to_be32(sizeof(struct ipr_ioadl64_desc) * ipr_cmd->dma_use_sg);
5023
5017 if (scsi_cmd->sc_data_direction == DMA_TO_DEVICE) { 5024 if (scsi_cmd->sc_data_direction == DMA_TO_DEVICE) {
5018 ioadl_flags = IPR_IOADL_FLAGS_WRITE; 5025 ioadl_flags = IPR_IOADL_FLAGS_WRITE;
5019 ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_WRITE_NOT_READ; 5026 ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_WRITE_NOT_READ;
@@ -5135,7 +5142,7 @@ static void ipr_erp_done(struct ipr_cmnd *ipr_cmd)
5135 struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd; 5142 struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd;
5136 struct ipr_resource_entry *res = scsi_cmd->device->hostdata; 5143 struct ipr_resource_entry *res = scsi_cmd->device->hostdata;
5137 struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; 5144 struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
5138 u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); 5145 u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
5139 5146
5140 if (IPR_IOASC_SENSE_KEY(ioasc) > 0) { 5147 if (IPR_IOASC_SENSE_KEY(ioasc) > 0) {
5141 scsi_cmd->result |= (DID_ERROR << 16); 5148 scsi_cmd->result |= (DID_ERROR << 16);
@@ -5166,7 +5173,7 @@ static void ipr_erp_done(struct ipr_cmnd *ipr_cmd)
5166static void ipr_reinit_ipr_cmnd_for_erp(struct ipr_cmnd *ipr_cmd) 5173static void ipr_reinit_ipr_cmnd_for_erp(struct ipr_cmnd *ipr_cmd)
5167{ 5174{
5168 struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb; 5175 struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb;
5169 struct ipr_ioasa *ioasa = &ipr_cmd->ioasa; 5176 struct ipr_ioasa *ioasa = &ipr_cmd->s.ioasa;
5170 dma_addr_t dma_addr = ipr_cmd->dma_addr; 5177 dma_addr_t dma_addr = ipr_cmd->dma_addr;
5171 5178
5172 memset(&ioarcb->cmd_pkt, 0, sizeof(struct ipr_cmd_pkt)); 5179 memset(&ioarcb->cmd_pkt, 0, sizeof(struct ipr_cmd_pkt));
@@ -5174,8 +5181,8 @@ static void ipr_reinit_ipr_cmnd_for_erp(struct ipr_cmnd *ipr_cmd)
5174 ioarcb->read_data_transfer_length = 0; 5181 ioarcb->read_data_transfer_length = 0;
5175 ioarcb->ioadl_len = 0; 5182 ioarcb->ioadl_len = 0;
5176 ioarcb->read_ioadl_len = 0; 5183 ioarcb->read_ioadl_len = 0;
5177 ioasa->ioasc = 0; 5184 ioasa->hdr.ioasc = 0;
5178 ioasa->residual_data_len = 0; 5185 ioasa->hdr.residual_data_len = 0;
5179 5186
5180 if (ipr_cmd->ioa_cfg->sis64) 5187 if (ipr_cmd->ioa_cfg->sis64)
5181 ioarcb->u.sis64_addr_data.data_ioadl_addr = 5188 ioarcb->u.sis64_addr_data.data_ioadl_addr =
@@ -5200,7 +5207,7 @@ static void ipr_reinit_ipr_cmnd_for_erp(struct ipr_cmnd *ipr_cmd)
5200static void ipr_erp_request_sense(struct ipr_cmnd *ipr_cmd) 5207static void ipr_erp_request_sense(struct ipr_cmnd *ipr_cmd)
5201{ 5208{
5202 struct ipr_cmd_pkt *cmd_pkt = &ipr_cmd->ioarcb.cmd_pkt; 5209 struct ipr_cmd_pkt *cmd_pkt = &ipr_cmd->ioarcb.cmd_pkt;
5203 u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); 5210 u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
5204 5211
5205 if (IPR_IOASC_SENSE_KEY(ioasc) > 0) { 5212 if (IPR_IOASC_SENSE_KEY(ioasc) > 0) {
5206 ipr_erp_done(ipr_cmd); 5213 ipr_erp_done(ipr_cmd);
@@ -5277,12 +5284,12 @@ static void ipr_dump_ioasa(struct ipr_ioa_cfg *ioa_cfg,
5277 int i; 5284 int i;
5278 u16 data_len; 5285 u16 data_len;
5279 u32 ioasc, fd_ioasc; 5286 u32 ioasc, fd_ioasc;
5280 struct ipr_ioasa *ioasa = &ipr_cmd->ioasa; 5287 struct ipr_ioasa *ioasa = &ipr_cmd->s.ioasa;
5281 __be32 *ioasa_data = (__be32 *)ioasa; 5288 __be32 *ioasa_data = (__be32 *)ioasa;
5282 int error_index; 5289 int error_index;
5283 5290
5284 ioasc = be32_to_cpu(ioasa->ioasc) & IPR_IOASC_IOASC_MASK; 5291 ioasc = be32_to_cpu(ioasa->hdr.ioasc) & IPR_IOASC_IOASC_MASK;
5285 fd_ioasc = be32_to_cpu(ioasa->fd_ioasc) & IPR_IOASC_IOASC_MASK; 5292 fd_ioasc = be32_to_cpu(ioasa->hdr.fd_ioasc) & IPR_IOASC_IOASC_MASK;
5286 5293
5287 if (0 == ioasc) 5294 if (0 == ioasc)
5288 return; 5295 return;
@@ -5297,7 +5304,7 @@ static void ipr_dump_ioasa(struct ipr_ioa_cfg *ioa_cfg,
5297 5304
5298 if (ioa_cfg->log_level < IPR_MAX_LOG_LEVEL) { 5305 if (ioa_cfg->log_level < IPR_MAX_LOG_LEVEL) {
5299 /* Don't log an error if the IOA already logged one */ 5306 /* Don't log an error if the IOA already logged one */
5300 if (ioasa->ilid != 0) 5307 if (ioasa->hdr.ilid != 0)
5301 return; 5308 return;
5302 5309
5303 if (!ipr_is_gscsi(res)) 5310 if (!ipr_is_gscsi(res))
@@ -5309,10 +5316,11 @@ static void ipr_dump_ioasa(struct ipr_ioa_cfg *ioa_cfg,
5309 5316
5310 ipr_res_err(ioa_cfg, res, "%s\n", ipr_error_table[error_index].error); 5317 ipr_res_err(ioa_cfg, res, "%s\n", ipr_error_table[error_index].error);
5311 5318
5312 if (sizeof(struct ipr_ioasa) < be16_to_cpu(ioasa->ret_stat_len)) 5319 data_len = be16_to_cpu(ioasa->hdr.ret_stat_len);
5320 if (ioa_cfg->sis64 && sizeof(struct ipr_ioasa64) < data_len)
5321 data_len = sizeof(struct ipr_ioasa64);
5322 else if (!ioa_cfg->sis64 && sizeof(struct ipr_ioasa) < data_len)
5313 data_len = sizeof(struct ipr_ioasa); 5323 data_len = sizeof(struct ipr_ioasa);
5314 else
5315 data_len = be16_to_cpu(ioasa->ret_stat_len);
5316 5324
5317 ipr_err("IOASA Dump:\n"); 5325 ipr_err("IOASA Dump:\n");
5318 5326
@@ -5338,8 +5346,8 @@ static void ipr_gen_sense(struct ipr_cmnd *ipr_cmd)
5338 u32 failing_lba; 5346 u32 failing_lba;
5339 u8 *sense_buf = ipr_cmd->scsi_cmd->sense_buffer; 5347 u8 *sense_buf = ipr_cmd->scsi_cmd->sense_buffer;
5340 struct ipr_resource_entry *res = ipr_cmd->scsi_cmd->device->hostdata; 5348 struct ipr_resource_entry *res = ipr_cmd->scsi_cmd->device->hostdata;
5341 struct ipr_ioasa *ioasa = &ipr_cmd->ioasa; 5349 struct ipr_ioasa *ioasa = &ipr_cmd->s.ioasa;
5342 u32 ioasc = be32_to_cpu(ioasa->ioasc); 5350 u32 ioasc = be32_to_cpu(ioasa->hdr.ioasc);
5343 5351
5344 memset(sense_buf, 0, SCSI_SENSE_BUFFERSIZE); 5352 memset(sense_buf, 0, SCSI_SENSE_BUFFERSIZE);
5345 5353
@@ -5382,7 +5390,7 @@ static void ipr_gen_sense(struct ipr_cmnd *ipr_cmd)
5382 5390
5383 /* Illegal request */ 5391 /* Illegal request */
5384 if ((IPR_IOASC_SENSE_KEY(ioasc) == 0x05) && 5392 if ((IPR_IOASC_SENSE_KEY(ioasc) == 0x05) &&
5385 (be32_to_cpu(ioasa->ioasc_specific) & IPR_FIELD_POINTER_VALID)) { 5393 (be32_to_cpu(ioasa->hdr.ioasc_specific) & IPR_FIELD_POINTER_VALID)) {
5386 sense_buf[7] = 10; /* additional length */ 5394 sense_buf[7] = 10; /* additional length */
5387 5395
5388 /* IOARCB was in error */ 5396 /* IOARCB was in error */
@@ -5393,10 +5401,10 @@ static void ipr_gen_sense(struct ipr_cmnd *ipr_cmd)
5393 5401
5394 sense_buf[16] = 5402 sense_buf[16] =
5395 ((IPR_FIELD_POINTER_MASK & 5403 ((IPR_FIELD_POINTER_MASK &
5396 be32_to_cpu(ioasa->ioasc_specific)) >> 8) & 0xff; 5404 be32_to_cpu(ioasa->hdr.ioasc_specific)) >> 8) & 0xff;
5397 sense_buf[17] = 5405 sense_buf[17] =
5398 (IPR_FIELD_POINTER_MASK & 5406 (IPR_FIELD_POINTER_MASK &
5399 be32_to_cpu(ioasa->ioasc_specific)) & 0xff; 5407 be32_to_cpu(ioasa->hdr.ioasc_specific)) & 0xff;
5400 } else { 5408 } else {
5401 if (ioasc == IPR_IOASC_MED_DO_NOT_REALLOC) { 5409 if (ioasc == IPR_IOASC_MED_DO_NOT_REALLOC) {
5402 if (ipr_is_vset_device(res)) 5410 if (ipr_is_vset_device(res))
@@ -5428,14 +5436,20 @@ static void ipr_gen_sense(struct ipr_cmnd *ipr_cmd)
5428 **/ 5436 **/
5429static int ipr_get_autosense(struct ipr_cmnd *ipr_cmd) 5437static int ipr_get_autosense(struct ipr_cmnd *ipr_cmd)
5430{ 5438{
5431 struct ipr_ioasa *ioasa = &ipr_cmd->ioasa; 5439 struct ipr_ioasa *ioasa = &ipr_cmd->s.ioasa;
5440 struct ipr_ioasa64 *ioasa64 = &ipr_cmd->s.ioasa64;
5432 5441
5433 if ((be32_to_cpu(ioasa->ioasc_specific) & IPR_AUTOSENSE_VALID) == 0) 5442 if ((be32_to_cpu(ioasa->hdr.ioasc_specific) & IPR_AUTOSENSE_VALID) == 0)
5434 return 0; 5443 return 0;
5435 5444
5436 memcpy(ipr_cmd->scsi_cmd->sense_buffer, ioasa->auto_sense.data, 5445 if (ipr_cmd->ioa_cfg->sis64)
5437 min_t(u16, be16_to_cpu(ioasa->auto_sense.auto_sense_len), 5446 memcpy(ipr_cmd->scsi_cmd->sense_buffer, ioasa64->auto_sense.data,
5438 SCSI_SENSE_BUFFERSIZE)); 5447 min_t(u16, be16_to_cpu(ioasa64->auto_sense.auto_sense_len),
5448 SCSI_SENSE_BUFFERSIZE));
5449 else
5450 memcpy(ipr_cmd->scsi_cmd->sense_buffer, ioasa->auto_sense.data,
5451 min_t(u16, be16_to_cpu(ioasa->auto_sense.auto_sense_len),
5452 SCSI_SENSE_BUFFERSIZE));
5439 return 1; 5453 return 1;
5440} 5454}
5441 5455
@@ -5455,7 +5469,7 @@ static void ipr_erp_start(struct ipr_ioa_cfg *ioa_cfg,
5455{ 5469{
5456 struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd; 5470 struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd;
5457 struct ipr_resource_entry *res = scsi_cmd->device->hostdata; 5471 struct ipr_resource_entry *res = scsi_cmd->device->hostdata;
5458 u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); 5472 u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
5459 u32 masked_ioasc = ioasc & IPR_IOASC_IOASC_MASK; 5473 u32 masked_ioasc = ioasc & IPR_IOASC_IOASC_MASK;
5460 5474
5461 if (!res) { 5475 if (!res) {
@@ -5547,9 +5561,9 @@ static void ipr_scsi_done(struct ipr_cmnd *ipr_cmd)
5547{ 5561{
5548 struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; 5562 struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
5549 struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd; 5563 struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd;
5550 u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); 5564 u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
5551 5565
5552 scsi_set_resid(scsi_cmd, be32_to_cpu(ipr_cmd->ioasa.residual_data_len)); 5566 scsi_set_resid(scsi_cmd, be32_to_cpu(ipr_cmd->s.ioasa.hdr.residual_data_len));
5553 5567
5554 if (likely(IPR_IOASC_SENSE_KEY(ioasc) == 0)) { 5568 if (likely(IPR_IOASC_SENSE_KEY(ioasc) == 0)) {
5555 scsi_dma_unmap(ipr_cmd->scsi_cmd); 5569 scsi_dma_unmap(ipr_cmd->scsi_cmd);
@@ -5839,19 +5853,23 @@ static void ipr_sata_done(struct ipr_cmnd *ipr_cmd)
5839 struct ata_queued_cmd *qc = ipr_cmd->qc; 5853 struct ata_queued_cmd *qc = ipr_cmd->qc;
5840 struct ipr_sata_port *sata_port = qc->ap->private_data; 5854 struct ipr_sata_port *sata_port = qc->ap->private_data;
5841 struct ipr_resource_entry *res = sata_port->res; 5855 struct ipr_resource_entry *res = sata_port->res;
5842 u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); 5856 u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
5843 5857
5844 memcpy(&sata_port->ioasa, &ipr_cmd->ioasa.u.gata, 5858 if (ipr_cmd->ioa_cfg->sis64)
5845 sizeof(struct ipr_ioasa_gata)); 5859 memcpy(&sata_port->ioasa, &ipr_cmd->s.ioasa64.u.gata,
5860 sizeof(struct ipr_ioasa_gata));
5861 else
5862 memcpy(&sata_port->ioasa, &ipr_cmd->s.ioasa.u.gata,
5863 sizeof(struct ipr_ioasa_gata));
5846 ipr_dump_ioasa(ioa_cfg, ipr_cmd, res); 5864 ipr_dump_ioasa(ioa_cfg, ipr_cmd, res);
5847 5865
5848 if (be32_to_cpu(ipr_cmd->ioasa.ioasc_specific) & IPR_ATA_DEVICE_WAS_RESET) 5866 if (be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc_specific) & IPR_ATA_DEVICE_WAS_RESET)
5849 scsi_report_device_reset(ioa_cfg->host, res->bus, res->target); 5867 scsi_report_device_reset(ioa_cfg->host, res->bus, res->target);
5850 5868
5851 if (IPR_IOASC_SENSE_KEY(ioasc) > RECOVERED_ERROR) 5869 if (IPR_IOASC_SENSE_KEY(ioasc) > RECOVERED_ERROR)
5852 qc->err_mask |= __ac_err_mask(ipr_cmd->ioasa.u.gata.status); 5870 qc->err_mask |= __ac_err_mask(sata_port->ioasa.status);
5853 else 5871 else
5854 qc->err_mask |= ac_err_mask(ipr_cmd->ioasa.u.gata.status); 5872 qc->err_mask |= ac_err_mask(sata_port->ioasa.status);
5855 list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q); 5873 list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
5856 ata_qc_complete(qc); 5874 ata_qc_complete(qc);
5857} 5875}
@@ -6520,7 +6538,7 @@ static void ipr_build_mode_sense(struct ipr_cmnd *ipr_cmd,
6520static int ipr_reset_cmd_failed(struct ipr_cmnd *ipr_cmd) 6538static int ipr_reset_cmd_failed(struct ipr_cmnd *ipr_cmd)
6521{ 6539{
6522 struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; 6540 struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
6523 u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); 6541 u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
6524 6542
6525 dev_err(&ioa_cfg->pdev->dev, 6543 dev_err(&ioa_cfg->pdev->dev,
6526 "0x%02X failed with IOASC: 0x%08X\n", 6544 "0x%02X failed with IOASC: 0x%08X\n",
@@ -6544,7 +6562,7 @@ static int ipr_reset_cmd_failed(struct ipr_cmnd *ipr_cmd)
6544static int ipr_reset_mode_sense_failed(struct ipr_cmnd *ipr_cmd) 6562static int ipr_reset_mode_sense_failed(struct ipr_cmnd *ipr_cmd)
6545{ 6563{
6546 struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; 6564 struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
6547 u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); 6565 u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
6548 6566
6549 if (ioasc == IPR_IOASC_IR_INVALID_REQ_TYPE_OR_PKT) { 6567 if (ioasc == IPR_IOASC_IR_INVALID_REQ_TYPE_OR_PKT) {
6550 ipr_cmd->job_step = ipr_set_supported_devs; 6568 ipr_cmd->job_step = ipr_set_supported_devs;
@@ -6634,7 +6652,7 @@ static int ipr_ioafp_mode_select_page24(struct ipr_cmnd *ipr_cmd)
6634 **/ 6652 **/
6635static int ipr_reset_mode_sense_page24_failed(struct ipr_cmnd *ipr_cmd) 6653static int ipr_reset_mode_sense_page24_failed(struct ipr_cmnd *ipr_cmd)
6636{ 6654{
6637 u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); 6655 u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
6638 6656
6639 if (ioasc == IPR_IOASC_IR_INVALID_REQ_TYPE_OR_PKT) { 6657 if (ioasc == IPR_IOASC_IR_INVALID_REQ_TYPE_OR_PKT) {
6640 ipr_cmd->job_step = ipr_ioafp_mode_sense_page28; 6658 ipr_cmd->job_step = ipr_ioafp_mode_sense_page28;
@@ -6706,7 +6724,7 @@ static int ipr_init_res_table(struct ipr_cmnd *ipr_cmd)
6706 list_move_tail(&res->queue, &old_res); 6724 list_move_tail(&res->queue, &old_res);
6707 6725
6708 if (ioa_cfg->sis64) 6726 if (ioa_cfg->sis64)
6709 entries = ioa_cfg->u.cfg_table64->hdr64.num_entries; 6727 entries = be16_to_cpu(ioa_cfg->u.cfg_table64->hdr64.num_entries);
6710 else 6728 else
6711 entries = ioa_cfg->u.cfg_table->hdr.num_entries; 6729 entries = ioa_cfg->u.cfg_table->hdr.num_entries;
6712 6730
@@ -6792,6 +6810,7 @@ static int ipr_ioafp_query_ioa_cfg(struct ipr_cmnd *ipr_cmd)
6792 ioarcb->res_handle = cpu_to_be32(IPR_IOA_RES_HANDLE); 6810 ioarcb->res_handle = cpu_to_be32(IPR_IOA_RES_HANDLE);
6793 6811
6794 ioarcb->cmd_pkt.cdb[0] = IPR_QUERY_IOA_CONFIG; 6812 ioarcb->cmd_pkt.cdb[0] = IPR_QUERY_IOA_CONFIG;
6813 ioarcb->cmd_pkt.cdb[6] = (ioa_cfg->cfg_table_size >> 16) & 0xff;
6795 ioarcb->cmd_pkt.cdb[7] = (ioa_cfg->cfg_table_size >> 8) & 0xff; 6814 ioarcb->cmd_pkt.cdb[7] = (ioa_cfg->cfg_table_size >> 8) & 0xff;
6796 ioarcb->cmd_pkt.cdb[8] = ioa_cfg->cfg_table_size & 0xff; 6815 ioarcb->cmd_pkt.cdb[8] = ioa_cfg->cfg_table_size & 0xff;
6797 6816
@@ -7122,7 +7141,9 @@ static int ipr_reset_next_stage(struct ipr_cmnd *ipr_cmd)
7122 ipr_dbg("IPL stage = 0x%lx, IPL stage time = %ld\n", stage, stage_time); 7141 ipr_dbg("IPL stage = 0x%lx, IPL stage time = %ld\n", stage, stage_time);
7123 7142
7124 /* sanity check the stage_time value */ 7143 /* sanity check the stage_time value */
7125 if (stage_time < IPR_IPL_INIT_MIN_STAGE_TIME) 7144 if (stage_time == 0)
7145 stage_time = IPR_IPL_INIT_DEFAULT_STAGE_TIME;
7146 else if (stage_time < IPR_IPL_INIT_MIN_STAGE_TIME)
7126 stage_time = IPR_IPL_INIT_MIN_STAGE_TIME; 7147 stage_time = IPR_IPL_INIT_MIN_STAGE_TIME;
7127 else if (stage_time > IPR_LONG_OPERATIONAL_TIMEOUT) 7148 else if (stage_time > IPR_LONG_OPERATIONAL_TIMEOUT)
7128 stage_time = IPR_LONG_OPERATIONAL_TIMEOUT; 7149 stage_time = IPR_LONG_OPERATIONAL_TIMEOUT;
@@ -7165,13 +7186,14 @@ static int ipr_reset_enable_ioa(struct ipr_cmnd *ipr_cmd)
7165{ 7186{
7166 struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; 7187 struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
7167 volatile u32 int_reg; 7188 volatile u32 int_reg;
7189 volatile u64 maskval;
7168 7190
7169 ENTER; 7191 ENTER;
7170 ipr_cmd->job_step = ipr_ioafp_identify_hrrq; 7192 ipr_cmd->job_step = ipr_ioafp_identify_hrrq;
7171 ipr_init_ioa_mem(ioa_cfg); 7193 ipr_init_ioa_mem(ioa_cfg);
7172 7194
7173 ioa_cfg->allow_interrupts = 1; 7195 ioa_cfg->allow_interrupts = 1;
7174 int_reg = readl(ioa_cfg->regs.sense_interrupt_reg); 7196 int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32);
7175 7197
7176 if (int_reg & IPR_PCII_IOA_TRANS_TO_OPER) { 7198 if (int_reg & IPR_PCII_IOA_TRANS_TO_OPER) {
7177 writel((IPR_PCII_ERROR_INTERRUPTS | IPR_PCII_HRRQ_UPDATED), 7199 writel((IPR_PCII_ERROR_INTERRUPTS | IPR_PCII_HRRQ_UPDATED),
@@ -7183,9 +7205,12 @@ static int ipr_reset_enable_ioa(struct ipr_cmnd *ipr_cmd)
7183 /* Enable destructive diagnostics on IOA */ 7205 /* Enable destructive diagnostics on IOA */
7184 writel(ioa_cfg->doorbell, ioa_cfg->regs.set_uproc_interrupt_reg32); 7206 writel(ioa_cfg->doorbell, ioa_cfg->regs.set_uproc_interrupt_reg32);
7185 7207
7186 writel(IPR_PCII_OPER_INTERRUPTS, ioa_cfg->regs.clr_interrupt_mask_reg32); 7208 if (ioa_cfg->sis64) {
7187 if (ioa_cfg->sis64) 7209 maskval = IPR_PCII_IPL_STAGE_CHANGE;
7188 writel(IPR_PCII_IPL_STAGE_CHANGE, ioa_cfg->regs.clr_interrupt_mask_reg); 7210 maskval = (maskval << 32) | IPR_PCII_OPER_INTERRUPTS;
7211 writeq(maskval, ioa_cfg->regs.clr_interrupt_mask_reg);
7212 } else
7213 writel(IPR_PCII_OPER_INTERRUPTS, ioa_cfg->regs.clr_interrupt_mask_reg32);
7189 7214
7190 int_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg); 7215 int_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg);
7191 7216
@@ -7332,12 +7357,12 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd)
7332 rc = pci_restore_state(ioa_cfg->pdev); 7357 rc = pci_restore_state(ioa_cfg->pdev);
7333 7358
7334 if (rc != PCIBIOS_SUCCESSFUL) { 7359 if (rc != PCIBIOS_SUCCESSFUL) {
7335 ipr_cmd->ioasa.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR); 7360 ipr_cmd->s.ioasa.hdr.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR);
7336 return IPR_RC_JOB_CONTINUE; 7361 return IPR_RC_JOB_CONTINUE;
7337 } 7362 }
7338 7363
7339 if (ipr_set_pcix_cmd_reg(ioa_cfg)) { 7364 if (ipr_set_pcix_cmd_reg(ioa_cfg)) {
7340 ipr_cmd->ioasa.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR); 7365 ipr_cmd->s.ioasa.hdr.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR);
7341 return IPR_RC_JOB_CONTINUE; 7366 return IPR_RC_JOB_CONTINUE;
7342 } 7367 }
7343 7368
@@ -7364,7 +7389,7 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd)
7364 } 7389 }
7365 } 7390 }
7366 7391
7367 ENTER; 7392 LEAVE;
7368 return IPR_RC_JOB_CONTINUE; 7393 return IPR_RC_JOB_CONTINUE;
7369} 7394}
7370 7395
@@ -7406,7 +7431,7 @@ static int ipr_reset_start_bist(struct ipr_cmnd *ipr_cmd)
7406 7431
7407 if (rc != PCIBIOS_SUCCESSFUL) { 7432 if (rc != PCIBIOS_SUCCESSFUL) {
7408 pci_unblock_user_cfg_access(ipr_cmd->ioa_cfg->pdev); 7433 pci_unblock_user_cfg_access(ipr_cmd->ioa_cfg->pdev);
7409 ipr_cmd->ioasa.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR); 7434 ipr_cmd->s.ioasa.hdr.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR);
7410 rc = IPR_RC_JOB_CONTINUE; 7435 rc = IPR_RC_JOB_CONTINUE;
7411 } else { 7436 } else {
7412 ipr_cmd->job_step = ipr_reset_bist_done; 7437 ipr_cmd->job_step = ipr_reset_bist_done;
@@ -7665,7 +7690,7 @@ static void ipr_reset_ioa_job(struct ipr_cmnd *ipr_cmd)
7665 struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; 7690 struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
7666 7691
7667 do { 7692 do {
7668 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); 7693 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
7669 7694
7670 if (ioa_cfg->reset_cmd != ipr_cmd) { 7695 if (ioa_cfg->reset_cmd != ipr_cmd) {
7671 /* 7696 /*
@@ -8048,13 +8073,13 @@ static int __devinit ipr_alloc_cmd_blks(struct ipr_ioa_cfg *ioa_cfg)
8048 ioarcb->u.sis64_addr_data.data_ioadl_addr = 8073 ioarcb->u.sis64_addr_data.data_ioadl_addr =
8049 cpu_to_be64(dma_addr + offsetof(struct ipr_cmnd, i.ioadl64)); 8074 cpu_to_be64(dma_addr + offsetof(struct ipr_cmnd, i.ioadl64));
8050 ioarcb->u.sis64_addr_data.ioasa_host_pci_addr = 8075 ioarcb->u.sis64_addr_data.ioasa_host_pci_addr =
8051 cpu_to_be64(dma_addr + offsetof(struct ipr_cmnd, ioasa)); 8076 cpu_to_be64(dma_addr + offsetof(struct ipr_cmnd, s.ioasa64));
8052 } else { 8077 } else {
8053 ioarcb->write_ioadl_addr = 8078 ioarcb->write_ioadl_addr =
8054 cpu_to_be32(dma_addr + offsetof(struct ipr_cmnd, i.ioadl)); 8079 cpu_to_be32(dma_addr + offsetof(struct ipr_cmnd, i.ioadl));
8055 ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr; 8080 ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr;
8056 ioarcb->ioasa_host_pci_addr = 8081 ioarcb->ioasa_host_pci_addr =
8057 cpu_to_be32(dma_addr + offsetof(struct ipr_cmnd, ioasa)); 8082 cpu_to_be32(dma_addr + offsetof(struct ipr_cmnd, s.ioasa));
8058 } 8083 }
8059 ioarcb->ioasa_len = cpu_to_be16(sizeof(struct ipr_ioasa)); 8084 ioarcb->ioasa_len = cpu_to_be16(sizeof(struct ipr_ioasa));
8060 ipr_cmd->cmd_index = i; 8085 ipr_cmd->cmd_index = i;
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index 4c267b5e0b96..9ecd2259eb39 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -244,6 +244,7 @@
244#define IPR_RUNTIME_RESET 0x40000000 244#define IPR_RUNTIME_RESET 0x40000000
245 245
246#define IPR_IPL_INIT_MIN_STAGE_TIME 5 246#define IPR_IPL_INIT_MIN_STAGE_TIME 5
247#define IPR_IPL_INIT_DEFAULT_STAGE_TIME 15
247#define IPR_IPL_INIT_STAGE_UNKNOWN 0x0 248#define IPR_IPL_INIT_STAGE_UNKNOWN 0x0
248#define IPR_IPL_INIT_STAGE_TRANSOP 0xB0000000 249#define IPR_IPL_INIT_STAGE_TRANSOP 0xB0000000
249#define IPR_IPL_INIT_STAGE_MASK 0xff000000 250#define IPR_IPL_INIT_STAGE_MASK 0xff000000
@@ -613,7 +614,7 @@ struct ipr_auto_sense {
613 __be32 data[SCSI_SENSE_BUFFERSIZE/sizeof(__be32)]; 614 __be32 data[SCSI_SENSE_BUFFERSIZE/sizeof(__be32)];
614}; 615};
615 616
616struct ipr_ioasa { 617struct ipr_ioasa_hdr {
617 __be32 ioasc; 618 __be32 ioasc;
618#define IPR_IOASC_SENSE_KEY(ioasc) ((ioasc) >> 24) 619#define IPR_IOASC_SENSE_KEY(ioasc) ((ioasc) >> 24)
619#define IPR_IOASC_SENSE_CODE(ioasc) (((ioasc) & 0x00ff0000) >> 16) 620#define IPR_IOASC_SENSE_CODE(ioasc) (((ioasc) & 0x00ff0000) >> 16)
@@ -645,6 +646,25 @@ struct ipr_ioasa {
645#define IPR_FIELD_POINTER_VALID (0x80000000 >> 8) 646#define IPR_FIELD_POINTER_VALID (0x80000000 >> 8)
646#define IPR_FIELD_POINTER_MASK 0x0000ffff 647#define IPR_FIELD_POINTER_MASK 0x0000ffff
647 648
649}__attribute__((packed, aligned (4)));
650
651struct ipr_ioasa {
652 struct ipr_ioasa_hdr hdr;
653
654 union {
655 struct ipr_ioasa_vset vset;
656 struct ipr_ioasa_af_dasd dasd;
657 struct ipr_ioasa_gpdd gpdd;
658 struct ipr_ioasa_gata gata;
659 } u;
660
661 struct ipr_auto_sense auto_sense;
662}__attribute__((packed, aligned (4)));
663
664struct ipr_ioasa64 {
665 struct ipr_ioasa_hdr hdr;
666 u8 fd_res_path[8];
667
648 union { 668 union {
649 struct ipr_ioasa_vset vset; 669 struct ipr_ioasa_vset vset;
650 struct ipr_ioasa_af_dasd dasd; 670 struct ipr_ioasa_af_dasd dasd;
@@ -804,7 +824,7 @@ struct ipr_hostrcb_array_data_entry_enhanced {
804}__attribute__((packed, aligned (4))); 824}__attribute__((packed, aligned (4)));
805 825
806struct ipr_hostrcb_type_ff_error { 826struct ipr_hostrcb_type_ff_error {
807 __be32 ioa_data[502]; 827 __be32 ioa_data[758];
808}__attribute__((packed, aligned (4))); 828}__attribute__((packed, aligned (4)));
809 829
810struct ipr_hostrcb_type_01_error { 830struct ipr_hostrcb_type_01_error {
@@ -1181,7 +1201,7 @@ struct ipr_resource_entry {
1181 u8 flags; 1201 u8 flags;
1182 __be16 res_flags; 1202 __be16 res_flags;
1183 1203
1184 __be32 type; 1204 u8 type;
1185 1205
1186 u8 qmodel; 1206 u8 qmodel;
1187 struct ipr_std_inq_data std_inq_data; 1207 struct ipr_std_inq_data std_inq_data;
@@ -1464,7 +1484,10 @@ struct ipr_cmnd {
1464 struct ipr_ioadl64_desc ioadl64[IPR_NUM_IOADL_ENTRIES]; 1484 struct ipr_ioadl64_desc ioadl64[IPR_NUM_IOADL_ENTRIES];
1465 struct ipr_ata64_ioadl ata_ioadl; 1485 struct ipr_ata64_ioadl ata_ioadl;
1466 } i; 1486 } i;
1467 struct ipr_ioasa ioasa; 1487 union {
1488 struct ipr_ioasa ioasa;
1489 struct ipr_ioasa64 ioasa64;
1490 } s;
1468 struct list_head queue; 1491 struct list_head queue;
1469 struct scsi_cmnd *scsi_cmd; 1492 struct scsi_cmnd *scsi_cmd;
1470 struct ata_queued_cmd *qc; 1493 struct ata_queued_cmd *qc;
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index bf55d3057413..fec47de72535 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -601,10 +601,8 @@ static void iscsi_sw_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
601 set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx); 601 set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
602 write_unlock_bh(&tcp_sw_conn->sock->sk->sk_callback_lock); 602 write_unlock_bh(&tcp_sw_conn->sock->sk->sk_callback_lock);
603 603
604 if (sk_sleep(sock->sk)) { 604 sock->sk->sk_err = EIO;
605 sock->sk->sk_err = EIO; 605 wake_up_interruptible(sk_sleep(sock->sk));
606 wake_up_interruptible(sk_sleep(sock->sk));
607 }
608 606
609 iscsi_conn_stop(cls_conn, flag); 607 iscsi_conn_stop(cls_conn, flag);
610 iscsi_sw_tcp_release_conn(conn); 608 iscsi_sw_tcp_release_conn(conn);
diff --git a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c
index 18735b39b3d3..3ddb4dc62d5d 100644
--- a/drivers/scsi/mac53c94.c
+++ b/drivers/scsi/mac53c94.c
@@ -542,8 +542,11 @@ MODULE_DEVICE_TABLE (of, mac53c94_match);
542 542
543static struct macio_driver mac53c94_driver = 543static struct macio_driver mac53c94_driver =
544{ 544{
545 .name = "mac53c94", 545 .driver = {
546 .match_table = mac53c94_match, 546 .name = "mac53c94",
547 .owner = THIS_MODULE,
548 .of_match_table = mac53c94_match,
549 },
547 .probe = mac53c94_probe, 550 .probe = mac53c94_probe,
548 .remove = mac53c94_remove, 551 .remove = mac53c94_remove,
549}; 552};
diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c
index a1c97e88068a..1f784fde2510 100644
--- a/drivers/scsi/mesh.c
+++ b/drivers/scsi/mesh.c
@@ -2036,8 +2036,11 @@ MODULE_DEVICE_TABLE (of, mesh_match);
2036 2036
2037static struct macio_driver mesh_driver = 2037static struct macio_driver mesh_driver =
2038{ 2038{
2039 .name = "mesh", 2039 .driver = {
2040 .match_table = mesh_match, 2040 .name = "mesh",
2041 .owner = THIS_MODULE,
2042 .of_match_table = mesh_match,
2043 },
2041 .probe = mesh_probe, 2044 .probe = mesh_probe,
2042 .remove = mesh_remove, 2045 .remove = mesh_remove,
2043 .shutdown = mesh_shutdown, 2046 .shutdown = mesh_shutdown,
diff --git a/drivers/scsi/mvme147.c b/drivers/scsi/mvme147.c
index 716d1785cda7..c29d0dbb9660 100644
--- a/drivers/scsi/mvme147.c
+++ b/drivers/scsi/mvme147.c
@@ -16,12 +16,12 @@
16#include <linux/stat.h> 16#include <linux/stat.h>
17 17
18 18
19static struct Scsi_Host *mvme147_host = NULL; 19static irqreturn_t mvme147_intr(int irq, void *data)
20
21static irqreturn_t mvme147_intr(int irq, void *dummy)
22{ 20{
21 struct Scsi_Host *instance = data;
22
23 if (irq == MVME147_IRQ_SCSI_PORT) 23 if (irq == MVME147_IRQ_SCSI_PORT)
24 wd33c93_intr(mvme147_host); 24 wd33c93_intr(instance);
25 else 25 else
26 m147_pcc->dma_intr = 0x89; /* Ack and enable ints */ 26 m147_pcc->dma_intr = 0x89; /* Ack and enable ints */
27 return IRQ_HANDLED; 27 return IRQ_HANDLED;
@@ -29,7 +29,8 @@ static irqreturn_t mvme147_intr(int irq, void *dummy)
29 29
30static int dma_setup(struct scsi_cmnd *cmd, int dir_in) 30static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
31{ 31{
32 struct WD33C93_hostdata *hdata = shost_priv(mvme147_host); 32 struct Scsi_Host *instance = cmd->device->host;
33 struct WD33C93_hostdata *hdata = shost_priv(instance);
33 unsigned char flags = 0x01; 34 unsigned char flags = 0x01;
34 unsigned long addr = virt_to_bus(cmd->SCp.ptr); 35 unsigned long addr = virt_to_bus(cmd->SCp.ptr);
35 36
@@ -66,6 +67,7 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt,
66int mvme147_detect(struct scsi_host_template *tpnt) 67int mvme147_detect(struct scsi_host_template *tpnt)
67{ 68{
68 static unsigned char called = 0; 69 static unsigned char called = 0;
70 struct Scsi_Host *instance;
69 wd33c93_regs regs; 71 wd33c93_regs regs;
70 struct WD33C93_hostdata *hdata; 72 struct WD33C93_hostdata *hdata;
71 73
@@ -76,25 +78,25 @@ int mvme147_detect(struct scsi_host_template *tpnt)
76 tpnt->proc_name = "MVME147"; 78 tpnt->proc_name = "MVME147";
77 tpnt->proc_info = &wd33c93_proc_info; 79 tpnt->proc_info = &wd33c93_proc_info;
78 80
79 mvme147_host = scsi_register(tpnt, sizeof(struct WD33C93_hostdata)); 81 instance = scsi_register(tpnt, sizeof(struct WD33C93_hostdata));
80 if (!mvme147_host) 82 if (!instance)
81 goto err_out; 83 goto err_out;
82 84
83 mvme147_host->base = 0xfffe4000; 85 instance->base = 0xfffe4000;
84 mvme147_host->irq = MVME147_IRQ_SCSI_PORT; 86 instance->irq = MVME147_IRQ_SCSI_PORT;
85 regs.SASR = (volatile unsigned char *)0xfffe4000; 87 regs.SASR = (volatile unsigned char *)0xfffe4000;
86 regs.SCMD = (volatile unsigned char *)0xfffe4001; 88 regs.SCMD = (volatile unsigned char *)0xfffe4001;
87 hdata = shost_priv(mvme147_host); 89 hdata = shost_priv(instance);
88 hdata->no_sync = 0xff; 90 hdata->no_sync = 0xff;
89 hdata->fast = 0; 91 hdata->fast = 0;
90 hdata->dma_mode = CTRL_DMA; 92 hdata->dma_mode = CTRL_DMA;
91 wd33c93_init(mvme147_host, regs, dma_setup, dma_stop, WD33C93_FS_8_10); 93 wd33c93_init(instance, regs, dma_setup, dma_stop, WD33C93_FS_8_10);
92 94
93 if (request_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr, 0, 95 if (request_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr, 0,
94 "MVME147 SCSI PORT", mvme147_intr)) 96 "MVME147 SCSI PORT", instance))
95 goto err_unregister; 97 goto err_unregister;
96 if (request_irq(MVME147_IRQ_SCSI_DMA, mvme147_intr, 0, 98 if (request_irq(MVME147_IRQ_SCSI_DMA, mvme147_intr, 0,
97 "MVME147 SCSI DMA", mvme147_intr)) 99 "MVME147 SCSI DMA", instance))
98 goto err_free_irq; 100 goto err_free_irq;
99#if 0 /* Disabled; causes problems booting */ 101#if 0 /* Disabled; causes problems booting */
100 m147_pcc->scsi_interrupt = 0x10; /* Assert SCSI bus reset */ 102 m147_pcc->scsi_interrupt = 0x10; /* Assert SCSI bus reset */
@@ -113,7 +115,7 @@ int mvme147_detect(struct scsi_host_template *tpnt)
113err_free_irq: 115err_free_irq:
114 free_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr); 116 free_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr);
115err_unregister: 117err_unregister:
116 scsi_unregister(mvme147_host); 118 scsi_unregister(instance);
117err_out: 119err_out:
118 return 0; 120 return 0;
119} 121}
@@ -132,9 +134,6 @@ static int mvme147_bus_reset(struct scsi_cmnd *cmd)
132 return SUCCESS; 134 return SUCCESS;
133} 135}
134 136
135#define HOSTS_C
136
137#include "mvme147.h"
138 137
139static struct scsi_host_template driver_template = { 138static struct scsi_host_template driver_template = {
140 .proc_name = "MVME147", 139 .proc_name = "MVME147",
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index 8dbf1c3afb7b..d64b7178fa08 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -3587,7 +3587,7 @@ if (SRpnt) printk(KERN_ERR "%s:A: Not supposed to have SRpnt at line %d\n", name
3587 if (i == (-ENOSPC)) { 3587 if (i == (-ENOSPC)) {
3588 transfer = STp->buffer->writing; /* FIXME -- check this logic */ 3588 transfer = STp->buffer->writing; /* FIXME -- check this logic */
3589 if (transfer <= do_count) { 3589 if (transfer <= do_count) {
3590 filp->f_pos += do_count - transfer; 3590 *ppos += do_count - transfer;
3591 count -= do_count - transfer; 3591 count -= do_count - transfer;
3592 if (STps->drv_block >= 0) { 3592 if (STps->drv_block >= 0) {
3593 STps->drv_block += (do_count - transfer) / STp->block_size; 3593 STps->drv_block += (do_count - transfer) / STp->block_size;
@@ -3625,7 +3625,7 @@ if (SRpnt) printk(KERN_ERR "%s:A: Not supposed to have SRpnt at line %d\n", name
3625 goto out; 3625 goto out;
3626 } 3626 }
3627 3627
3628 filp->f_pos += do_count; 3628 *ppos += do_count;
3629 b_point += do_count; 3629 b_point += do_count;
3630 count -= do_count; 3630 count -= do_count;
3631 if (STps->drv_block >= 0) { 3631 if (STps->drv_block >= 0) {
@@ -3647,7 +3647,7 @@ if (SRpnt) printk(KERN_ERR "%s:A: Not supposed to have SRpnt at line %d\n", name
3647 if (STps->drv_block >= 0) { 3647 if (STps->drv_block >= 0) {
3648 STps->drv_block += blks; 3648 STps->drv_block += blks;
3649 } 3649 }
3650 filp->f_pos += count; 3650 *ppos += count;
3651 count = 0; 3651 count = 0;
3652 } 3652 }
3653 3653
@@ -3823,7 +3823,7 @@ static ssize_t osst_read(struct file * filp, char __user * buf, size_t count, lo
3823 } 3823 }
3824 STp->logical_blk_num += transfer / STp->block_size; 3824 STp->logical_blk_num += transfer / STp->block_size;
3825 STps->drv_block += transfer / STp->block_size; 3825 STps->drv_block += transfer / STp->block_size;
3826 filp->f_pos += transfer; 3826 *ppos += transfer;
3827 buf += transfer; 3827 buf += transfer;
3828 total += transfer; 3828 total += transfer;
3829 } 3829 }
@@ -5626,6 +5626,7 @@ static const struct file_operations osst_fops = {
5626 .open = os_scsi_tape_open, 5626 .open = os_scsi_tape_open,
5627 .flush = os_scsi_tape_flush, 5627 .flush = os_scsi_tape_flush,
5628 .release = os_scsi_tape_close, 5628 .release = os_scsi_tape_close,
5629 .llseek = noop_llseek,
5629}; 5630};
5630 5631
5631static int osst_supports(struct scsi_device * SDp) 5632static int osst_supports(struct scsi_device * SDp)
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 9798c2c06b93..1c027a97d8b9 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -492,19 +492,20 @@ void scsi_target_reap(struct scsi_target *starget)
492 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 492 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
493 unsigned long flags; 493 unsigned long flags;
494 enum scsi_target_state state; 494 enum scsi_target_state state;
495 int empty; 495 int empty = 0;
496 496
497 spin_lock_irqsave(shost->host_lock, flags); 497 spin_lock_irqsave(shost->host_lock, flags);
498 state = starget->state; 498 state = starget->state;
499 empty = --starget->reap_ref == 0 && 499 if (--starget->reap_ref == 0 && list_empty(&starget->devices)) {
500 list_empty(&starget->devices) ? 1 : 0; 500 empty = 1;
501 starget->state = STARGET_DEL;
502 }
501 spin_unlock_irqrestore(shost->host_lock, flags); 503 spin_unlock_irqrestore(shost->host_lock, flags);
502 504
503 if (!empty) 505 if (!empty)
504 return; 506 return;
505 507
506 BUG_ON(state == STARGET_DEL); 508 BUG_ON(state == STARGET_DEL);
507 starget->state = STARGET_DEL;
508 if (state == STARGET_CREATED) 509 if (state == STARGET_CREATED)
509 scsi_target_destroy(starget); 510 scsi_target_destroy(starget);
510 else 511 else
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 829cc37abc41..8802e48bc063 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -97,6 +97,7 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC);
97#endif 97#endif
98 98
99static int sd_revalidate_disk(struct gendisk *); 99static int sd_revalidate_disk(struct gendisk *);
100static void sd_unlock_native_capacity(struct gendisk *disk);
100static int sd_probe(struct device *); 101static int sd_probe(struct device *);
101static int sd_remove(struct device *); 102static int sd_remove(struct device *);
102static void sd_shutdown(struct device *); 103static void sd_shutdown(struct device *);
@@ -1101,6 +1102,7 @@ static const struct block_device_operations sd_fops = {
1101#endif 1102#endif
1102 .media_changed = sd_media_changed, 1103 .media_changed = sd_media_changed,
1103 .revalidate_disk = sd_revalidate_disk, 1104 .revalidate_disk = sd_revalidate_disk,
1105 .unlock_native_capacity = sd_unlock_native_capacity,
1104}; 1106};
1105 1107
1106static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd) 1108static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd)
@@ -2121,6 +2123,26 @@ static int sd_revalidate_disk(struct gendisk *disk)
2121} 2123}
2122 2124
2123/** 2125/**
2126 * sd_unlock_native_capacity - unlock native capacity
2127 * @disk: struct gendisk to set capacity for
2128 *
2129 * Block layer calls this function if it detects that partitions
2130 * on @disk reach beyond the end of the device. If the SCSI host
2131 * implements ->unlock_native_capacity() method, it's invoked to
2132 * give it a chance to adjust the device capacity.
2133 *
2134 * CONTEXT:
2135 * Defined by block layer. Might sleep.
2136 */
2137static void sd_unlock_native_capacity(struct gendisk *disk)
2138{
2139 struct scsi_device *sdev = scsi_disk(disk)->device;
2140
2141 if (sdev->host->hostt->unlock_native_capacity)
2142 sdev->host->hostt->unlock_native_capacity(sdev);
2143}
2144
2145/**
2124 * sd_format_disk_name - format disk name 2146 * sd_format_disk_name - format disk name
2125 * @prefix: name prefix - ie. "sd" for SCSI disks 2147 * @prefix: name prefix - ie. "sd" for SCSI disks
2126 * @index: index of the disk to format name for 2148 * @index: index of the disk to format name for
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 3ea1a713ef25..24211d0efa6d 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -3962,6 +3962,7 @@ static const struct file_operations st_fops =
3962 .open = st_open, 3962 .open = st_open,
3963 .flush = st_flush, 3963 .flush = st_flush,
3964 .release = st_release, 3964 .release = st_release,
3965 .llseek = noop_llseek,
3965}; 3966};
3966 3967
3967static int st_probe(struct device *dev) 3968static int st_probe(struct device *dev)
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index 01c012da4e26..746a44621d91 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -982,6 +982,18 @@ static int skip_tx_en_setup(struct serial_private *priv,
982#define PCI_SUBDEVICE_ID_POCTAL422 0x0408 982#define PCI_SUBDEVICE_ID_POCTAL422 0x0408
983#define PCI_VENDOR_ID_ADVANTECH 0x13fe 983#define PCI_VENDOR_ID_ADVANTECH 0x13fe
984#define PCI_DEVICE_ID_ADVANTECH_PCI3620 0x3620 984#define PCI_DEVICE_ID_ADVANTECH_PCI3620 0x3620
985#define PCI_DEVICE_ID_TITAN_200I 0x8028
986#define PCI_DEVICE_ID_TITAN_400I 0x8048
987#define PCI_DEVICE_ID_TITAN_800I 0x8088
988#define PCI_DEVICE_ID_TITAN_800EH 0xA007
989#define PCI_DEVICE_ID_TITAN_800EHB 0xA008
990#define PCI_DEVICE_ID_TITAN_400EH 0xA009
991#define PCI_DEVICE_ID_TITAN_100E 0xA010
992#define PCI_DEVICE_ID_TITAN_200E 0xA012
993#define PCI_DEVICE_ID_TITAN_400E 0xA013
994#define PCI_DEVICE_ID_TITAN_800E 0xA014
995#define PCI_DEVICE_ID_TITAN_200EI 0xA016
996#define PCI_DEVICE_ID_TITAN_200EISI 0xA017
985 997
986/* Unknown vendors/cards - this should not be in linux/pci_ids.h */ 998/* Unknown vendors/cards - this should not be in linux/pci_ids.h */
987#define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584 999#define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584
@@ -1541,6 +1553,10 @@ enum pci_board_num_t {
1541 pbn_b3_4_115200, 1553 pbn_b3_4_115200,
1542 pbn_b3_8_115200, 1554 pbn_b3_8_115200,
1543 1555
1556 pbn_b4_bt_2_921600,
1557 pbn_b4_bt_4_921600,
1558 pbn_b4_bt_8_921600,
1559
1544 /* 1560 /*
1545 * Board-specific versions. 1561 * Board-specific versions.
1546 */ 1562 */
@@ -1995,6 +2011,25 @@ static struct pciserial_board pci_boards[] __devinitdata = {
1995 .uart_offset = 8, 2011 .uart_offset = 8,
1996 }, 2012 },
1997 2013
2014 [pbn_b4_bt_2_921600] = {
2015 .flags = FL_BASE4,
2016 .num_ports = 2,
2017 .base_baud = 921600,
2018 .uart_offset = 8,
2019 },
2020 [pbn_b4_bt_4_921600] = {
2021 .flags = FL_BASE4,
2022 .num_ports = 4,
2023 .base_baud = 921600,
2024 .uart_offset = 8,
2025 },
2026 [pbn_b4_bt_8_921600] = {
2027 .flags = FL_BASE4,
2028 .num_ports = 8,
2029 .base_baud = 921600,
2030 .uart_offset = 8,
2031 },
2032
1998 /* 2033 /*
1999 * Entries following this are board-specific. 2034 * Entries following this are board-specific.
2000 */ 2035 */
@@ -3043,6 +3078,42 @@ static struct pci_device_id serial_pci_tbl[] = {
3043 { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800L, 3078 { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800L,
3044 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3079 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
3045 pbn_b0_bt_8_921600 }, 3080 pbn_b0_bt_8_921600 },
3081 { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200I,
3082 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
3083 pbn_b4_bt_2_921600 },
3084 { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400I,
3085 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
3086 pbn_b4_bt_4_921600 },
3087 { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800I,
3088 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
3089 pbn_b4_bt_8_921600 },
3090 { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400EH,
3091 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
3092 pbn_b0_4_921600 },
3093 { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800EH,
3094 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
3095 pbn_b0_4_921600 },
3096 { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800EHB,
3097 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
3098 pbn_b0_4_921600 },
3099 { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100E,
3100 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
3101 pbn_oxsemi_1_4000000 },
3102 { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200E,
3103 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
3104 pbn_oxsemi_2_4000000 },
3105 { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400E,
3106 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
3107 pbn_oxsemi_4_4000000 },
3108 { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800E,
3109 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
3110 pbn_oxsemi_8_4000000 },
3111 { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200EI,
3112 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
3113 pbn_oxsemi_2_4000000 },
3114 { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200EISI,
3115 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
3116 pbn_oxsemi_2_4000000 },
3046 3117
3047 { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_550, 3118 { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_550,
3048 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3119 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
diff --git a/drivers/serial/altera_uart.c b/drivers/serial/altera_uart.c
index bcee156d2f2e..0f1189605d21 100644
--- a/drivers/serial/altera_uart.c
+++ b/drivers/serial/altera_uart.c
@@ -89,15 +89,12 @@ static unsigned int altera_uart_tx_empty(struct uart_port *port)
89static unsigned int altera_uart_get_mctrl(struct uart_port *port) 89static unsigned int altera_uart_get_mctrl(struct uart_port *port)
90{ 90{
91 struct altera_uart *pp = container_of(port, struct altera_uart, port); 91 struct altera_uart *pp = container_of(port, struct altera_uart, port);
92 unsigned long flags;
93 unsigned int sigs; 92 unsigned int sigs;
94 93
95 spin_lock_irqsave(&port->lock, flags);
96 sigs = 94 sigs =
97 (readl(port->membase + ALTERA_UART_STATUS_REG) & 95 (readl(port->membase + ALTERA_UART_STATUS_REG) &
98 ALTERA_UART_STATUS_CTS_MSK) ? TIOCM_CTS : 0; 96 ALTERA_UART_STATUS_CTS_MSK) ? TIOCM_CTS : 0;
99 sigs |= (pp->sigs & TIOCM_RTS); 97 sigs |= (pp->sigs & TIOCM_RTS);
100 spin_unlock_irqrestore(&port->lock, flags);
101 98
102 return sigs; 99 return sigs;
103} 100}
@@ -105,49 +102,37 @@ static unsigned int altera_uart_get_mctrl(struct uart_port *port)
105static void altera_uart_set_mctrl(struct uart_port *port, unsigned int sigs) 102static void altera_uart_set_mctrl(struct uart_port *port, unsigned int sigs)
106{ 103{
107 struct altera_uart *pp = container_of(port, struct altera_uart, port); 104 struct altera_uart *pp = container_of(port, struct altera_uart, port);
108 unsigned long flags;
109 105
110 spin_lock_irqsave(&port->lock, flags);
111 pp->sigs = sigs; 106 pp->sigs = sigs;
112 if (sigs & TIOCM_RTS) 107 if (sigs & TIOCM_RTS)
113 pp->imr |= ALTERA_UART_CONTROL_RTS_MSK; 108 pp->imr |= ALTERA_UART_CONTROL_RTS_MSK;
114 else 109 else
115 pp->imr &= ~ALTERA_UART_CONTROL_RTS_MSK; 110 pp->imr &= ~ALTERA_UART_CONTROL_RTS_MSK;
116 writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG); 111 writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
117 spin_unlock_irqrestore(&port->lock, flags);
118} 112}
119 113
120static void altera_uart_start_tx(struct uart_port *port) 114static void altera_uart_start_tx(struct uart_port *port)
121{ 115{
122 struct altera_uart *pp = container_of(port, struct altera_uart, port); 116 struct altera_uart *pp = container_of(port, struct altera_uart, port);
123 unsigned long flags;
124 117
125 spin_lock_irqsave(&port->lock, flags);
126 pp->imr |= ALTERA_UART_CONTROL_TRDY_MSK; 118 pp->imr |= ALTERA_UART_CONTROL_TRDY_MSK;
127 writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG); 119 writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
128 spin_unlock_irqrestore(&port->lock, flags);
129} 120}
130 121
131static void altera_uart_stop_tx(struct uart_port *port) 122static void altera_uart_stop_tx(struct uart_port *port)
132{ 123{
133 struct altera_uart *pp = container_of(port, struct altera_uart, port); 124 struct altera_uart *pp = container_of(port, struct altera_uart, port);
134 unsigned long flags;
135 125
136 spin_lock_irqsave(&port->lock, flags);
137 pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK; 126 pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK;
138 writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG); 127 writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
139 spin_unlock_irqrestore(&port->lock, flags);
140} 128}
141 129
142static void altera_uart_stop_rx(struct uart_port *port) 130static void altera_uart_stop_rx(struct uart_port *port)
143{ 131{
144 struct altera_uart *pp = container_of(port, struct altera_uart, port); 132 struct altera_uart *pp = container_of(port, struct altera_uart, port);
145 unsigned long flags;
146 133
147 spin_lock_irqsave(&port->lock, flags);
148 pp->imr &= ~ALTERA_UART_CONTROL_RRDY_MSK; 134 pp->imr &= ~ALTERA_UART_CONTROL_RRDY_MSK;
149 writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG); 135 writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
150 spin_unlock_irqrestore(&port->lock, flags);
151} 136}
152 137
153static void altera_uart_break_ctl(struct uart_port *port, int break_state) 138static 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)
272 unsigned int isr; 257 unsigned int isr;
273 258
274 isr = readl(port->membase + ALTERA_UART_STATUS_REG) & pp->imr; 259 isr = readl(port->membase + ALTERA_UART_STATUS_REG) & pp->imr;
260
261 spin_lock(&port->lock);
275 if (isr & ALTERA_UART_STATUS_RRDY_MSK) 262 if (isr & ALTERA_UART_STATUS_RRDY_MSK)
276 altera_uart_rx_chars(pp); 263 altera_uart_rx_chars(pp);
277 if (isr & ALTERA_UART_STATUS_TRDY_MSK) 264 if (isr & ALTERA_UART_STATUS_TRDY_MSK)
278 altera_uart_tx_chars(pp); 265 altera_uart_tx_chars(pp);
266 spin_unlock(&port->lock);
267
279 return IRQ_RETVAL(isr); 268 return IRQ_RETVAL(isr);
280} 269}
281 270
@@ -402,31 +391,24 @@ int __init early_altera_uart_setup(struct altera_uart_platform_uart *platp)
402 return 0; 391 return 0;
403} 392}
404 393
405static void altera_uart_console_putc(struct console *co, const char c) 394static void altera_uart_console_putc(struct uart_port *port, const char c)
406{ 395{
407 struct uart_port *port = &(altera_uart_ports + co->index)->port; 396 while (!(readl(port->membase + ALTERA_UART_STATUS_REG) &
408 int i; 397 ALTERA_UART_STATUS_TRDY_MSK))
398 cpu_relax();
409 399
410 for (i = 0; i < 0x10000; i++) {
411 if (readl(port->membase + ALTERA_UART_STATUS_REG) &
412 ALTERA_UART_STATUS_TRDY_MSK)
413 break;
414 }
415 writel(c, port->membase + ALTERA_UART_TXDATA_REG); 400 writel(c, port->membase + ALTERA_UART_TXDATA_REG);
416 for (i = 0; i < 0x10000; i++) {
417 if (readl(port->membase + ALTERA_UART_STATUS_REG) &
418 ALTERA_UART_STATUS_TRDY_MSK)
419 break;
420 }
421} 401}
422 402
423static void altera_uart_console_write(struct console *co, const char *s, 403static void altera_uart_console_write(struct console *co, const char *s,
424 unsigned int count) 404 unsigned int count)
425{ 405{
406 struct uart_port *port = &(altera_uart_ports + co->index)->port;
407
426 for (; count; count--, s++) { 408 for (; count; count--, s++) {
427 altera_uart_console_putc(co, *s); 409 altera_uart_console_putc(port, *s);
428 if (*s == '\n') 410 if (*s == '\n')
429 altera_uart_console_putc(co, '\r'); 411 altera_uart_console_putc(port, '\r');
430 } 412 }
431} 413}
432 414
@@ -516,7 +498,7 @@ static int __devinit altera_uart_probe(struct platform_device *pdev)
516 return 0; 498 return 0;
517} 499}
518 500
519static int altera_uart_remove(struct platform_device *pdev) 501static int __devexit altera_uart_remove(struct platform_device *pdev)
520{ 502{
521 struct uart_port *port; 503 struct uart_port *port;
522 int i; 504 int i;
diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c
index 96f7e7484fee..511cbf687877 100644
--- a/drivers/serial/bfin_5xx.c
+++ b/drivers/serial/bfin_5xx.c
@@ -797,7 +797,7 @@ static void bfin_serial_shutdown(struct uart_port *port)
797 gpio_free(uart->rts_pin); 797 gpio_free(uart->rts_pin);
798#endif 798#endif
799#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS 799#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
800 if (UART_GET_IER(uart) && EDSSI) 800 if (UART_GET_IER(uart) & EDSSI)
801 free_irq(uart->status_irq, uart); 801 free_irq(uart->status_irq, uart);
802#endif 802#endif
803} 803}
@@ -869,7 +869,12 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
869 } 869 }
870 870
871 baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); 871 baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
872 quot = uart_get_divisor(port, baud) - ANOMALY_05000230; 872 quot = uart_get_divisor(port, baud);
873
874 /* If discipline is not IRDA, apply ANOMALY_05000230 */
875 if (termios->c_line != N_IRDA)
876 quot -= ANOMALY_05000230;
877
873 spin_lock_irqsave(&uart->port.lock, flags); 878 spin_lock_irqsave(&uart->port.lock, flags);
874 879
875 UART_SET_ANOMALY_THRESHOLD(uart, USEC_PER_SEC / baud * 15); 880 UART_SET_ANOMALY_THRESHOLD(uart, USEC_PER_SEC / baud * 15);
diff --git a/drivers/serial/msm_serial.c b/drivers/serial/msm_serial.c
index ecdc0facf7ee..f8c816e7725d 100644
--- a/drivers/serial/msm_serial.c
+++ b/drivers/serial/msm_serial.c
@@ -41,19 +41,6 @@ struct msm_port {
41 unsigned int imr; 41 unsigned int imr;
42}; 42};
43 43
44#define UART_TO_MSM(uart_port) ((struct msm_port *) uart_port)
45
46static inline void msm_write(struct uart_port *port, unsigned int val,
47 unsigned int off)
48{
49 __raw_writel(val, port->membase + off);
50}
51
52static inline unsigned int msm_read(struct uart_port *port, unsigned int off)
53{
54 return __raw_readl(port->membase + off);
55}
56
57static void msm_stop_tx(struct uart_port *port) 44static void msm_stop_tx(struct uart_port *port)
58{ 45{
59 struct msm_port *msm_port = UART_TO_MSM(port); 46 struct msm_port *msm_port = UART_TO_MSM(port);
@@ -320,11 +307,7 @@ static void msm_init_clock(struct uart_port *port)
320 struct msm_port *msm_port = UART_TO_MSM(port); 307 struct msm_port *msm_port = UART_TO_MSM(port);
321 308
322 clk_enable(msm_port->clk); 309 clk_enable(msm_port->clk);
323 310 msm_serial_set_mnd_regs(port);
324 msm_write(port, 0xC0, UART_MREG);
325 msm_write(port, 0xB2, UART_NREG);
326 msm_write(port, 0x7D, UART_DREG);
327 msm_write(port, 0x1C, UART_MNDREG);
328} 311}
329 312
330static int msm_startup(struct uart_port *port) 313static int msm_startup(struct uart_port *port)
@@ -706,6 +689,8 @@ static int __init msm_serial_probe(struct platform_device *pdev)
706 if (unlikely(IS_ERR(msm_port->clk))) 689 if (unlikely(IS_ERR(msm_port->clk)))
707 return PTR_ERR(msm_port->clk); 690 return PTR_ERR(msm_port->clk);
708 port->uartclk = clk_get_rate(msm_port->clk); 691 port->uartclk = clk_get_rate(msm_port->clk);
692 printk(KERN_INFO "uartclk = %d\n", port->uartclk);
693
709 694
710 resource = platform_get_resource(pdev, IORESOURCE_MEM, 0); 695 resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
711 if (unlikely(!resource)) 696 if (unlikely(!resource))
diff --git a/drivers/serial/msm_serial.h b/drivers/serial/msm_serial.h
index 689f1fa0e84e..f6ca9ca79e98 100644
--- a/drivers/serial/msm_serial.h
+++ b/drivers/serial/msm_serial.h
@@ -114,4 +114,60 @@
114#define UART_MISR 0x0010 114#define UART_MISR 0x0010
115#define UART_ISR 0x0014 115#define UART_ISR 0x0014
116 116
117#define UART_TO_MSM(uart_port) ((struct msm_port *) uart_port)
118
119static inline
120void msm_write(struct uart_port *port, unsigned int val, unsigned int off)
121{
122 __raw_writel(val, port->membase + off);
123}
124
125static inline
126unsigned int msm_read(struct uart_port *port, unsigned int off)
127{
128 return __raw_readl(port->membase + off);
129}
130
131/*
132 * Setup the MND registers to use the TCXO clock.
133 */
134static inline void msm_serial_set_mnd_regs_tcxo(struct uart_port *port)
135{
136 msm_write(port, 0x06, UART_MREG);
137 msm_write(port, 0xF1, UART_NREG);
138 msm_write(port, 0x0F, UART_DREG);
139 msm_write(port, 0x1A, UART_MNDREG);
140}
141
142/*
143 * Setup the MND registers to use the TCXO clock divided by 4.
144 */
145static inline void msm_serial_set_mnd_regs_tcxoby4(struct uart_port *port)
146{
147 msm_write(port, 0x18, UART_MREG);
148 msm_write(port, 0xF6, UART_NREG);
149 msm_write(port, 0x0F, UART_DREG);
150 msm_write(port, 0x0A, UART_MNDREG);
151}
152
153static inline
154void msm_serial_set_mnd_regs_from_uartclk(struct uart_port *port)
155{
156 if (port->uartclk == 19200000)
157 msm_serial_set_mnd_regs_tcxo(port);
158 else
159 msm_serial_set_mnd_regs_tcxoby4(port);
160}
161
162/*
163 * TROUT has a specific defect that makes it report it's uartclk
164 * as 19.2Mhz (TCXO) when it's actually 4.8Mhz (TCXO/4). This special
165 * cases TROUT to use the right clock.
166 */
167#ifdef CONFIG_MACH_TROUT
168#define msm_serial_set_mnd_regs msm_serial_set_mnd_regs_tcxoby4
169#else
170#define msm_serial_set_mnd_regs msm_serial_set_mnd_regs_from_uartclk
171#endif
172
117#endif /* __DRIVERS_SERIAL_MSM_SERIAL_H */ 173#endif /* __DRIVERS_SERIAL_MSM_SERIAL_H */
diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c
index cabbdc7ba583..5b9cde79e4ea 100644
--- a/drivers/serial/pmac_zilog.c
+++ b/drivers/serial/pmac_zilog.c
@@ -2005,8 +2005,11 @@ static struct of_device_id pmz_match[] =
2005MODULE_DEVICE_TABLE (of, pmz_match); 2005MODULE_DEVICE_TABLE (of, pmz_match);
2006 2006
2007static struct macio_driver pmz_driver = { 2007static struct macio_driver pmz_driver = {
2008 .name = "pmac_zilog", 2008 .driver = {
2009 .match_table = pmz_match, 2009 .name = "pmac_zilog",
2010 .owner = THIS_MODULE,
2011 .of_match_table = pmz_match,
2012 },
2010 .probe = pmz_attach, 2013 .probe = pmz_attach,
2011 .remove = pmz_detach, 2014 .remove = pmz_detach,
2012 .suspend = pmz_suspend, 2015 .suspend = pmz_suspend,
diff --git a/drivers/serial/s5pv210.c b/drivers/serial/s5pv210.c
index 8dc03837617b..4a789e5361a4 100644
--- a/drivers/serial/s5pv210.c
+++ b/drivers/serial/s5pv210.c
@@ -119,7 +119,7 @@ static int s5p_serial_probe(struct platform_device *pdev)
119 return s3c24xx_serial_probe(pdev, s5p_uart_inf[pdev->id]); 119 return s3c24xx_serial_probe(pdev, s5p_uart_inf[pdev->id]);
120} 120}
121 121
122static struct platform_driver s5p_serial_drv = { 122static struct platform_driver s5p_serial_driver = {
123 .probe = s5p_serial_probe, 123 .probe = s5p_serial_probe,
124 .remove = __devexit_p(s3c24xx_serial_remove), 124 .remove = __devexit_p(s3c24xx_serial_remove),
125 .driver = { 125 .driver = {
@@ -130,19 +130,19 @@ static struct platform_driver s5p_serial_drv = {
130 130
131static int __init s5pv210_serial_console_init(void) 131static int __init s5pv210_serial_console_init(void)
132{ 132{
133 return s3c24xx_serial_initconsole(&s5p_serial_drv, s5p_uart_inf); 133 return s3c24xx_serial_initconsole(&s5p_serial_driver, s5p_uart_inf);
134} 134}
135 135
136console_initcall(s5pv210_serial_console_init); 136console_initcall(s5pv210_serial_console_init);
137 137
138static int __init s5p_serial_init(void) 138static int __init s5p_serial_init(void)
139{ 139{
140 return s3c24xx_serial_init(&s5p_serial_drv, *s5p_uart_inf); 140 return s3c24xx_serial_init(&s5p_serial_driver, *s5p_uart_inf);
141} 141}
142 142
143static void __exit s5p_serial_exit(void) 143static void __exit s5p_serial_exit(void)
144{ 144{
145 platform_driver_unregister(&s5p_serial_drv); 145 platform_driver_unregister(&s5p_serial_driver);
146} 146}
147 147
148module_init(s5p_serial_init); 148module_init(s5p_serial_init);
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index dadd686c9801..526307368f8b 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -715,6 +715,8 @@ static struct pcmcia_device_id serial_ids[] = {
715 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0057, 0x0021), 715 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0057, 0x0021),
716 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0089, 0x110a), 716 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0089, 0x110a),
717 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0104, 0x000a), 717 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0104, 0x000a),
718 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0x0d0a),
719 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0x0e0a),
718 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0xea15), 720 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0xea15),
719 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0109, 0x0501), 721 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0109, 0x0501),
720 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0138, 0x110a), 722 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0138, 0x110a),
@@ -724,8 +726,6 @@ static struct pcmcia_device_id serial_ids[] = {
724 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x016c, 0x0081), 726 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x016c, 0x0081),
725 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x021b, 0x0101), 727 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x021b, 0x0101),
726 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x08a1, 0xc0ab), 728 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x08a1, 0xc0ab),
727 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0x0d0a),
728 PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0x0e0a),
729 PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "CC/XJEM3288", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x04cd2988, 0x46a52d63), 729 PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "CC/XJEM3288", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x04cd2988, 0x46a52d63),
730 PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "CC/XJEM3336", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x0143b773, 0x46a52d63), 730 PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "CC/XJEM3336", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x0143b773, 0x46a52d63),
731 PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "EM1144T", "PCMCIA MODEM", 0xf510db04, 0x856d66c8, 0xbd6c43ef), 731 PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "EM1144T", "PCMCIA MODEM", 0xf510db04, 0x856d66c8, 0xbd6c43ef),
@@ -768,17 +768,26 @@ static struct pcmcia_device_id serial_ids[] = {
768 PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x0276), 768 PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x0276),
769 PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0039), 769 PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0039),
770 PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0006), 770 PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0006),
771 PCMCIA_DEVICE_MANF_CARD(0x0105, 0x0101), /* TDK DF2814 */
772 PCMCIA_DEVICE_MANF_CARD(0x0105, 0x100a), /* Xircom CM-56G */
773 PCMCIA_DEVICE_MANF_CARD(0x0105, 0x3e0a), /* TDK DF5660 */
771 PCMCIA_DEVICE_MANF_CARD(0x0105, 0x410a), 774 PCMCIA_DEVICE_MANF_CARD(0x0105, 0x410a),
775 PCMCIA_DEVICE_MANF_CARD(0x0107, 0x0002), /* USRobotics 14,400 */
772 PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d50), 776 PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d50),
773 PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d51), 777 PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d51),
774 PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d52), 778 PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d52),
775 PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d53), 779 PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d53),
776 PCMCIA_DEVICE_MANF_CARD(0x010b, 0xd180), 780 PCMCIA_DEVICE_MANF_CARD(0x010b, 0xd180),
781 PCMCIA_DEVICE_MANF_CARD(0x0115, 0x3330), /* USRobotics/SUN 14,400 */
782 PCMCIA_DEVICE_MANF_CARD(0x0124, 0x0100), /* Nokia DTP-2 ver II */
783 PCMCIA_DEVICE_MANF_CARD(0x0134, 0x5600), /* LASAT COMMUNICATIONS A/S */
777 PCMCIA_DEVICE_MANF_CARD(0x0137, 0x000e), 784 PCMCIA_DEVICE_MANF_CARD(0x0137, 0x000e),
778 PCMCIA_DEVICE_MANF_CARD(0x0137, 0x001b), 785 PCMCIA_DEVICE_MANF_CARD(0x0137, 0x001b),
779 PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0025), 786 PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0025),
780 PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0045), 787 PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0045),
781 PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0052), 788 PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0052),
789 PCMCIA_DEVICE_MANF_CARD(0x016c, 0x0006), /* Psion 56K+Fax */
790 PCMCIA_DEVICE_MANF_CARD(0x0200, 0x0001), /* MultiMobile */
782 PCMCIA_DEVICE_PROD_ID134("ADV", "TECH", "COMpad-32/85", 0x67459937, 0x916d02ba, 0x8fbe92ae), 791 PCMCIA_DEVICE_PROD_ID134("ADV", "TECH", "COMpad-32/85", 0x67459937, 0x916d02ba, 0x8fbe92ae),
783 PCMCIA_DEVICE_PROD_ID124("GATEWAY2000", "CC3144", "PCMCIA MODEM", 0x506bccae, 0xcb3685f1, 0xbd6c43ef), 792 PCMCIA_DEVICE_PROD_ID124("GATEWAY2000", "CC3144", "PCMCIA MODEM", 0x506bccae, 0xcb3685f1, 0xbd6c43ef),
784 PCMCIA_DEVICE_PROD_ID14("MEGAHERTZ", "PCMCIA MODEM", 0xf510db04, 0xbd6c43ef), 793 PCMCIA_DEVICE_PROD_ID14("MEGAHERTZ", "PCMCIA MODEM", 0xf510db04, 0xbd6c43ef),
@@ -792,16 +801,21 @@ static struct pcmcia_device_id serial_ids[] = {
792 PCMCIA_DEVICE_PROD_ID12("COMPAQ", "PCMCIA 33600 FAX/DATA MODEM", 0xa3a3062c, 0x5a00ce95), 801 PCMCIA_DEVICE_PROD_ID12("COMPAQ", "PCMCIA 33600 FAX/DATA MODEM", 0xa3a3062c, 0x5a00ce95),
793 PCMCIA_DEVICE_PROD_ID12("Computerboards, Inc.", "PCM-COM422", 0xd0b78f51, 0x7e2d49ed), 802 PCMCIA_DEVICE_PROD_ID12("Computerboards, Inc.", "PCM-COM422", 0xd0b78f51, 0x7e2d49ed),
794 PCMCIA_DEVICE_PROD_ID12("Dr. Neuhaus", "FURY CARD 14K4", 0x76942813, 0x8b96ce65), 803 PCMCIA_DEVICE_PROD_ID12("Dr. Neuhaus", "FURY CARD 14K4", 0x76942813, 0x8b96ce65),
804 PCMCIA_DEVICE_PROD_ID12("IBM", "ISDN/56K/GSM", 0xb569a6e5, 0xfee5297b),
795 PCMCIA_DEVICE_PROD_ID12("Intelligent", "ANGIA FAX/MODEM", 0xb496e65e, 0xf31602a6), 805 PCMCIA_DEVICE_PROD_ID12("Intelligent", "ANGIA FAX/MODEM", 0xb496e65e, 0xf31602a6),
796 PCMCIA_DEVICE_PROD_ID12("Intel", "MODEM 2400+", 0x816cc815, 0x412729fb), 806 PCMCIA_DEVICE_PROD_ID12("Intel", "MODEM 2400+", 0x816cc815, 0x412729fb),
807 PCMCIA_DEVICE_PROD_ID12("Intertex", "IX34-PCMCIA", 0xf8a097e3, 0x97880447),
797 PCMCIA_DEVICE_PROD_ID12("IOTech Inc ", "PCMCIA Dual RS-232 Serial Port Card", 0x3bd2d898, 0x92abc92f), 808 PCMCIA_DEVICE_PROD_ID12("IOTech Inc ", "PCMCIA Dual RS-232 Serial Port Card", 0x3bd2d898, 0x92abc92f),
798 PCMCIA_DEVICE_PROD_ID12("MACRONIX", "FAX/MODEM", 0x668388b3, 0x3f9bdf2f), 809 PCMCIA_DEVICE_PROD_ID12("MACRONIX", "FAX/MODEM", 0x668388b3, 0x3f9bdf2f),
799 PCMCIA_DEVICE_PROD_ID12("Multi-Tech", "MT1432LT", 0x5f73be51, 0x0b3e2383), 810 PCMCIA_DEVICE_PROD_ID12("Multi-Tech", "MT1432LT", 0x5f73be51, 0x0b3e2383),
800 PCMCIA_DEVICE_PROD_ID12("Multi-Tech", "MT2834LT", 0x5f73be51, 0x4cd7c09e), 811 PCMCIA_DEVICE_PROD_ID12("Multi-Tech", "MT2834LT", 0x5f73be51, 0x4cd7c09e),
801 PCMCIA_DEVICE_PROD_ID12("OEM ", "C288MX ", 0xb572d360, 0xd2385b7a), 812 PCMCIA_DEVICE_PROD_ID12("OEM ", "C288MX ", 0xb572d360, 0xd2385b7a),
813 PCMCIA_DEVICE_PROD_ID12("Option International", "V34bis GSM/PSTN Data/Fax Modem", 0x9d7cd6f5, 0x5cb8bf41),
802 PCMCIA_DEVICE_PROD_ID12("PCMCIA ", "C336MX ", 0x99bcafe9, 0xaa25bcab), 814 PCMCIA_DEVICE_PROD_ID12("PCMCIA ", "C336MX ", 0x99bcafe9, 0xaa25bcab),
803 PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "PCMCIA Dual RS-232 Serial Port Card", 0xc4420b35, 0x92abc92f), 815 PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "PCMCIA Dual RS-232 Serial Port Card", 0xc4420b35, 0x92abc92f),
804 PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "Dual RS-232 Serial Port PC Card", 0xc4420b35, 0x031a380d), 816 PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "Dual RS-232 Serial Port PC Card", 0xc4420b35, 0x031a380d),
817 PCMCIA_DEVICE_PROD_ID12("Telia", "SurfinBird 560P/A+", 0xe2cdd5e, 0xc9314b38),
818 PCMCIA_DEVICE_PROD_ID1("Smart Serial Port", 0x2d8ce292),
805 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "cis/PCMLM28.cis"), 819 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "cis/PCMLM28.cis"),
806 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "cis/PCMLM28.cis"), 820 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "cis/PCMLM28.cis"),
807 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"), 821 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"),
diff --git a/drivers/sfi/sfi_acpi.c b/drivers/sfi/sfi_acpi.c
index 34aba30eb84b..f5b4ca581541 100644
--- a/drivers/sfi/sfi_acpi.c
+++ b/drivers/sfi/sfi_acpi.c
@@ -173,3 +173,44 @@ int sfi_acpi_table_parse(char *signature, char *oem_id, char *oem_table_id,
173 sfi_acpi_put_table(table); 173 sfi_acpi_put_table(table);
174 return ret; 174 return ret;
175} 175}
176
177static ssize_t sfi_acpi_table_show(struct file *filp, struct kobject *kobj,
178 struct bin_attribute *bin_attr, char *buf,
179 loff_t offset, size_t count)
180{
181 struct sfi_table_attr *tbl_attr =
182 container_of(bin_attr, struct sfi_table_attr, attr);
183 struct acpi_table_header *th = NULL;
184 struct sfi_table_key key;
185 ssize_t cnt;
186
187 key.sig = tbl_attr->name;
188 key.oem_id = NULL;
189 key.oem_table_id = NULL;
190
191 th = sfi_acpi_get_table(&key);
192 if (!th)
193 return 0;
194
195 cnt = memory_read_from_buffer(buf, count, &offset,
196 th, th->length);
197 sfi_acpi_put_table(th);
198
199 return cnt;
200}
201
202
203void __init sfi_acpi_sysfs_init(void)
204{
205 u32 tbl_cnt, i;
206 struct sfi_table_attr *tbl_attr;
207
208 tbl_cnt = XSDT_GET_NUM_ENTRIES(xsdt_va, u64);
209 for (i = 0; i < tbl_cnt; i++) {
210 tbl_attr =
211 sfi_sysfs_install_table(xsdt_va->table_offset_entry[i]);
212 tbl_attr->attr.read = sfi_acpi_table_show;
213 }
214
215 return;
216}
diff --git a/drivers/sfi/sfi_core.c b/drivers/sfi/sfi_core.c
index b204a0929139..ceba593dc84f 100644
--- a/drivers/sfi/sfi_core.c
+++ b/drivers/sfi/sfi_core.c
@@ -67,6 +67,7 @@
67#include <linux/acpi.h> 67#include <linux/acpi.h>
68#include <linux/init.h> 68#include <linux/init.h>
69#include <linux/sfi.h> 69#include <linux/sfi.h>
70#include <linux/slab.h>
70 71
71#include "sfi_core.h" 72#include "sfi_core.h"
72 73
@@ -382,6 +383,104 @@ static __init int sfi_find_syst(void)
382 return -1; 383 return -1;
383} 384}
384 385
386static struct kobject *sfi_kobj;
387static struct kobject *tables_kobj;
388
389static ssize_t sfi_table_show(struct file *filp, struct kobject *kobj,
390 struct bin_attribute *bin_attr, char *buf,
391 loff_t offset, size_t count)
392{
393 struct sfi_table_attr *tbl_attr =
394 container_of(bin_attr, struct sfi_table_attr, attr);
395 struct sfi_table_header *th = NULL;
396 struct sfi_table_key key;
397 ssize_t cnt;
398
399 key.sig = tbl_attr->name;
400 key.oem_id = NULL;
401 key.oem_table_id = NULL;
402
403 if (strncmp(SFI_SIG_SYST, tbl_attr->name, SFI_SIGNATURE_SIZE)) {
404 th = sfi_get_table(&key);
405 if (!th)
406 return 0;
407
408 cnt = memory_read_from_buffer(buf, count, &offset,
409 th, th->len);
410 sfi_put_table(th);
411 } else
412 cnt = memory_read_from_buffer(buf, count, &offset,
413 syst_va, syst_va->header.len);
414
415 return cnt;
416}
417
418struct sfi_table_attr __init *sfi_sysfs_install_table(u64 pa)
419{
420 struct sfi_table_attr *tbl_attr;
421 struct sfi_table_header *th;
422 int ret;
423
424 tbl_attr = kzalloc(sizeof(struct sfi_table_attr), GFP_KERNEL);
425 if (!tbl_attr)
426 return NULL;
427
428 th = sfi_map_table(pa);
429 if (!th || !th->sig[0]) {
430 kfree(tbl_attr);
431 return NULL;
432 }
433
434 sysfs_attr_init(&tbl_attr->attr.attr);
435 memcpy(tbl_attr->name, th->sig, SFI_SIGNATURE_SIZE);
436
437 tbl_attr->attr.size = 0;
438 tbl_attr->attr.read = sfi_table_show;
439 tbl_attr->attr.attr.name = tbl_attr->name;
440 tbl_attr->attr.attr.mode = 0400;
441
442 ret = sysfs_create_bin_file(tables_kobj,
443 &tbl_attr->attr);
444 if (ret) {
445 kfree(tbl_attr);
446 tbl_attr = NULL;
447 }
448
449 sfi_unmap_table(th);
450 return tbl_attr;
451}
452
453static int __init sfi_sysfs_init(void)
454{
455 int tbl_cnt, i;
456
457 if (sfi_disabled)
458 return 0;
459
460 sfi_kobj = kobject_create_and_add("sfi", firmware_kobj);
461 if (!sfi_kobj)
462 return 0;
463
464 tables_kobj = kobject_create_and_add("tables", sfi_kobj);
465 if (!tables_kobj) {
466 kobject_put(sfi_kobj);
467 return 0;
468 }
469
470 sfi_sysfs_install_table(syst_pa);
471
472 tbl_cnt = SFI_GET_NUM_ENTRIES(syst_va, u64);
473
474 for (i = 0; i < tbl_cnt; i++)
475 sfi_sysfs_install_table(syst_va->pentry[i]);
476
477 sfi_acpi_sysfs_init();
478 kobject_uevent(sfi_kobj, KOBJ_ADD);
479 kobject_uevent(tables_kobj, KOBJ_ADD);
480 pr_info("SFI sysfs interfaces init success\n");
481 return 0;
482}
483
385void __init sfi_init(void) 484void __init sfi_init(void)
386{ 485{
387 if (!acpi_disabled) 486 if (!acpi_disabled)
@@ -390,7 +489,7 @@ void __init sfi_init(void)
390 if (sfi_disabled) 489 if (sfi_disabled)
391 return; 490 return;
392 491
393 pr_info("Simple Firmware Interface v0.7 http://simplefirmware.org\n"); 492 pr_info("Simple Firmware Interface v0.81 http://simplefirmware.org\n");
394 493
395 if (sfi_find_syst() || sfi_parse_syst() || sfi_platform_init()) 494 if (sfi_find_syst() || sfi_parse_syst() || sfi_platform_init())
396 disable_sfi(); 495 disable_sfi();
@@ -414,3 +513,9 @@ void __init sfi_init_late(void)
414 513
415 sfi_acpi_init(); 514 sfi_acpi_init();
416} 515}
516
517/*
518 * The reason we put it here becasue we need wait till the /sys/firmware
519 * is setup, then our interface can be registered in /sys/firmware/sfi
520 */
521core_initcall(sfi_sysfs_init);
diff --git a/drivers/sfi/sfi_core.h b/drivers/sfi/sfi_core.h
index da82d39e104d..b7cf220d44ec 100644
--- a/drivers/sfi/sfi_core.h
+++ b/drivers/sfi/sfi_core.h
@@ -61,6 +61,12 @@ struct sfi_table_key{
61 char *oem_table_id; 61 char *oem_table_id;
62}; 62};
63 63
64/* sysfs interface */
65struct sfi_table_attr {
66 struct bin_attribute attr;
67 char name[8];
68};
69
64#define SFI_ANY_KEY { .sig = NULL, .oem_id = NULL, .oem_table_id = NULL } 70#define SFI_ANY_KEY { .sig = NULL, .oem_id = NULL, .oem_table_id = NULL }
65 71
66extern int __init sfi_acpi_init(void); 72extern int __init sfi_acpi_init(void);
@@ -68,3 +74,5 @@ extern struct sfi_table_header *sfi_check_table(u64 paddr,
68 struct sfi_table_key *key); 74 struct sfi_table_key *key);
69struct sfi_table_header *sfi_get_table(struct sfi_table_key *key); 75struct sfi_table_header *sfi_get_table(struct sfi_table_key *key);
70extern void sfi_put_table(struct sfi_table_header *table); 76extern void sfi_put_table(struct sfi_table_header *table);
77extern struct sfi_table_attr __init *sfi_sysfs_install_table(u64 pa);
78extern void __init sfi_acpi_sysfs_init(void);
diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c
index c585574b9aed..e91a23e5ffd8 100644
--- a/drivers/sh/intc.c
+++ b/drivers/sh/intc.c
@@ -16,6 +16,8 @@
16 * License. See the file "COPYING" in the main directory of this archive 16 * License. See the file "COPYING" in the main directory of this archive
17 * for more details. 17 * for more details.
18 */ 18 */
19#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20
19#include <linux/init.h> 21#include <linux/init.h>
20#include <linux/irq.h> 22#include <linux/irq.h>
21#include <linux/module.h> 23#include <linux/module.h>
@@ -855,8 +857,8 @@ static void __init intc_register_irq(struct intc_desc *desc,
855 primary = 1; 857 primary = 1;
856 858
857 if (!data[0] && !data[1]) 859 if (!data[0] && !data[1])
858 pr_warning("intc: missing unique irq mask for " 860 pr_warning("missing unique irq mask for irq %d (vect 0x%04x)\n",
859 "irq %d (vect 0x%04x)\n", irq, irq2evt(irq)); 861 irq, irq2evt(irq));
860 862
861 data[0] = data[0] ? data[0] : intc_mask_data(desc, d, enum_id, 1); 863 data[0] = data[0] ? data[0] : intc_mask_data(desc, d, enum_id, 1);
862 data[1] = data[1] ? data[1] : intc_prio_data(desc, d, enum_id, 1); 864 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)
952 struct intc_desc_int *d; 954 struct intc_desc_int *d;
953 struct resource *res; 955 struct resource *res;
954 956
955 pr_info("intc: Registered controller '%s' with %u IRQs\n", 957 pr_info("Registered controller '%s' with %u IRQs\n",
956 desc->name, hw->nr_vectors); 958 desc->name, hw->nr_vectors);
957 959
958 d = kzalloc(sizeof(*d), GFP_NOWAIT); 960 d = kzalloc(sizeof(*d), GFP_NOWAIT);
@@ -1148,7 +1150,7 @@ int register_intc_userimask(unsigned long addr)
1148 if (unlikely(!uimask)) 1150 if (unlikely(!uimask))
1149 return -ENOMEM; 1151 return -ENOMEM;
1150 1152
1151 pr_info("intc: userimask support registered for levels 0 -> %d\n", 1153 pr_info("userimask support registered for levels 0 -> %d\n",
1152 default_prio_level - 1); 1154 default_prio_level - 1);
1153 1155
1154 return 0; 1156 return 0;
@@ -1286,7 +1288,7 @@ static int __init register_intc_sysdevs(void)
1286 } 1288 }
1287 1289
1288 if (error) 1290 if (error)
1289 pr_err("intc: sysdev registration error\n"); 1291 pr_err("sysdev registration error\n");
1290 1292
1291 return error; 1293 return error;
1292} 1294}
diff --git a/drivers/spi/mpc512x_psc_spi.c b/drivers/spi/mpc512x_psc_spi.c
index 28a126d2742b..2534b1ec3edd 100644
--- a/drivers/spi/mpc512x_psc_spi.c
+++ b/drivers/spi/mpc512x_psc_spi.c
@@ -512,29 +512,29 @@ static int __init mpc512x_psc_spi_of_probe(struct of_device *op,
512 u64 regaddr64, size64; 512 u64 regaddr64, size64;
513 s16 id = -1; 513 s16 id = -1;
514 514
515 regaddr_p = of_get_address(op->node, 0, &size64, NULL); 515 regaddr_p = of_get_address(op->dev.of_node, 0, &size64, NULL);
516 if (!regaddr_p) { 516 if (!regaddr_p) {
517 dev_err(&op->dev, "Invalid PSC address\n"); 517 dev_err(&op->dev, "Invalid PSC address\n");
518 return -EINVAL; 518 return -EINVAL;
519 } 519 }
520 regaddr64 = of_translate_address(op->node, regaddr_p); 520 regaddr64 = of_translate_address(op->dev.of_node, regaddr_p);
521 521
522 /* get PSC id (0..11, used by port_config) */ 522 /* get PSC id (0..11, used by port_config) */
523 if (op->dev.platform_data == NULL) { 523 if (op->dev.platform_data == NULL) {
524 const u32 *psc_nump; 524 const u32 *psc_nump;
525 525
526 psc_nump = of_get_property(op->node, "cell-index", NULL); 526 psc_nump = of_get_property(op->dev.of_node, "cell-index", NULL);
527 if (!psc_nump || *psc_nump > 11) { 527 if (!psc_nump || *psc_nump > 11) {
528 dev_err(&op->dev, "mpc512x_psc_spi: Device node %s " 528 dev_err(&op->dev, "mpc512x_psc_spi: Device node %s "
529 "has invalid cell-index property\n", 529 "has invalid cell-index property\n",
530 op->node->full_name); 530 op->dev.of_node->full_name);
531 return -EINVAL; 531 return -EINVAL;
532 } 532 }
533 id = *psc_nump; 533 id = *psc_nump;
534 } 534 }
535 535
536 return mpc512x_psc_spi_do_probe(&op->dev, (u32) regaddr64, (u32) size64, 536 return mpc512x_psc_spi_do_probe(&op->dev, (u32) regaddr64, (u32) size64,
537 irq_of_parse_and_map(op->node, 0), id); 537 irq_of_parse_and_map(op->dev.of_node, 0), id);
538} 538}
539 539
540static int __exit mpc512x_psc_spi_of_remove(struct of_device *op) 540static 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[] = {
550MODULE_DEVICE_TABLE(of, mpc512x_psc_spi_of_match); 550MODULE_DEVICE_TABLE(of, mpc512x_psc_spi_of_match);
551 551
552static struct of_platform_driver mpc512x_psc_spi_of_driver = { 552static struct of_platform_driver mpc512x_psc_spi_of_driver = {
553 .match_table = mpc512x_psc_spi_of_match,
554 .probe = mpc512x_psc_spi_of_probe, 553 .probe = mpc512x_psc_spi_of_probe,
555 .remove = __exit_p(mpc512x_psc_spi_of_remove), 554 .remove = __exit_p(mpc512x_psc_spi_of_remove),
556 .driver = { 555 .driver = {
557 .name = "mpc512x-psc-spi", 556 .name = "mpc512x-psc-spi",
558 .owner = THIS_MODULE, 557 .owner = THIS_MODULE,
558 .of_match_table = mpc512x_psc_spi_of_match,
559 }, 559 },
560}; 560};
561 561
diff --git a/drivers/spi/spi_ppc4xx.c b/drivers/spi/spi_ppc4xx.c
index 19c0b3b34fce..d53466a249d9 100644
--- a/drivers/spi/spi_ppc4xx.c
+++ b/drivers/spi/spi_ppc4xx.c
@@ -397,7 +397,7 @@ static int __init spi_ppc4xx_of_probe(struct of_device *op,
397 struct spi_master *master; 397 struct spi_master *master;
398 struct spi_bitbang *bbp; 398 struct spi_bitbang *bbp;
399 struct resource resource; 399 struct resource resource;
400 struct device_node *np = op->node; 400 struct device_node *np = op->dev.of_node;
401 struct device *dev = &op->dev; 401 struct device *dev = &op->dev;
402 struct device_node *opbnp; 402 struct device_node *opbnp;
403 int ret; 403 int ret;
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c
index 989e2752cc36..6dcda86be6eb 100644
--- a/drivers/ssb/pci.c
+++ b/drivers/ssb/pci.c
@@ -625,9 +625,12 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus,
625 ssb_printk(KERN_ERR PFX "No SPROM available!\n"); 625 ssb_printk(KERN_ERR PFX "No SPROM available!\n");
626 return -ENODEV; 626 return -ENODEV;
627 } 627 }
628 628 if (bus->chipco.dev) { /* can be unavailible! */
629 bus->sprom_offset = (bus->chipco.dev->id.revision < 31) ? 629 bus->sprom_offset = (bus->chipco.dev->id.revision < 31) ?
630 SSB_SPROM_BASE1 : SSB_SPROM_BASE31; 630 SSB_SPROM_BASE1 : SSB_SPROM_BASE31;
631 } else {
632 bus->sprom_offset = SSB_SPROM_BASE1;
633 }
631 634
632 buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL); 635 buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
633 if (!buf) 636 if (!buf)
diff --git a/drivers/ssb/sprom.c b/drivers/ssb/sprom.c
index 007bc3a03486..4f7cc8d13277 100644
--- a/drivers/ssb/sprom.c
+++ b/drivers/ssb/sprom.c
@@ -185,6 +185,7 @@ bool ssb_is_sprom_available(struct ssb_bus *bus)
185 /* this routine differs from specs as we do not access SPROM directly 185 /* this routine differs from specs as we do not access SPROM directly
186 on PCMCIA */ 186 on PCMCIA */
187 if (bus->bustype == SSB_BUSTYPE_PCI && 187 if (bus->bustype == SSB_BUSTYPE_PCI &&
188 bus->chipco.dev && /* can be unavailible! */
188 bus->chipco.dev->id.revision >= 31) 189 bus->chipco.dev->id.revision >= 31)
189 return bus->chipco.capabilities & SSB_CHIPCO_CAP_SPROM; 190 return bus->chipco.capabilities & SSB_CHIPCO_CAP_SPROM;
190 191
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index b5c3b3013037..984a75440710 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -141,5 +141,11 @@ source "drivers/staging/ti-st/Kconfig"
141 141
142source "drivers/staging/adis16255/Kconfig" 142source "drivers/staging/adis16255/Kconfig"
143 143
144source "drivers/staging/xgifb/Kconfig"
145
146source "drivers/staging/mrst-touchscreen/Kconfig"
147
148source "drivers/staging/msm/Kconfig"
149
144endif # !STAGING_EXCLUDE_BUILD 150endif # !STAGING_EXCLUDE_BUILD
145endif # STAGING 151endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index e330dd5e843d..9fa25133874a 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -51,3 +51,6 @@ obj-$(CONFIG_CRYSTALHD) += crystalhd/
51obj-$(CONFIG_CXT1E1) += cxt1e1/ 51obj-$(CONFIG_CXT1E1) += cxt1e1/
52obj-$(CONFIG_TI_ST) += ti-st/ 52obj-$(CONFIG_TI_ST) += ti-st/
53obj-$(CONFIG_ADIS16255) += adis16255/ 53obj-$(CONFIG_ADIS16255) += adis16255/
54obj-$(CONFIG_FB_XGI) += xgifb/
55obj-$(CONFIG_TOUCHSCREEN_MRSTOUCH) += mrst-touchscreen/
56obj-$(CONFIG_MSM_STAGING) += msm/
diff --git a/drivers/staging/adis16255/Kconfig b/drivers/staging/adis16255/Kconfig
index a642be66adea..a883c1f4478b 100644
--- a/drivers/staging/adis16255/Kconfig
+++ b/drivers/staging/adis16255/Kconfig
@@ -1,5 +1,5 @@
1config ADIS16255 1config ADIS16255
2 tristate "Ananlog Devices ADIS16250/16255" 2 tristate "Analog Devices ADIS16250/16255"
3 depends on SPI && SYSFS 3 depends on SPI && SYSFS
4 ---help--- 4 ---help---
5 If you say yes here you get support for the Analog Devices 5 If you say yes here you get support for the Analog Devices
diff --git a/drivers/staging/adis16255/adis16255.c b/drivers/staging/adis16255/adis16255.c
index 1ba11f00b2e7..55d66e290f7d 100644
--- a/drivers/staging/adis16255/adis16255.c
+++ b/drivers/staging/adis16255/adis16255.c
@@ -361,7 +361,7 @@ err:
361 361
362/*-------------------------------------------------------------------------*/ 362/*-------------------------------------------------------------------------*/
363 363
364static int spi_adis16255_probe(struct spi_device *spi) 364static int __devinit spi_adis16255_probe(struct spi_device *spi)
365{ 365{
366 366
367 struct adis16255_init_data *init_data = spi->dev.platform_data; 367 struct adis16255_init_data *init_data = spi->dev.platform_data;
@@ -421,7 +421,7 @@ err:
421 return status; 421 return status;
422} 422}
423 423
424static int spi_adis16255_remove(struct spi_device *spi) 424static int __devexit spi_adis16255_remove(struct spi_device *spi)
425{ 425{
426 struct spi_adis16255_data *spiadis = dev_get_drvdata(&spi->dev); 426 struct spi_adis16255_data *spiadis = dev_get_drvdata(&spi->dev);
427 427
diff --git a/drivers/staging/batman-adv/device.c b/drivers/staging/batman-adv/device.c
index ad82ec4a4856..7eb6559e0315 100644
--- a/drivers/staging/batman-adv/device.c
+++ b/drivers/staging/batman-adv/device.c
@@ -309,7 +309,7 @@ void bat_device_add_packet(struct device_client *device_client,
309 struct device_packet *device_packet; 309 struct device_packet *device_packet;
310 unsigned long flags; 310 unsigned long flags;
311 311
312 device_packet = kmalloc(sizeof(struct device_packet), GFP_KERNEL); 312 device_packet = kmalloc(sizeof(struct device_packet), GFP_ATOMIC);
313 313
314 if (!device_packet) 314 if (!device_packet)
315 return; 315 return;
diff --git a/drivers/staging/batman-adv/main.c b/drivers/staging/batman-adv/main.c
index 9d13979c2d8e..74c70d589a93 100644
--- a/drivers/staging/batman-adv/main.c
+++ b/drivers/staging/batman-adv/main.c
@@ -127,7 +127,10 @@ int init_module(void)
127 return 0; 127 return 0;
128 128
129unreg_soft_device: 129unreg_soft_device:
130 unregister_netdevice(soft_device); 130 unregister_netdev(soft_device);
131 soft_device = NULL;
132 return -ENOMEM;
133
131free_soft_device: 134free_soft_device:
132 free_netdev(soft_device); 135 free_netdev(soft_device);
133 soft_device = NULL; 136 soft_device = NULL;
diff --git a/drivers/staging/batman-adv/send.c b/drivers/staging/batman-adv/send.c
index d8536e277a26..ac69ed871a76 100644
--- a/drivers/staging/batman-adv/send.c
+++ b/drivers/staging/batman-adv/send.c
@@ -440,6 +440,9 @@ void send_outstanding_bcast_packet(struct work_struct *work)
440 hlist_del(&forw_packet->list); 440 hlist_del(&forw_packet->list);
441 spin_unlock_irqrestore(&forw_bcast_list_lock, flags); 441 spin_unlock_irqrestore(&forw_bcast_list_lock, flags);
442 442
443 if (atomic_read(&module_state) == MODULE_DEACTIVATING)
444 goto out;
445
443 /* rebroadcast packet */ 446 /* rebroadcast packet */
444 rcu_read_lock(); 447 rcu_read_lock();
445 list_for_each_entry_rcu(batman_if, &if_list, list) { 448 list_for_each_entry_rcu(batman_if, &if_list, list) {
@@ -453,15 +456,15 @@ void send_outstanding_bcast_packet(struct work_struct *work)
453 456
454 forw_packet->num_packets++; 457 forw_packet->num_packets++;
455 458
456 /* if we still have some more bcasts to send and we are not shutting 459 /* if we still have some more bcasts to send */
457 * down */ 460 if (forw_packet->num_packets < 3) {
458 if ((forw_packet->num_packets < 3) &&
459 (atomic_read(&module_state) != MODULE_DEACTIVATING))
460 _add_bcast_packet_to_list(forw_packet, ((5 * HZ) / 1000)); 461 _add_bcast_packet_to_list(forw_packet, ((5 * HZ) / 1000));
461 else { 462 return;
462 forw_packet_free(forw_packet);
463 atomic_inc(&bcast_queue_left);
464 } 463 }
464
465out:
466 forw_packet_free(forw_packet);
467 atomic_inc(&bcast_queue_left);
465} 468}
466 469
467void send_outstanding_bat_packet(struct work_struct *work) 470void send_outstanding_bat_packet(struct work_struct *work)
@@ -476,6 +479,9 @@ void send_outstanding_bat_packet(struct work_struct *work)
476 hlist_del(&forw_packet->list); 479 hlist_del(&forw_packet->list);
477 spin_unlock_irqrestore(&forw_bat_list_lock, flags); 480 spin_unlock_irqrestore(&forw_bat_list_lock, flags);
478 481
482 if (atomic_read(&module_state) == MODULE_DEACTIVATING)
483 goto out;
484
479 send_packet(forw_packet); 485 send_packet(forw_packet);
480 486
481 /** 487 /**
@@ -483,10 +489,10 @@ void send_outstanding_bat_packet(struct work_struct *work)
483 * to determine the queues wake up time unless we are 489 * to determine the queues wake up time unless we are
484 * shutting down 490 * shutting down
485 */ 491 */
486 if ((forw_packet->own) && 492 if (forw_packet->own)
487 (atomic_read(&module_state) != MODULE_DEACTIVATING))
488 schedule_own_packet(forw_packet->if_incoming); 493 schedule_own_packet(forw_packet->if_incoming);
489 494
495out:
490 /* don't count own packet */ 496 /* don't count own packet */
491 if (!forw_packet->own) 497 if (!forw_packet->own)
492 atomic_inc(&batman_queue_left); 498 atomic_inc(&batman_queue_left);
diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig
index 8ce307e64b58..aad47326d6dc 100644
--- a/drivers/staging/comedi/Kconfig
+++ b/drivers/staging/comedi/Kconfig
@@ -100,15 +100,6 @@ menuconfig COMEDI_ISA_DRIVERS
100 100
101if COMEDI_ISA_DRIVERS && ISA 101if COMEDI_ISA_DRIVERS && ISA
102 102
103config COMEDI_8255
104 tristate "Generic 8255 support"
105 default N
106 ---help---
107 Enable generic 8255 support.
108
109 To compile this driver as a module, choose M here: the module will be
110 called 8255.
111
112config COMEDI_ACL7225B 103config COMEDI_ACL7225B
113 tristate "ADlink NuDAQ ACL-7225b and compatibles support" 104 tristate "ADlink NuDAQ ACL-7225b and compatibles support"
114 default N 105 default N
@@ -130,6 +121,7 @@ config COMEDI_PCL711
130 121
131config COMEDI_PCL724 122config COMEDI_PCL724
132 tristate "Advantech PCL-722/724/731 and ADlink ACL-7122/7124/PET-48DIO" 123 tristate "Advantech PCL-722/724/731 and ADlink ACL-7122/7124/PET-48DIO"
124 select COMEDI_8255
133 default N 125 default N
134 ---help--- 126 ---help---
135 Enable support for Advantech PCL-724, PCL-722, PCL-731 and 127 Enable support for Advantech PCL-724, PCL-722, PCL-731 and
@@ -198,6 +190,7 @@ config COMEDI_PCL818
198 190
199config COMEDI_PCM3724 191config COMEDI_PCM3724
200 tristate "Advantech PCM-3724 PC/104 card support" 192 tristate "Advantech PCM-3724 PC/104 card support"
193 select COMEDI_8255
201 default N 194 default N
202 ---help--- 195 ---help---
203 Enable support for Advantech PCM-3724 PC/104 cards. 196 Enable support for Advantech PCM-3724 PC/104 cards.
@@ -232,18 +225,9 @@ config COMEDI_RTI802
232 To compile this driver as a module, choose M here: the module will be 225 To compile this driver as a module, choose M here: the module will be
233 called rti802. 226 called rti802.
234 227
235config COMEDI_DAS08
236 tristate "DAS-08 compatible ISA, PC/104 and PCMCIA card support"
237 default N
238 ---help---
239 Enable support for Keithley Metrabyte/ComputerBoards DAS08
240 and compatible ISA and PC/104 cards
241
242 To compile this driver as a module, choose M here: the module will be
243 called das08.
244
245config COMEDI_DAS16M1 228config COMEDI_DAS16M1
246 tristate "MeasurementComputing CIO-DAS16/M1DAS-16 ISA card support" 229 tristate "MeasurementComputing CIO-DAS16/M1DAS-16 ISA card support"
230 select COMEDI_8255
247 select COMEDI_FC 231 select COMEDI_FC
248 default N 232 default N
249 ---help--- 233 ---help---
@@ -254,6 +238,7 @@ config COMEDI_DAS16M1
254 238
255config COMEDI_DAS16 239config COMEDI_DAS16
256 tristate "DAS-16 compatible ISA and PC/104 card support" 240 tristate "DAS-16 compatible ISA and PC/104 card support"
241 select COMEDI_8255
257 select COMEDI_FC 242 select COMEDI_FC
258 default N 243 default N
259 ---help--- 244 ---help---
@@ -385,6 +370,7 @@ config COMEDI_FL512
385 370
386config COMEDI_AIO_AIO12_8 371config COMEDI_AIO_AIO12_8
387 tristate "I/O Products PC/104 AIO12-8 Analog I/O Board support" 372 tristate "I/O Products PC/104 AIO12-8 Analog I/O Board support"
373 select COMEDI_8255
388 default N 374 default N
389 ---help--- 375 ---help---
390 Enable support for I/O Products PC/104 AIO12-8 Analog I/O Board 376 Enable support for I/O Products PC/104 AIO12-8 Analog I/O Board
@@ -466,6 +452,7 @@ config COMEDI_NI_ATMIO
466config COMEDI_NI_ATMIO16D 452config COMEDI_NI_ATMIO16D
467 tristate "NI AT-MIO16/AT-MIO16D series ISA-PNP card support" 453 tristate "NI AT-MIO16/AT-MIO16D series ISA-PNP card support"
468 depends on ISAPNP && COMEDI_NI_COMMON 454 depends on ISAPNP && COMEDI_NI_COMMON
455 select COMEDI_8255
469 default N 456 default N
470 ---help--- 457 ---help---
471 Enable support for National Instruments AT-MIO16/AT-MIO16D cards. 458 Enable support for National Instruments AT-MIO16/AT-MIO16D cards.
@@ -667,6 +654,7 @@ config COMEDI_ADDI_APCI_3XXX
667 654
668config COMEDI_ADL_PCI6208 655config COMEDI_ADL_PCI6208
669 tristate "ADLink PCI-6208A support" 656 tristate "ADLink PCI-6208A support"
657 select COMEDI_8255
670 default N 658 default N
671 ---help--- 659 ---help---
672 Enable support for ADLink PCI-6208A cards 660 Enable support for ADLink PCI-6208A cards
@@ -751,6 +739,7 @@ config COMEDI_ADV_PCI1723
751 739
752config COMEDI_ADV_PCI_DIO 740config COMEDI_ADV_PCI_DIO
753 tristate "Advantech PCI DIO card support" 741 tristate "Advantech PCI DIO card support"
742 select COMEDI_8255
754 default N 743 default N
755 ---help--- 744 ---help---
756 Enable support for Advantech PCI DIO cards 745 Enable support for Advantech PCI DIO cards
@@ -762,6 +751,7 @@ config COMEDI_ADV_PCI_DIO
762 751
763config COMEDI_AMPLC_DIO200 752config COMEDI_AMPLC_DIO200
764 tristate "Amplicon PC272E and PCI272 DIO board support" 753 tristate "Amplicon PC272E and PCI272 DIO board support"
754 select COMEDI_8255
765 default N 755 default N
766 ---help--- 756 ---help---
767 Enable support for Amplicon PC272E and PCI272 DIO boards 757 Enable support for Amplicon PC272E and PCI272 DIO boards
@@ -771,6 +761,7 @@ config COMEDI_AMPLC_DIO200
771 761
772config COMEDI_AMPLC_PC236 762config COMEDI_AMPLC_PC236
773 tristate "Amplicon PC36AT and PCI236 DIO board support" 763 tristate "Amplicon PC36AT and PCI236 DIO board support"
764 select COMEDI_8255
774 default N 765 default N
775 ---help--- 766 ---help---
776 Enable support for Amplicon PC36AT and PCI236 DIO boards 767 Enable support for Amplicon PC36AT and PCI236 DIO boards
@@ -799,6 +790,7 @@ config COMEDI_AMPLC_PCI224
799 790
800config COMEDI_AMPLC_PCI230 791config COMEDI_AMPLC_PCI230
801 tristate "Amplicon PCI230 and PCI260 support" 792 tristate "Amplicon PCI230 and PCI260 support"
793 select COMEDI_8255
802 default N 794 default N
803 ---help--- 795 ---help---
804 Enable support for Amplicon PCI230 and PCI260 Multifunction I/O 796 Enable support for Amplicon PCI230 and PCI260 Multifunction I/O
@@ -869,6 +861,7 @@ config COMEDI_II_PCI20KC
869 861
870config COMEDI_DAQBOARD2000 862config COMEDI_DAQBOARD2000
871 tristate "IOtech DAQboard/2000 support" 863 tristate "IOtech DAQboard/2000 support"
864 select COMEDI_8255
872 default N 865 default N
873 ---help--- 866 ---help---
874 Enable support for the IOtech DAQboard/2000 867 Enable support for the IOtech DAQboard/2000
@@ -896,6 +889,7 @@ config COMEDI_KE_COUNTER
896 889
897config COMEDI_CB_PCIDAS64 890config COMEDI_CB_PCIDAS64
898 tristate "MeasurementComputing PCI-DAS 64xx, 60xx, and 4020 support" 891 tristate "MeasurementComputing PCI-DAS 64xx, 60xx, and 4020 support"
892 select COMEDI_8255
899 select COMEDI_FC 893 select COMEDI_FC
900 default N 894 default N
901 ---help--- 895 ---help---
@@ -907,6 +901,7 @@ config COMEDI_CB_PCIDAS64
907 901
908config COMEDI_CB_PCIDAS 902config COMEDI_CB_PCIDAS
909 tristate "MeasurementComputing PCI-DAS support" 903 tristate "MeasurementComputing PCI-DAS support"
904 select COMEDI_8255
910 select COMEDI_FC 905 select COMEDI_FC
911 default N 906 default N
912 ---help--- 907 ---help---
@@ -920,6 +915,7 @@ config COMEDI_CB_PCIDAS
920 915
921config COMEDI_CB_PCIDDA 916config COMEDI_CB_PCIDDA
922 tristate "MeasurementComputing PCI-DDA series support" 917 tristate "MeasurementComputing PCI-DDA series support"
918 select COMEDI_8255
923 default N 919 default N
924 ---help--- 920 ---help---
925 Enable support for ComputerBoards/MeasurementComputing PCI-DDA 921 Enable support for ComputerBoards/MeasurementComputing PCI-DDA
@@ -931,6 +927,7 @@ config COMEDI_CB_PCIDDA
931 927
932config COMEDI_CB_PCIDIO 928config COMEDI_CB_PCIDIO
933 tristate "MeasurementComputing PCI-DIO series support" 929 tristate "MeasurementComputing PCI-DIO series support"
930 select COMEDI_8255
934 default N 931 default N
935 ---help--- 932 ---help---
936 Enable support for ComputerBoards/MeasurementComputing PCI-DIO series 933 Enable support for ComputerBoards/MeasurementComputing PCI-DIO series
@@ -941,6 +938,7 @@ config COMEDI_CB_PCIDIO
941 938
942config COMEDI_CB_PCIMDAS 939config COMEDI_CB_PCIMDAS
943 tristate "MeasurementComputing PCIM-DAS1602/16 support" 940 tristate "MeasurementComputing PCIM-DAS1602/16 support"
941 select COMEDI_8255
944 default N 942 default N
945 ---help--- 943 ---help---
946 Enable support for ComputerBoards/MeasurementComputing PCI Migration 944 Enable support for ComputerBoards/MeasurementComputing PCI Migration
@@ -951,6 +949,7 @@ config COMEDI_CB_PCIMDAS
951 949
952config COMEDI_CB_PCIMDDA 950config COMEDI_CB_PCIMDDA
953 tristate "MeasurementComputing PCIM-DDA06-16 support" 951 tristate "MeasurementComputing PCIM-DDA06-16 support"
952 select COMEDI_8255
954 default N 953 default N
955 ---help--- 954 ---help---
956 Enable support for ComputerBoards/MeasurementComputing PCIM-DDA06-16 955 Enable support for ComputerBoards/MeasurementComputing PCIM-DDA06-16
@@ -1026,6 +1025,7 @@ config COMEDI_NI_670X
1026config COMEDI_NI_PCIDIO 1025config COMEDI_NI_PCIDIO
1027 tristate "NI PCI-DIO32HS, PCI-DIO96, PCI-6533, PCI-6503 support" 1026 tristate "NI PCI-DIO32HS, PCI-DIO96, PCI-6533, PCI-6503 support"
1028 depends on COMEDI_MITE 1027 depends on COMEDI_MITE
1028 select COMEDI_8255
1029 default N 1029 default N
1030 ---help--- 1030 ---help---
1031 Enable support for National Instruments PCI-DIO-32HS, PXI-6533, 1031 Enable support for National Instruments PCI-DIO-32HS, PXI-6533,
@@ -1058,6 +1058,7 @@ config COMEDI_NI_PCIMIO
1058 1058
1059config COMEDI_RTD520 1059config COMEDI_RTD520
1060 tristate "Real Time Devices PCI4520/DM7520 support" 1060 tristate "Real Time Devices PCI4520/DM7520 support"
1061 select COMEDI_8255
1061 default N 1062 default N
1062 ---help--- 1063 ---help---
1063 Enable support for Real Time Devices PCI4520/DM7520 1064 Enable support for Real Time Devices PCI4520/DM7520
@@ -1097,7 +1098,7 @@ endif # COMEDI_PCI_DRIVERS
1097 1098
1098menuconfig COMEDI_PCMCIA_DRIVERS 1099menuconfig COMEDI_PCMCIA_DRIVERS
1099 tristate "Comedi PCMCIA drivers" 1100 tristate "Comedi PCMCIA drivers"
1100 depends on COMEDI && PCMCIA && PCCARD 1101 depends on COMEDI && (PCMCIA || PCCARD)
1101 default N 1102 default N
1102 ---help--- 1103 ---help---
1103 Enable comedi PCMCIA and PCCARD drivers to be built 1104 Enable comedi PCMCIA and PCCARD drivers to be built
@@ -1142,6 +1143,7 @@ config COMEDI_NI_DAQ_700_CS
1142config COMEDI_NI_DAQ_DIO24_CS 1143config COMEDI_NI_DAQ_DIO24_CS
1143 tristate "NI DAQ-Card DIO-24 PCMCIA support" 1144 tristate "NI DAQ-Card DIO-24 PCMCIA support"
1144 depends on COMEDI_NI_COMMON 1145 depends on COMEDI_NI_COMMON
1146 select COMEDI_8255
1145 default N 1147 default N
1146 ---help--- 1148 ---help---
1147 Enable support for the National Instruments PCMCIA DAQ-Card DIO-24 1149 Enable support for the National Instruments PCMCIA DAQ-Card DIO-24
@@ -1162,8 +1164,8 @@ config COMEDI_NI_LABPC_CS
1162config COMEDI_NI_MIO_CS 1164config COMEDI_NI_MIO_CS
1163 tristate "NI DAQCard E series PCMCIA support" 1165 tristate "NI DAQCard E series PCMCIA support"
1164 depends on COMEDI_NI_TIO && COMEDI_NI_COMMON 1166 depends on COMEDI_NI_TIO && COMEDI_NI_COMMON
1165 default N
1166 select COMEDI_FC 1167 select COMEDI_FC
1168 default N
1167 ---help--- 1169 ---help---
1168 Enable support for the National Instruments PCMCIA DAQCard E series 1170 Enable support for the National Instruments PCMCIA DAQCard E series
1169 DAQCard-ai-16xe-50, DAQCard-ai-16e-4, DAQCard-6062E, DAQCard-6024E 1171 DAQCard-ai-16xe-50, DAQCard-ai-16e-4, DAQCard-6062E, DAQCard-6024E
@@ -1265,7 +1267,8 @@ config COMEDI_MITE
1265 1267
1266config COMEDI_NI_TIO 1268config COMEDI_NI_TIO
1267 tristate "NI general purpose counter support" 1269 tristate "NI general purpose counter support"
1268 select COMEDI_MITE 1270 depends on COMEDI_MITE
1271 select COMEDI_8255
1269 default N 1272 default N
1270 ---help--- 1273 ---help---
1271 Enable support for National Instruments general purpose counters. 1274 Enable support for National Instruments general purpose counters.
@@ -1278,6 +1281,8 @@ config COMEDI_NI_TIO
1278 1281
1279config COMEDI_NI_LABPC 1282config COMEDI_NI_LABPC
1280 tristate "NI Lab-PC and compatibles ISA and PCI support" 1283 tristate "NI Lab-PC and compatibles ISA and PCI support"
1284 depends on COMEDI_MITE
1285 select COMEDI_8255
1281 select COMEDI_FC 1286 select COMEDI_FC
1282 default N 1287 default N
1283 ---help--- 1288 ---help---
@@ -1291,8 +1296,40 @@ config COMEDI_NI_LABPC
1291 1296
1292endif # COMEDI_NI_COMMON 1297endif # COMEDI_NI_COMMON
1293 1298
1299config COMEDI_8255
1300 tristate "Generic 8255 support"
1301 depends on COMEDI
1302 default N
1303 ---help---
1304 Enable generic 8255 support.
1305
1306 You should enable compilation this driver if you plan to use a board
1307 that has an 8255 chip. For multifunction boards, the main driver will
1308 configure the 8255 subdevice automatically.
1309
1310 Note that most PCI 8255 boards do NOT work with this driver, and
1311 need a separate driver as a wrapper.
1312
1313 To compile this driver as a module, choose M here: the module will be
1314 called 8255.
1315
1316config COMEDI_DAS08
1317 tristate "DAS-08 compatible support"
1318 depends on COMEDI
1319 select COMEDI_8255
1320 default N
1321 ---help---
1322 Enable support for DAS08 and compatible ISA, PC/104 and PCI cards.
1323
1324 Note that PCMCIA DAS08 cards are not directly supported by this
1325 driver, and need a separate driver as a wrapper.
1326
1327 To compile this driver as a module, choose M here: the module will be
1328 called das08.
1329
1294config COMEDI_FC 1330config COMEDI_FC
1295 tristate "Comedi shared functions for low-level driver support" 1331 tristate "Comedi shared functions for low-level driver support"
1332 depends on COMEDI
1296 default N 1333 default N
1297 ---help--- 1334 ---help---
1298 Enable support for shared functions for low-level drivers. 1335 Enable support for shared functions for low-level drivers.
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index aced00e5cd10..aeb2c00875cd 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -83,7 +83,7 @@ static int do_subdinfo_ioctl(struct comedi_device *dev,
83static int do_chaninfo_ioctl(struct comedi_device *dev, 83static int do_chaninfo_ioctl(struct comedi_device *dev,
84 struct comedi_chaninfo __user *arg); 84 struct comedi_chaninfo __user *arg);
85static int do_bufinfo_ioctl(struct comedi_device *dev, 85static int do_bufinfo_ioctl(struct comedi_device *dev,
86 struct comedi_bufinfo __user *arg); 86 struct comedi_bufinfo __user *arg, void *file);
87static int do_cmd_ioctl(struct comedi_device *dev, 87static int do_cmd_ioctl(struct comedi_device *dev,
88 struct comedi_cmd __user *arg, void *file); 88 struct comedi_cmd __user *arg, void *file);
89static int do_lock_ioctl(struct comedi_device *dev, unsigned int arg, 89static 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,
169 break; 169 break;
170 case COMEDI_BUFINFO: 170 case COMEDI_BUFINFO:
171 rc = do_bufinfo_ioctl(dev, 171 rc = do_bufinfo_ioctl(dev,
172 (struct comedi_bufinfo __user *)arg); 172 (struct comedi_bufinfo __user *)arg,
173 file);
173 break; 174 break;
174 case COMEDI_LOCK: 175 case COMEDI_LOCK:
175 rc = do_lock_ioctl(dev, arg, file); 176 rc = do_lock_ioctl(dev, arg, file);
@@ -563,7 +564,7 @@ static int do_chaninfo_ioctl(struct comedi_device *dev,
563 564
564 */ 565 */
565static int do_bufinfo_ioctl(struct comedi_device *dev, 566static int do_bufinfo_ioctl(struct comedi_device *dev,
566 struct comedi_bufinfo __user *arg) 567 struct comedi_bufinfo __user *arg, void *file)
567{ 568{
568 struct comedi_bufinfo bi; 569 struct comedi_bufinfo bi;
569 struct comedi_subdevice *s; 570 struct comedi_subdevice *s;
@@ -576,6 +577,10 @@ static int do_bufinfo_ioctl(struct comedi_device *dev,
576 return -EINVAL; 577 return -EINVAL;
577 578
578 s = dev->subdevices + bi.subdevice; 579 s = dev->subdevices + bi.subdevice;
580
581 if (s->lock && s->lock != file)
582 return -EACCES;
583
579 async = s->async; 584 async = s->async;
580 585
581 if (!async) { 586 if (!async) {
@@ -584,8 +589,17 @@ static int do_bufinfo_ioctl(struct comedi_device *dev,
584 bi.buf_read_ptr = 0; 589 bi.buf_read_ptr = 0;
585 bi.buf_write_count = 0; 590 bi.buf_write_count = 0;
586 bi.buf_read_count = 0; 591 bi.buf_read_count = 0;
592 bi.bytes_read = 0;
593 bi.bytes_written = 0;
587 goto copyback; 594 goto copyback;
588 } 595 }
596 if (!s->busy) {
597 bi.bytes_read = 0;
598 bi.bytes_written = 0;
599 goto copyback_position;
600 }
601 if (s->busy != file)
602 return -EACCES;
589 603
590 if (bi.bytes_read && (s->subdev_flags & SDF_CMD_READ)) { 604 if (bi.bytes_read && (s->subdev_flags & SDF_CMD_READ)) {
591 bi.bytes_read = comedi_buf_read_alloc(async, bi.bytes_read); 605 bi.bytes_read = comedi_buf_read_alloc(async, bi.bytes_read);
@@ -604,6 +618,7 @@ static int do_bufinfo_ioctl(struct comedi_device *dev,
604 comedi_buf_write_free(async, bi.bytes_written); 618 comedi_buf_write_free(async, bi.bytes_written);
605 } 619 }
606 620
621copyback_position:
607 bi.buf_write_count = async->buf_write_count; 622 bi.buf_write_count = async->buf_write_count;
608 bi.buf_write_ptr = async->buf_write_ptr; 623 bi.buf_write_ptr = async->buf_write_ptr;
609 bi.buf_read_count = async->buf_read_count; 624 bi.buf_read_count = async->buf_read_count;
@@ -1576,6 +1591,19 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
1576 while (nbytes > 0 && !retval) { 1591 while (nbytes > 0 && !retval) {
1577 set_current_state(TASK_INTERRUPTIBLE); 1592 set_current_state(TASK_INTERRUPTIBLE);
1578 1593
1594 if (!(comedi_get_subdevice_runflags(s) & SRF_RUNNING)) {
1595 if (count == 0) {
1596 if (comedi_get_subdevice_runflags(s) &
1597 SRF_ERROR) {
1598 retval = -EPIPE;
1599 } else {
1600 retval = 0;
1601 }
1602 do_become_nonbusy(dev, s);
1603 }
1604 break;
1605 }
1606
1579 n = nbytes; 1607 n = nbytes;
1580 1608
1581 m = n; 1609 m = n;
@@ -1588,16 +1616,6 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
1588 n = m; 1616 n = m;
1589 1617
1590 if (n == 0) { 1618 if (n == 0) {
1591 if (!(comedi_get_subdevice_runflags(s) & SRF_RUNNING)) {
1592 if (comedi_get_subdevice_runflags(s) &
1593 SRF_ERROR) {
1594 retval = -EPIPE;
1595 } else {
1596 retval = 0;
1597 }
1598 do_become_nonbusy(dev, s);
1599 break;
1600 }
1601 if (file->f_flags & O_NONBLOCK) { 1619 if (file->f_flags & O_NONBLOCK) {
1602 retval = -EAGAIN; 1620 retval = -EAGAIN;
1603 break; 1621 break;
diff --git a/drivers/staging/comedi/drivers/Makefile b/drivers/staging/comedi/drivers/Makefile
index 5ccf246e2526..354fb7d29841 100644
--- a/drivers/staging/comedi/drivers/Makefile
+++ b/drivers/staging/comedi/drivers/Makefile
@@ -12,7 +12,6 @@ obj-$(CONFIG_COMEDI_SERIAL2002) += serial2002.o
12obj-$(CONFIG_COMEDI_SKEL) += skel.o 12obj-$(CONFIG_COMEDI_SKEL) += skel.o
13 13
14# Comedi ISA drivers 14# Comedi ISA drivers
15obj-$(CONFIG_COMEDI_8255) += 8255.o
16obj-$(CONFIG_COMEDI_ACL7225B) += acl7225b.o 15obj-$(CONFIG_COMEDI_ACL7225B) += acl7225b.o
17obj-$(CONFIG_COMEDI_PCL711) += pcl711.o 16obj-$(CONFIG_COMEDI_PCL711) += pcl711.o
18obj-$(CONFIG_COMEDI_PCL724) += pcl724.o 17obj-$(CONFIG_COMEDI_PCL724) += pcl724.o
@@ -26,7 +25,6 @@ obj-$(CONFIG_COMEDI_PCM3724) += pcm3724.o
26obj-$(CONFIG_COMEDI_PCM3730) += pcm3730.o 25obj-$(CONFIG_COMEDI_PCM3730) += pcm3730.o
27obj-$(CONFIG_COMEDI_RTI800) += rti800.o 26obj-$(CONFIG_COMEDI_RTI800) += rti800.o
28obj-$(CONFIG_COMEDI_RTI802) += rti802.o 27obj-$(CONFIG_COMEDI_RTI802) += rti802.o
29obj-$(CONFIG_COMEDI_DAS08) += das08.o
30obj-$(CONFIG_COMEDI_DAS16M1) += das16m1.o 28obj-$(CONFIG_COMEDI_DAS16M1) += das16m1.o
31obj-$(CONFIG_COMEDI_DAS16) += das16.o 29obj-$(CONFIG_COMEDI_DAS16) += das16.o
32obj-$(CONFIG_COMEDI_DAS800) += das800.o 30obj-$(CONFIG_COMEDI_DAS800) += das800.o
@@ -135,4 +133,6 @@ obj-$(CONFIG_COMEDI_NI_TIO) += ni_tio.o
135obj-$(CONFIG_COMEDI_NI_TIO) += ni_tiocmd.o 133obj-$(CONFIG_COMEDI_NI_TIO) += ni_tiocmd.o
136obj-$(CONFIG_COMEDI_NI_LABPC) += ni_labpc.o 134obj-$(CONFIG_COMEDI_NI_LABPC) += ni_labpc.o
137 135
136obj-$(CONFIG_COMEDI_8255) += 8255.o
137obj-$(CONFIG_COMEDI_DAS08) += das08.o
138obj-$(CONFIG_COMEDI_FC) += comedi_fc.o 138obj-$(CONFIG_COMEDI_FC) += comedi_fc.o
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
index 2c986413a81a..b18e81d8cf8a 100644
--- a/drivers/staging/comedi/drivers/addi-data/addi_common.c
+++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c
@@ -68,6 +68,10 @@ You should also find the complete GPL in the COPYING file accompanying this sour
68#include "addi_common.h" 68#include "addi_common.h"
69#include "addi_amcc_s5933.h" 69#include "addi_amcc_s5933.h"
70 70
71#ifndef ADDIDATA_DRIVER_NAME
72#define ADDIDATA_DRIVER_NAME "addi_common"
73#endif
74
71/* Update-0.7.57->0.7.68MODULE_AUTHOR("ADDI-DATA GmbH <info@addi-data.com>"); */ 75/* Update-0.7.57->0.7.68MODULE_AUTHOR("ADDI-DATA GmbH <info@addi-data.com>"); */
72/* Update-0.7.57->0.7.68MODULE_DESCRIPTION("Comedi ADDI-DATA module"); */ 76/* Update-0.7.57->0.7.68MODULE_DESCRIPTION("Comedi ADDI-DATA module"); */
73/* Update-0.7.57->0.7.68MODULE_LICENSE("GPL"); */ 77/* Update-0.7.57->0.7.68MODULE_LICENSE("GPL"); */
@@ -2528,7 +2532,7 @@ static const struct addi_board boardtypes[] = {
2528#define n_boardtypes (sizeof(boardtypes)/sizeof(struct addi_board)) 2532#define n_boardtypes (sizeof(boardtypes)/sizeof(struct addi_board))
2529 2533
2530static struct comedi_driver driver_addi = { 2534static struct comedi_driver driver_addi = {
2531 .driver_name = "addi_common", 2535 .driver_name = ADDIDATA_DRIVER_NAME,
2532 .module = THIS_MODULE, 2536 .module = THIS_MODULE,
2533 .attach = i_ADDI_Attach, 2537 .attach = i_ADDI_Attach,
2534 .detach = i_ADDI_Detach, 2538 .detach = i_ADDI_Detach,
@@ -2570,10 +2574,6 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
2570 struct pcilst_struct *card = NULL; 2574 struct pcilst_struct *card = NULL;
2571 unsigned char pci_bus, pci_slot, pci_func; 2575 unsigned char pci_bus, pci_slot, pci_func;
2572 int i_Dma = 0; 2576 int i_Dma = 0;
2573 static char c_Identifier[150];
2574
2575 sprintf(c_Identifier, "Addi-Data GmbH Comedi %s",
2576 this_board->pc_DriverName);
2577 2577
2578 ret = alloc_private(dev, sizeof(struct addi_private)); 2578 ret = alloc_private(dev, sizeof(struct addi_private));
2579 if (ret < 0) 2579 if (ret < 0)
@@ -2583,7 +2583,7 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
2583 v_pci_card_list_init(this_board->i_VendorId, 1); /* 1 for displaying the list.. */ 2583 v_pci_card_list_init(this_board->i_VendorId, 1); /* 1 for displaying the list.. */
2584 pci_list_builded = 1; 2584 pci_list_builded = 1;
2585 } 2585 }
2586 /* printk("comedi%d: addi_common: board=%s",dev->minor,this_board->pc_DriverName); */ 2586 /* printk("comedi%d: "ADDIDATA_DRIVER_NAME": board=%s",dev->minor,this_board->pc_DriverName); */
2587 2587
2588 if ((this_board->i_Dma) && (it->options[2] == 0)) { 2588 if ((this_board->i_Dma) && (it->options[2] == 0)) {
2589 i_Dma = 1; 2589 i_Dma = 1;
@@ -2648,7 +2648,7 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
2648 2648
2649 if (irq > 0) { 2649 if (irq > 0) {
2650 if (request_irq(irq, v_ADDI_Interrupt, IRQF_SHARED, 2650 if (request_irq(irq, v_ADDI_Interrupt, IRQF_SHARED,
2651 c_Identifier, dev) < 0) { 2651 this_board->pc_DriverName, dev) < 0) {
2652 printk(", unable to allocate IRQ %u, DISABLING IT", 2652 printk(", unable to allocate IRQ %u, DISABLING IT",
2653 irq); 2653 irq);
2654 irq = 0; /* Can't use IRQ */ 2654 irq = 0; /* Can't use IRQ */
diff --git a/drivers/staging/comedi/drivers/addi_apci_035.c b/drivers/staging/comedi/drivers/addi_apci_035.c
index da454e854c4c..6dfcbe803f2d 100644
--- a/drivers/staging/comedi/drivers/addi_apci_035.c
+++ b/drivers/staging/comedi/drivers/addi_apci_035.c
@@ -2,4 +2,6 @@
2 2
3#define ADDIDATA_WATCHDOG 2 /* Or shold it be something else */ 3#define ADDIDATA_WATCHDOG 2 /* Or shold it be something else */
4 4
5#define ADDIDATA_DRIVER_NAME "addi_apci_035"
6
5#include "addi-data/addi_common.c" 7#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_1032.c b/drivers/staging/comedi/drivers/addi_apci_1032.c
index fa2056e8aa0e..4722ec834f7b 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1032.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1032.c
@@ -1,3 +1,5 @@
1#define CONFIG_APCI_1032 1 1#define CONFIG_APCI_1032 1
2 2
3#define ADDIDATA_DRIVER_NAME "addi_apci_1032"
4
3#include "addi-data/addi_common.c" 5#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c
index 7a5cae599ef8..db3dafdcf691 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1500.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1500.c
@@ -1,3 +1,5 @@
1#define CONFIG_APCI_1500 1 1#define CONFIG_APCI_1500 1
2 2
3#define ADDIDATA_DRIVER_NAME "addi_apci_1500"
4
3#include "addi-data/addi_common.c" 5#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_1516.c b/drivers/staging/comedi/drivers/addi_apci_1516.c
index 8d414844009f..f591baff6a0b 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1516.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1516.c
@@ -1,3 +1,5 @@
1#define CONFIG_APCI_1516 1 1#define CONFIG_APCI_1516 1
2 2
3#define ADDIDATA_DRIVER_NAME "addi_apci_1516"
4
3#include "addi-data/addi_common.c" 5#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_1564.c b/drivers/staging/comedi/drivers/addi_apci_1564.c
index 0351cdde1026..6f5c923ac226 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1564.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1564.c
@@ -1,3 +1,5 @@
1#define CONFIG_APCI_1564 1 1#define CONFIG_APCI_1564 1
2 2
3#define ADDIDATA_DRIVER_NAME "addi_apci_1564"
4
3#include "addi-data/addi_common.c" 5#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_16xx.c b/drivers/staging/comedi/drivers/addi_apci_16xx.c
index 506799041294..1d926add9e6d 100644
--- a/drivers/staging/comedi/drivers/addi_apci_16xx.c
+++ b/drivers/staging/comedi/drivers/addi_apci_16xx.c
@@ -1,3 +1,5 @@
1#define CONFIG_APCI_16XX 1 1#define CONFIG_APCI_16XX 1
2 2
3#define ADDIDATA_DRIVER_NAME "addi_apci_16xx"
4
3#include "addi-data/addi_common.c" 5#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_1710.c b/drivers/staging/comedi/drivers/addi_apci_1710.c
index c433445913dd..df6ba8ccf56f 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1710.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1710.c
@@ -1,3 +1,5 @@
1#define CONFIG_APCI_1710 1 1#define CONFIG_APCI_1710 1
2 2
3#define ADDIDATA_DRIVER_NAME "addi_apci_1710"
4
3#include "addi-data/addi_common.c" 5#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_2016.c b/drivers/staging/comedi/drivers/addi_apci_2016.c
index 271c47c8cad3..7266e412f0a6 100644
--- a/drivers/staging/comedi/drivers/addi_apci_2016.c
+++ b/drivers/staging/comedi/drivers/addi_apci_2016.c
@@ -1,3 +1,5 @@
1#define CONFIG_APCI_2016 1 1#define CONFIG_APCI_2016 1
2 2
3#define ADDIDATA_DRIVER_NAME "addi_apci_2016"
4
3#include "addi-data/addi_common.c" 5#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_2032.c b/drivers/staging/comedi/drivers/addi_apci_2032.c
index 5108ea2a3924..f67da94119e8 100644
--- a/drivers/staging/comedi/drivers/addi_apci_2032.c
+++ b/drivers/staging/comedi/drivers/addi_apci_2032.c
@@ -1,3 +1,5 @@
1#define CONFIG_APCI_2032 1 1#define CONFIG_APCI_2032 1
2 2
3#define ADDIDATA_DRIVER_NAME "addi_apci_2032"
4
3#include "addi-data/addi_common.c" 5#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_2200.c b/drivers/staging/comedi/drivers/addi_apci_2200.c
index e439f835cf4f..bc7f7d653503 100644
--- a/drivers/staging/comedi/drivers/addi_apci_2200.c
+++ b/drivers/staging/comedi/drivers/addi_apci_2200.c
@@ -1,3 +1,5 @@
1#define CONFIG_APCI_2200 1 1#define CONFIG_APCI_2200 1
2 2
3#define ADDIDATA_DRIVER_NAME "addi_apci_2200"
4
3#include "addi-data/addi_common.c" 5#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_3001.c b/drivers/staging/comedi/drivers/addi_apci_3001.c
index df97c305828b..d86c4209cb90 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3001.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3001.c
@@ -1,3 +1,5 @@
1#define CONFIG_APCI_3001 1 1#define CONFIG_APCI_3001 1
2 2
3#define ADDIDATA_DRIVER_NAME "addi_apci_3001"
4
3#include "addi-data/addi_common.c" 5#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_3120.c b/drivers/staging/comedi/drivers/addi_apci_3120.c
index 9183125ddde4..0b22cf10415d 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3120.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3120.c
@@ -1,3 +1,5 @@
1#define CONFIG_APCI_3120 1 1#define CONFIG_APCI_3120 1
2 2
3#define ADDIDATA_DRIVER_NAME "addi_apci_3120"
4
3#include "addi-data/addi_common.c" 5#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_3200.c b/drivers/staging/comedi/drivers/addi_apci_3200.c
index f25a70b3290b..159313997dcf 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3200.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3200.c
@@ -1,3 +1,5 @@
1#define CONFIG_APCI_3200 1 1#define CONFIG_APCI_3200 1
2 2
3#define ADDIDATA_DRIVER_NAME "addi_apci_3200"
4
3#include "addi-data/addi_common.c" 5#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_3300.c b/drivers/staging/comedi/drivers/addi_apci_3300.c
index 1ee4778ad45b..733c69abc43a 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3300.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3300.c
@@ -1,3 +1,5 @@
1#define CONFIG_APCI_3300 1 1#define CONFIG_APCI_3300 1
2 2
3#define ADDIDATA_DRIVER_NAME "addi_apci_3300"
4
3#include "addi-data/addi_common.c" 5#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_3501.c b/drivers/staging/comedi/drivers/addi_apci_3501.c
index 1049e20237e8..d8a01b154e35 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3501.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3501.c
@@ -1,3 +1,5 @@
1#define CONFIG_APCI_3501 1 1#define CONFIG_APCI_3501 1
2 2
3#define ADDIDATA_DRIVER_NAME "addi_apci_3501"
4
3#include "addi-data/addi_common.c" 5#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/addi_apci_3xxx.c b/drivers/staging/comedi/drivers/addi_apci_3xxx.c
index fb9deb7083bd..942bc9e259a8 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3xxx.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3xxx.c
@@ -1,3 +1,5 @@
1#define CONFIG_APCI_3XXX 1 1#define CONFIG_APCI_3XXX 1
2 2
3#define ADDIDATA_DRIVER_NAME "addi_apci_3xxx"
4
3#include "addi-data/addi_common.c" 5#include "addi-data/addi_common.c"
diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c
index 40eeecf5347f..e424a0c7d34f 100644
--- a/drivers/staging/comedi/drivers/adv_pci_dio.c
+++ b/drivers/staging/comedi/drivers/adv_pci_dio.c
@@ -7,17 +7,17 @@
7*/ 7*/
8/* 8/*
9Driver: adv_pci_dio 9Driver: adv_pci_dio
10Description: Advantech PCI-1730, PCI-1733, PCI-1734, PCI-1736UP, 10Description: Advantech PCI-1730, PCI-1733, PCI-1734, PCI-1735U,
11 PCI-1750, PCI-1751, PCI-1752, PCI-1753/E, PCI-1754, 11 PCI-1736UP, PCI-1750, PCI-1751, PCI-1752, PCI-1753/E,
12 PCI-1756, PCI-1762 12 PCI-1754, PCI-1756, PCI-1762
13Author: Michal Dobes <dobes@tesnet.cz> 13Author: Michal Dobes <dobes@tesnet.cz>
14Devices: [Advantech] PCI-1730 (adv_pci_dio), PCI-1733, 14Devices: [Advantech] PCI-1730 (adv_pci_dio), PCI-1733,
15 PCI-1734, PCI-1736UP, PCI-1750, 15 PCI-1734, PCI-1735U, PCI-1736UP, PCI-1750,
16 PCI-1751, PCI-1752, PCI-1753, 16 PCI-1751, PCI-1752, PCI-1753,
17 PCI-1753+PCI-1753E, PCI-1754, PCI-1756, 17 PCI-1753+PCI-1753E, PCI-1754, PCI-1756,
18 PCI-1760, PCI-1762 18 PCI-1760, PCI-1762
19Status: untested 19Status: untested
20Updated: Mon, 14 Apr 2008 10:43:08 +0100 20Updated: Tue, 04 May 2010 13:00:00 +0000
21 21
22This driver supports now only insn interface for DI/DO/DIO. 22This driver supports now only insn interface for DI/DO/DIO.
23 23
@@ -35,6 +35,7 @@ Configuration options:
35 35
36#include "comedi_pci.h" 36#include "comedi_pci.h"
37#include "8255.h" 37#include "8255.h"
38#include "8253.h"
38 39
39#undef PCI_DIO_EXTDEBUG /* if defined, enable extensive debug logging */ 40#undef PCI_DIO_EXTDEBUG /* if defined, enable extensive debug logging */
40 41
@@ -49,7 +50,7 @@ Configuration options:
49 50
50/* hardware types of the cards */ 51/* hardware types of the cards */
51enum hw_cards_id { 52enum hw_cards_id {
52 TYPE_PCI1730, TYPE_PCI1733, TYPE_PCI1734, TYPE_PCI1736, 53 TYPE_PCI1730, TYPE_PCI1733, TYPE_PCI1734, TYPE_PCI1735, TYPE_PCI1736,
53 TYPE_PCI1750, 54 TYPE_PCI1750,
54 TYPE_PCI1751, 55 TYPE_PCI1751,
55 TYPE_PCI1752, 56 TYPE_PCI1752,
@@ -67,7 +68,10 @@ enum hw_io_access {
67#define MAX_DI_SUBDEVS 2 /* max number of DI subdevices per card */ 68#define MAX_DI_SUBDEVS 2 /* max number of DI subdevices per card */
68#define MAX_DO_SUBDEVS 2 /* max number of DO subdevices per card */ 69#define MAX_DO_SUBDEVS 2 /* max number of DO subdevices per card */
69#define MAX_DIO_SUBDEVG 2 /* max number of DIO subdevices group per card */ 70#define MAX_DIO_SUBDEVG 2 /* max number of DIO subdevices group per card */
71#define MAX_8254_SUBDEVS 1 /* max number of 8254 counter subdevs per card */
72 /* (could be more than one 8254 per subdevice) */
70 73
74#define SIZE_8254 4 /* 8254 IO space length */
71#define SIZE_8255 4 /* 8255 IO space length */ 75#define SIZE_8255 4 /* 8255 IO space length */
72 76
73#define PCIDIO_MAINREG 2 /* main I/O region for all Advantech cards? */ 77#define PCIDIO_MAINREG 2 /* main I/O region for all Advantech cards? */
@@ -85,6 +89,12 @@ enum hw_io_access {
85#define PCI1734_IDO 0 /* W: Isolated digital output 0-31 */ 89#define PCI1734_IDO 0 /* W: Isolated digital output 0-31 */
86#define PCI173x_BOARDID 4 /* R: Board I/D switch for 1730/3/4 */ 90#define PCI173x_BOARDID 4 /* R: Board I/D switch for 1730/3/4 */
87 91
92/* Advantech PCI-1735U */
93#define PCI1735_DI 0 /* R: Digital input 0-31 */
94#define PCI1735_DO 0 /* W: Digital output 0-31 */
95#define PCI1735_C8254 4 /* R/W: 8254 counter */
96#define PCI1735_BOARDID 8 /* R: Board I/D switch for 1735U */
97
88/* Advantech PCI-1736UP */ 98/* Advantech PCI-1736UP */
89#define PCI1736_IDI 0 /* R: Isolated digital input 0-15 */ 99#define PCI1736_IDI 0 /* R: Isolated digital input 0-15 */
90#define PCI1736_IDO 0 /* W: Isolated digital output 0-15 */ 100#define PCI1736_IDO 0 /* W: Isolated digital output 0-15 */
@@ -192,7 +202,8 @@ static int pci_dio_detach(struct comedi_device *dev);
192struct diosubd_data { 202struct diosubd_data {
193 int chans; /* num of chans */ 203 int chans; /* num of chans */
194 int addr; /* PCI address ofset */ 204 int addr; /* PCI address ofset */
195 int regs; /* number of registers to read or 8255 subdevices */ 205 int regs; /* number of registers to read or 8255
206 subdevices or 8254 chips */
196 unsigned int specflags; /* addon subdevice flags */ 207 unsigned int specflags; /* addon subdevice flags */
197}; 208};
198 209
@@ -206,6 +217,7 @@ struct dio_boardtype {
206 struct diosubd_data sdo[MAX_DO_SUBDEVS]; /* DO chans */ 217 struct diosubd_data sdo[MAX_DO_SUBDEVS]; /* DO chans */
207 struct diosubd_data sdio[MAX_DIO_SUBDEVG]; /* DIO 8255 chans */ 218 struct diosubd_data sdio[MAX_DIO_SUBDEVG]; /* DIO 8255 chans */
208 struct diosubd_data boardid; /* card supports board ID switch */ 219 struct diosubd_data boardid; /* card supports board ID switch */
220 struct diosubd_data s8254[MAX_8254_SUBDEVS]; /* 8254 subdevices */
209 enum hw_io_access io_access; 221 enum hw_io_access io_access;
210}; 222};
211 223
@@ -214,6 +226,7 @@ static DEFINE_PCI_DEVICE_TABLE(pci_dio_pci_table) = {
214 PCI_VENDOR_ID_ADVANTECH, 0x1730, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 226 PCI_VENDOR_ID_ADVANTECH, 0x1730, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
215 PCI_VENDOR_ID_ADVANTECH, 0x1733, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 227 PCI_VENDOR_ID_ADVANTECH, 0x1733, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
216 PCI_VENDOR_ID_ADVANTECH, 0x1734, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 228 PCI_VENDOR_ID_ADVANTECH, 0x1734, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
229 PCI_VENDOR_ID_ADVANTECH, 0x1735, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
217 PCI_VENDOR_ID_ADVANTECH, 0x1736, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 230 PCI_VENDOR_ID_ADVANTECH, 0x1736, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
218 PCI_VENDOR_ID_ADVANTECH, 0x1750, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 231 PCI_VENDOR_ID_ADVANTECH, 0x1750, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
219 PCI_VENDOR_ID_ADVANTECH, 0x1751, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 232 PCI_VENDOR_ID_ADVANTECH, 0x1751, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
@@ -235,14 +248,15 @@ static const struct dio_boardtype boardtypes[] = {
235 {{16, PCI1730_DO, 2, 0}, {16, PCI1730_IDO, 2, 0}}, 248 {{16, PCI1730_DO, 2, 0}, {16, PCI1730_IDO, 2, 0}},
236 {{0, 0, 0, 0}, {0, 0, 0, 0}}, 249 {{0, 0, 0, 0}, {0, 0, 0, 0}},
237 {4, PCI173x_BOARDID, 1, SDF_INTERNAL}, 250 {4, PCI173x_BOARDID, 1, SDF_INTERNAL},
238 IO_8b, 251 {{0, 0, 0, 0}},
239 }, 252 IO_8b},
240 {"pci1733", PCI_VENDOR_ID_ADVANTECH, 0x1733, PCIDIO_MAINREG, 253 {"pci1733", PCI_VENDOR_ID_ADVANTECH, 0x1733, PCIDIO_MAINREG,
241 TYPE_PCI1733, 254 TYPE_PCI1733,
242 {{0, 0, 0, 0}, {32, PCI1733_IDI, 4, 0}}, 255 {{0, 0, 0, 0}, {32, PCI1733_IDI, 4, 0}},
243 {{0, 0, 0, 0}, {0, 0, 0, 0}}, 256 {{0, 0, 0, 0}, {0, 0, 0, 0}},
244 {{0, 0, 0, 0}, {0, 0, 0, 0}}, 257 {{0, 0, 0, 0}, {0, 0, 0, 0}},
245 {4, PCI173x_BOARDID, 1, SDF_INTERNAL}, 258 {4, PCI173x_BOARDID, 1, SDF_INTERNAL},
259 {{0, 0, 0, 0}},
246 IO_8b}, 260 IO_8b},
247 {"pci1734", PCI_VENDOR_ID_ADVANTECH, 0x1734, PCIDIO_MAINREG, 261 {"pci1734", PCI_VENDOR_ID_ADVANTECH, 0x1734, PCIDIO_MAINREG,
248 TYPE_PCI1734, 262 TYPE_PCI1734,
@@ -250,6 +264,15 @@ static const struct dio_boardtype boardtypes[] = {
250 {{0, 0, 0, 0}, {32, PCI1734_IDO, 4, 0}}, 264 {{0, 0, 0, 0}, {32, PCI1734_IDO, 4, 0}},
251 {{0, 0, 0, 0}, {0, 0, 0, 0}}, 265 {{0, 0, 0, 0}, {0, 0, 0, 0}},
252 {4, PCI173x_BOARDID, 1, SDF_INTERNAL}, 266 {4, PCI173x_BOARDID, 1, SDF_INTERNAL},
267 {{0, 0, 0, 0}},
268 IO_8b},
269 {"pci1735", PCI_VENDOR_ID_ADVANTECH, 0x1735, PCIDIO_MAINREG,
270 TYPE_PCI1735,
271 {{32, PCI1735_DI, 4, 0}, {0, 0, 0, 0}},
272 {{32, PCI1735_DO, 4, 0}, {0, 0, 0, 0}},
273 {{0, 0, 0, 0}, {0, 0, 0, 0}},
274 { 4, PCI1735_BOARDID, 1, SDF_INTERNAL},
275 {{3, PCI1735_C8254, 1, 0}},
253 IO_8b}, 276 IO_8b},
254 {"pci1736", PCI_VENDOR_ID_ADVANTECH, 0x1736, PCI1736_MAINREG, 277 {"pci1736", PCI_VENDOR_ID_ADVANTECH, 0x1736, PCI1736_MAINREG,
255 TYPE_PCI1736, 278 TYPE_PCI1736,
@@ -257,14 +280,15 @@ static const struct dio_boardtype boardtypes[] = {
257 {{0, 0, 0, 0}, {16, PCI1736_IDO, 2, 0}}, 280 {{0, 0, 0, 0}, {16, PCI1736_IDO, 2, 0}},
258 {{0, 0, 0, 0}, {0, 0, 0, 0}}, 281 {{0, 0, 0, 0}, {0, 0, 0, 0}},
259 {4, PCI1736_BOARDID, 1, SDF_INTERNAL}, 282 {4, PCI1736_BOARDID, 1, SDF_INTERNAL},
260 IO_8b, 283 {{0, 0, 0, 0}},
261 }, 284 IO_8b},
262 {"pci1750", PCI_VENDOR_ID_ADVANTECH, 0x1750, PCIDIO_MAINREG, 285 {"pci1750", PCI_VENDOR_ID_ADVANTECH, 0x1750, PCIDIO_MAINREG,
263 TYPE_PCI1750, 286 TYPE_PCI1750,
264 {{0, 0, 0, 0}, {16, PCI1750_IDI, 2, 0}}, 287 {{0, 0, 0, 0}, {16, PCI1750_IDI, 2, 0}},
265 {{0, 0, 0, 0}, {16, PCI1750_IDO, 2, 0}}, 288 {{0, 0, 0, 0}, {16, PCI1750_IDO, 2, 0}},
266 {{0, 0, 0, 0}, {0, 0, 0, 0}}, 289 {{0, 0, 0, 0}, {0, 0, 0, 0}},
267 {0, 0, 0, 0}, 290 {0, 0, 0, 0},
291 {{0, 0, 0, 0}},
268 IO_8b}, 292 IO_8b},
269 {"pci1751", PCI_VENDOR_ID_ADVANTECH, 0x1751, PCIDIO_MAINREG, 293 {"pci1751", PCI_VENDOR_ID_ADVANTECH, 0x1751, PCIDIO_MAINREG,
270 TYPE_PCI1751, 294 TYPE_PCI1751,
@@ -272,6 +296,7 @@ static const struct dio_boardtype boardtypes[] = {
272 {{0, 0, 0, 0}, {0, 0, 0, 0}}, 296 {{0, 0, 0, 0}, {0, 0, 0, 0}},
273 {{48, PCI1751_DIO, 2, 0}, {0, 0, 0, 0}}, 297 {{48, PCI1751_DIO, 2, 0}, {0, 0, 0, 0}},
274 {0, 0, 0, 0}, 298 {0, 0, 0, 0},
299 {{0, 0, 0, 0}},
275 IO_8b}, 300 IO_8b},
276 {"pci1752", PCI_VENDOR_ID_ADVANTECH, 0x1752, PCIDIO_MAINREG, 301 {"pci1752", PCI_VENDOR_ID_ADVANTECH, 0x1752, PCIDIO_MAINREG,
277 TYPE_PCI1752, 302 TYPE_PCI1752,
@@ -279,6 +304,7 @@ static const struct dio_boardtype boardtypes[] = {
279 {{32, PCI1752_IDO, 2, 0}, {32, PCI1752_IDO2, 2, 0}}, 304 {{32, PCI1752_IDO, 2, 0}, {32, PCI1752_IDO2, 2, 0}},
280 {{0, 0, 0, 0}, {0, 0, 0, 0}}, 305 {{0, 0, 0, 0}, {0, 0, 0, 0}},
281 {4, PCI175x_BOARDID, 1, SDF_INTERNAL}, 306 {4, PCI175x_BOARDID, 1, SDF_INTERNAL},
307 {{0, 0, 0, 0}},
282 IO_16b}, 308 IO_16b},
283 {"pci1753", PCI_VENDOR_ID_ADVANTECH, 0x1753, PCIDIO_MAINREG, 309 {"pci1753", PCI_VENDOR_ID_ADVANTECH, 0x1753, PCIDIO_MAINREG,
284 TYPE_PCI1753, 310 TYPE_PCI1753,
@@ -286,6 +312,7 @@ static const struct dio_boardtype boardtypes[] = {
286 {{0, 0, 0, 0}, {0, 0, 0, 0}}, 312 {{0, 0, 0, 0}, {0, 0, 0, 0}},
287 {{96, PCI1753_DIO, 4, 0}, {0, 0, 0, 0}}, 313 {{96, PCI1753_DIO, 4, 0}, {0, 0, 0, 0}},
288 {0, 0, 0, 0}, 314 {0, 0, 0, 0},
315 {{0, 0, 0, 0}},
289 IO_8b}, 316 IO_8b},
290 {"pci1753e", PCI_VENDOR_ID_ADVANTECH, 0x1753, PCIDIO_MAINREG, 317 {"pci1753e", PCI_VENDOR_ID_ADVANTECH, 0x1753, PCIDIO_MAINREG,
291 TYPE_PCI1753E, 318 TYPE_PCI1753E,
@@ -293,6 +320,7 @@ static const struct dio_boardtype boardtypes[] = {
293 {{0, 0, 0, 0}, {0, 0, 0, 0}}, 320 {{0, 0, 0, 0}, {0, 0, 0, 0}},
294 {{96, PCI1753_DIO, 4, 0}, {96, PCI1753E_DIO, 4, 0}}, 321 {{96, PCI1753_DIO, 4, 0}, {96, PCI1753E_DIO, 4, 0}},
295 {0, 0, 0, 0}, 322 {0, 0, 0, 0},
323 {{0, 0, 0, 0}},
296 IO_8b}, 324 IO_8b},
297 {"pci1754", PCI_VENDOR_ID_ADVANTECH, 0x1754, PCIDIO_MAINREG, 325 {"pci1754", PCI_VENDOR_ID_ADVANTECH, 0x1754, PCIDIO_MAINREG,
298 TYPE_PCI1754, 326 TYPE_PCI1754,
@@ -300,6 +328,7 @@ static const struct dio_boardtype boardtypes[] = {
300 {{0, 0, 0, 0}, {0, 0, 0, 0}}, 328 {{0, 0, 0, 0}, {0, 0, 0, 0}},
301 {{0, 0, 0, 0}, {0, 0, 0, 0}}, 329 {{0, 0, 0, 0}, {0, 0, 0, 0}},
302 {4, PCI175x_BOARDID, 1, SDF_INTERNAL}, 330 {4, PCI175x_BOARDID, 1, SDF_INTERNAL},
331 {{0, 0, 0, 0}},
303 IO_16b}, 332 IO_16b},
304 {"pci1756", PCI_VENDOR_ID_ADVANTECH, 0x1756, PCIDIO_MAINREG, 333 {"pci1756", PCI_VENDOR_ID_ADVANTECH, 0x1756, PCIDIO_MAINREG,
305 TYPE_PCI1756, 334 TYPE_PCI1756,
@@ -307,6 +336,7 @@ static const struct dio_boardtype boardtypes[] = {
307 {{0, 0, 0, 0}, {32, PCI1756_IDO, 2, 0}}, 336 {{0, 0, 0, 0}, {32, PCI1756_IDO, 2, 0}},
308 {{0, 0, 0, 0}, {0, 0, 0, 0}}, 337 {{0, 0, 0, 0}, {0, 0, 0, 0}},
309 {4, PCI175x_BOARDID, 1, SDF_INTERNAL}, 338 {4, PCI175x_BOARDID, 1, SDF_INTERNAL},
339 {{0, 0, 0, 0}},
310 IO_16b}, 340 IO_16b},
311 {"pci1760", PCI_VENDOR_ID_ADVANTECH, 0x1760, 0, 341 {"pci1760", PCI_VENDOR_ID_ADVANTECH, 0x1760, 0,
312 TYPE_PCI1760, 342 TYPE_PCI1760,
@@ -314,6 +344,7 @@ static const struct dio_boardtype boardtypes[] = {
314 {{0, 0, 0, 0}, {0, 0, 0, 0}}, 344 {{0, 0, 0, 0}, {0, 0, 0, 0}},
315 {{0, 0, 0, 0}, {0, 0, 0, 0}}, 345 {{0, 0, 0, 0}, {0, 0, 0, 0}},
316 {0, 0, 0, 0}, 346 {0, 0, 0, 0},
347 {{0, 0, 0, 0}},
317 IO_8b}, 348 IO_8b},
318 {"pci1762", PCI_VENDOR_ID_ADVANTECH, 0x1762, PCIDIO_MAINREG, 349 {"pci1762", PCI_VENDOR_ID_ADVANTECH, 0x1762, PCIDIO_MAINREG,
319 TYPE_PCI1762, 350 TYPE_PCI1762,
@@ -321,6 +352,7 @@ static const struct dio_boardtype boardtypes[] = {
321 {{0, 0, 0, 0}, {16, PCI1762_RO, 1, 0}}, 352 {{0, 0, 0, 0}, {16, PCI1762_RO, 1, 0}},
322 {{0, 0, 0, 0}, {0, 0, 0, 0}}, 353 {{0, 0, 0, 0}, {0, 0, 0, 0}},
323 {4, PCI1762_BOARDID, 1, SDF_INTERNAL}, 354 {4, PCI1762_BOARDID, 1, SDF_INTERNAL},
355 {{0, 0, 0, 0}},
324 IO_16b} 356 IO_16b}
325}; 357};
326 358
@@ -440,6 +472,83 @@ static int pci_dio_insn_bits_do_w(struct comedi_device *dev,
440/* 472/*
441============================================================================== 473==============================================================================
442*/ 474*/
475static int pci_8254_insn_read(struct comedi_device *dev,
476 struct comedi_subdevice *s,
477 struct comedi_insn *insn, unsigned int *data)
478{
479 const struct diosubd_data *d = (const struct diosubd_data *)s->private;
480 unsigned int chan, chip, chipchan;
481 unsigned long flags;
482
483 chan = CR_CHAN(insn->chanspec); /* channel on subdevice */
484 chip = chan / 3; /* chip on subdevice */
485 chipchan = chan - (3 * chip); /* channel on chip on subdevice */
486 spin_lock_irqsave(&s->spin_lock, flags);
487 data[0] = i8254_read(dev->iobase + d->addr + (SIZE_8254 * chip),
488 0, chipchan);
489 spin_unlock_irqrestore(&s->spin_lock, flags);
490 return 1;
491}
492
493/*
494==============================================================================
495*/
496static int pci_8254_insn_write(struct comedi_device *dev,
497 struct comedi_subdevice *s,
498 struct comedi_insn *insn, unsigned int *data)
499{
500 const struct diosubd_data *d = (const struct diosubd_data *)s->private;
501 unsigned int chan, chip, chipchan;
502 unsigned long flags;
503
504 chan = CR_CHAN(insn->chanspec); /* channel on subdevice */
505 chip = chan / 3; /* chip on subdevice */
506 chipchan = chan - (3 * chip); /* channel on chip on subdevice */
507 spin_lock_irqsave(&s->spin_lock, flags);
508 i8254_write(dev->iobase + d->addr + (SIZE_8254 * chip),
509 0, chipchan, data[0]);
510 spin_unlock_irqrestore(&s->spin_lock, flags);
511 return 1;
512}
513
514/*
515==============================================================================
516*/
517static int pci_8254_insn_config(struct comedi_device *dev,
518 struct comedi_subdevice *s,
519 struct comedi_insn *insn, unsigned int *data)
520{
521 const struct diosubd_data *d = (const struct diosubd_data *)s->private;
522 unsigned int chan, chip, chipchan;
523 unsigned long iobase;
524 int ret = 0;
525 unsigned long flags;
526
527 chan = CR_CHAN(insn->chanspec); /* channel on subdevice */
528 chip = chan / 3; /* chip on subdevice */
529 chipchan = chan - (3 * chip); /* channel on chip on subdevice */
530 iobase = dev->iobase + d->addr + (SIZE_8254 * chip);
531 spin_lock_irqsave(&s->spin_lock, flags);
532 switch (data[0]) {
533 case INSN_CONFIG_SET_COUNTER_MODE:
534 ret = i8254_set_mode(iobase, 0, chipchan, data[1]);
535 if (ret < 0)
536 ret = -EINVAL;
537 break;
538 case INSN_CONFIG_8254_READ_STATUS:
539 data[1] = i8254_status(iobase, 0, chipchan);
540 break;
541 default:
542 ret = -EINVAL;
543 break;
544 }
545 spin_unlock_irqrestore(&s->spin_lock, flags);
546 return ret < 0 ? ret : insn->n;
547}
548
549/*
550==============================================================================
551*/
443static int pci1760_unchecked_mbxrequest(struct comedi_device *dev, 552static int pci1760_unchecked_mbxrequest(struct comedi_device *dev,
444 unsigned char *omb, unsigned char *imb, 553 unsigned char *omb, unsigned char *imb,
445 int repeats) 554 int repeats)
@@ -708,6 +817,15 @@ static int pci_dio_reset(struct comedi_device *dev)
708 outb(0, dev->iobase + PCI1734_IDO + 2); 817 outb(0, dev->iobase + PCI1734_IDO + 2);
709 outb(0, dev->iobase + PCI1734_IDO + 3); 818 outb(0, dev->iobase + PCI1734_IDO + 3);
710 break; 819 break;
820 case TYPE_PCI1735:
821 outb(0, dev->iobase + PCI1735_DO); /* clear outputs */
822 outb(0, dev->iobase + PCI1735_DO + 1);
823 outb(0, dev->iobase + PCI1735_DO + 2);
824 outb(0, dev->iobase + PCI1735_DO + 3);
825 i8254_set_mode(dev->iobase + PCI1735_C8254, 0, 0, I8254_MODE0);
826 i8254_set_mode(dev->iobase + PCI1735_C8254, 0, 1, I8254_MODE0);
827 i8254_set_mode(dev->iobase + PCI1735_C8254, 0, 2, I8254_MODE0);
828 break;
711 829
712 case TYPE_PCI1736: 830 case TYPE_PCI1736:
713 outb(0, dev->iobase + PCI1736_IDO); 831 outb(0, dev->iobase + PCI1736_IDO);
@@ -877,6 +995,26 @@ static int pci_dio_add_do(struct comedi_device *dev, struct comedi_subdevice *s,
877/* 995/*
878============================================================================== 996==============================================================================
879*/ 997*/
998static int pci_dio_add_8254(struct comedi_device *dev,
999 struct comedi_subdevice * s,
1000 const struct diosubd_data *d, int subdev)
1001{
1002 s->type = COMEDI_SUBD_COUNTER;
1003 s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
1004 s->n_chan = d->chans;
1005 s->maxdata = 65535;
1006 s->len_chanlist = d->chans;
1007 s->insn_read = pci_8254_insn_read;
1008 s->insn_write = pci_8254_insn_write;
1009 s->insn_config = pci_8254_insn_config;
1010 s->private = (void *)d;
1011
1012 return 0;
1013}
1014
1015/*
1016==============================================================================
1017*/
880static int CheckAndAllocCard(struct comedi_device *dev, 1018static int CheckAndAllocCard(struct comedi_device *dev,
881 struct comedi_devconfig *it, 1019 struct comedi_devconfig *it,
882 struct pci_dev *pcidev) 1020 struct pci_dev *pcidev)
@@ -979,6 +1117,9 @@ static int pci_dio_attach(struct comedi_device *dev,
979 n_subdevices += this_board->sdio[i].regs; 1117 n_subdevices += this_board->sdio[i].regs;
980 if (this_board->boardid.chans) 1118 if (this_board->boardid.chans)
981 n_subdevices++; 1119 n_subdevices++;
1120 for (i = 0; i < MAX_8254_SUBDEVS; i++)
1121 if (this_board->s8254[i].chans)
1122 n_subdevices++;
982 } 1123 }
983 1124
984 ret = alloc_subdevices(dev, n_subdevices); 1125 ret = alloc_subdevices(dev, n_subdevices);
@@ -1022,6 +1163,13 @@ static int pci_dio_attach(struct comedi_device *dev,
1022 subdev++; 1163 subdev++;
1023 } 1164 }
1024 1165
1166 for (i = 0; i < MAX_8254_SUBDEVS; i++)
1167 if (this_board->s8254[i].chans) {
1168 s = dev->subdevices + subdev;
1169 pci_dio_add_8254(dev, s, &this_board->s8254[i], subdev);
1170 subdev++;
1171 }
1172
1025 if (this_board->cardtype == TYPE_PCI1760) 1173 if (this_board->cardtype == TYPE_PCI1760)
1026 pci1760_attach(dev, it); 1174 pci1760_attach(dev, it);
1027 1175
@@ -1067,6 +1215,16 @@ static int pci_dio_detach(struct comedi_device *dev)
1067 } 1215 }
1068 } 1216 }
1069 1217
1218 if (this_board->boardid.chans) {
1219 subdev++;
1220 }
1221
1222 for (i = 0; i < MAX_8254_SUBDEVS; i++) {
1223 if (this_board->s8254[i].chans) {
1224 subdev++;
1225 }
1226 }
1227
1070 for (i = 0; i < dev->n_subdevices; i++) { 1228 for (i = 0; i < dev->n_subdevices; i++) {
1071 s = dev->subdevices + i; 1229 s = dev->subdevices + i;
1072 s->private = NULL; 1230 s->private = NULL;
diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c
index 8eb67651486a..bf27617aa62d 100644
--- a/drivers/staging/comedi/drivers/amplc_dio200.c
+++ b/drivers/staging/comedi/drivers/amplc_dio200.c
@@ -460,6 +460,7 @@ struct dio200_subdev_8254 {
460 int has_clk_gat_sce; 460 int has_clk_gat_sce;
461 unsigned clock_src[3]; /* Current clock sources */ 461 unsigned clock_src[3]; /* Current clock sources */
462 unsigned gate_src[3]; /* Current gate sources */ 462 unsigned gate_src[3]; /* Current gate sources */
463 spinlock_t spinlock;
463}; 464};
464 465
465struct dio200_subdev_intr { 466struct dio200_subdev_intr {
@@ -1042,8 +1043,11 @@ dio200_subdev_8254_read(struct comedi_device *dev, struct comedi_subdevice *s,
1042{ 1043{
1043 struct dio200_subdev_8254 *subpriv = s->private; 1044 struct dio200_subdev_8254 *subpriv = s->private;
1044 int chan = CR_CHAN(insn->chanspec); 1045 int chan = CR_CHAN(insn->chanspec);
1046 unsigned long flags;
1045 1047
1048 spin_lock_irqsave(&subpriv->spinlock, flags);
1046 data[0] = i8254_read(subpriv->iobase, 0, chan); 1049 data[0] = i8254_read(subpriv->iobase, 0, chan);
1050 spin_unlock_irqrestore(&subpriv->spinlock, flags);
1047 1051
1048 return 1; 1052 return 1;
1049} 1053}
@@ -1057,8 +1061,11 @@ dio200_subdev_8254_write(struct comedi_device *dev, struct comedi_subdevice *s,
1057{ 1061{
1058 struct dio200_subdev_8254 *subpriv = s->private; 1062 struct dio200_subdev_8254 *subpriv = s->private;
1059 int chan = CR_CHAN(insn->chanspec); 1063 int chan = CR_CHAN(insn->chanspec);
1064 unsigned long flags;
1060 1065
1066 spin_lock_irqsave(&subpriv->spinlock, flags);
1061 i8254_write(subpriv->iobase, 0, chan, data[0]); 1067 i8254_write(subpriv->iobase, 0, chan, data[0]);
1068 spin_unlock_irqrestore(&subpriv->spinlock, flags);
1062 1069
1063 return 1; 1070 return 1;
1064} 1071}
@@ -1151,14 +1158,16 @@ dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s,
1151 struct comedi_insn *insn, unsigned int *data) 1158 struct comedi_insn *insn, unsigned int *data)
1152{ 1159{
1153 struct dio200_subdev_8254 *subpriv = s->private; 1160 struct dio200_subdev_8254 *subpriv = s->private;
1154 int ret; 1161 int ret = 0;
1155 int chan = CR_CHAN(insn->chanspec); 1162 int chan = CR_CHAN(insn->chanspec);
1163 unsigned long flags;
1156 1164
1165 spin_lock_irqsave(&subpriv->spinlock, flags);
1157 switch (data[0]) { 1166 switch (data[0]) {
1158 case INSN_CONFIG_SET_COUNTER_MODE: 1167 case INSN_CONFIG_SET_COUNTER_MODE:
1159 ret = i8254_set_mode(subpriv->iobase, 0, chan, data[1]); 1168 ret = i8254_set_mode(subpriv->iobase, 0, chan, data[1]);
1160 if (ret < 0) 1169 if (ret < 0)
1161 return -EINVAL; 1170 ret = -EINVAL;
1162 break; 1171 break;
1163 case INSN_CONFIG_8254_READ_STATUS: 1172 case INSN_CONFIG_8254_READ_STATUS:
1164 data[1] = i8254_status(subpriv->iobase, 0, chan); 1173 data[1] = i8254_status(subpriv->iobase, 0, chan);
@@ -1166,30 +1175,35 @@ dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s,
1166 case INSN_CONFIG_SET_GATE_SRC: 1175 case INSN_CONFIG_SET_GATE_SRC:
1167 ret = dio200_set_gate_src(subpriv, chan, data[2]); 1176 ret = dio200_set_gate_src(subpriv, chan, data[2]);
1168 if (ret < 0) 1177 if (ret < 0)
1169 return -EINVAL; 1178 ret = -EINVAL;
1170 break; 1179 break;
1171 case INSN_CONFIG_GET_GATE_SRC: 1180 case INSN_CONFIG_GET_GATE_SRC:
1172 ret = dio200_get_gate_src(subpriv, chan); 1181 ret = dio200_get_gate_src(subpriv, chan);
1173 if (ret < 0) 1182 if (ret < 0) {
1174 return -EINVAL; 1183 ret = -EINVAL;
1184 break;
1185 }
1175 data[2] = ret; 1186 data[2] = ret;
1176 break; 1187 break;
1177 case INSN_CONFIG_SET_CLOCK_SRC: 1188 case INSN_CONFIG_SET_CLOCK_SRC:
1178 ret = dio200_set_clock_src(subpriv, chan, data[1]); 1189 ret = dio200_set_clock_src(subpriv, chan, data[1]);
1179 if (ret < 0) 1190 if (ret < 0)
1180 return -EINVAL; 1191 ret = -EINVAL;
1181 break; 1192 break;
1182 case INSN_CONFIG_GET_CLOCK_SRC: 1193 case INSN_CONFIG_GET_CLOCK_SRC:
1183 ret = dio200_get_clock_src(subpriv, chan, &data[2]); 1194 ret = dio200_get_clock_src(subpriv, chan, &data[2]);
1184 if (ret < 0) 1195 if (ret < 0) {
1185 return -EINVAL; 1196 ret = -EINVAL;
1197 break;
1198 }
1186 data[1] = ret; 1199 data[1] = ret;
1187 break; 1200 break;
1188 default: 1201 default:
1189 return -EINVAL; 1202 ret = -EINVAL;
1190 break; 1203 break;
1191 } 1204 }
1192 return insn->n; 1205 spin_unlock_irqrestore(&subpriv->spinlock, flags);
1206 return ret < 0 ? ret : insn->n;
1193} 1207}
1194 1208
1195/* 1209/*
@@ -1222,6 +1236,7 @@ dio200_subdev_8254_init(struct comedi_device *dev, struct comedi_subdevice *s,
1222 s->insn_write = dio200_subdev_8254_write; 1236 s->insn_write = dio200_subdev_8254_write;
1223 s->insn_config = dio200_subdev_8254_config; 1237 s->insn_config = dio200_subdev_8254_config;
1224 1238
1239 spin_lock_init(&subpriv->spinlock);
1225 subpriv->iobase = offset + iobase; 1240 subpriv->iobase = offset + iobase;
1226 subpriv->has_clk_gat_sce = has_clk_gat_sce; 1241 subpriv->has_clk_gat_sce = has_clk_gat_sce;
1227 if (has_clk_gat_sce) { 1242 if (has_clk_gat_sce) {
diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c
index cedb02d40f95..3a46f0c0bff9 100644
--- a/drivers/staging/comedi/drivers/ni_mio_cs.c
+++ b/drivers/staging/comedi/drivers/ni_mio_cs.c
@@ -123,7 +123,7 @@ static const struct ni_board_struct ni_boards[] = {
123 .adbits = 12, 123 .adbits = 12,
124 .ai_fifo_depth = 1024, 124 .ai_fifo_depth = 1024,
125 .alwaysdither = 0, 125 .alwaysdither = 0,
126 .gainlkup = ai_gain_16, 126 .gainlkup = ai_gain_4,
127 .ai_speed = 5000, 127 .ai_speed = 5000,
128 .n_aochan = 2, 128 .n_aochan = 2,
129 .aobits = 12, 129 .aobits = 12,
diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c
index 86f035d00675..27b4cb2e2ec2 100644
--- a/drivers/staging/comedi/drivers/usbdux.c
+++ b/drivers/staging/comedi/drivers/usbdux.c
@@ -351,8 +351,7 @@ static int usbdux_ai_stop(struct usbduxsub *this_usbduxsub, int do_unlink)
351 int ret = 0; 351 int ret = 0;
352 352
353 if (!this_usbduxsub) { 353 if (!this_usbduxsub) {
354 dev_err(&this_usbduxsub->interface->dev, 354 pr_err("comedi?: usbdux_ai_stop: this_usbduxsub=NULL!\n");
355 "comedi?: usbdux_ai_stop: this_usbduxsub=NULL!\n");
356 return -EFAULT; 355 return -EFAULT;
357 } 356 }
358 dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ai_stop\n"); 357 dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ai_stop\n");
diff --git a/drivers/staging/dream/synaptics_i2c_rmi.c b/drivers/staging/dream/synaptics_i2c_rmi.c
index 1f020dad6234..3320359408a9 100644
--- a/drivers/staging/dream/synaptics_i2c_rmi.c
+++ b/drivers/staging/dream/synaptics_i2c_rmi.c
@@ -519,7 +519,6 @@ err_input_register_device_failed:
519err_input_dev_alloc_failed: 519err_input_dev_alloc_failed:
520err_detect_failed: 520err_detect_failed:
521err_power_failed: 521err_power_failed:
522 i2c_set_clientdata(client, NULL);
523 kfree(ts); 522 kfree(ts);
524err_alloc_data_failed: 523err_alloc_data_failed:
525err_check_functionality_failed: 524err_check_functionality_failed:
@@ -537,7 +536,6 @@ static int synaptics_ts_remove(struct i2c_client *client)
537 else 536 else
538 hrtimer_cancel(&ts->timer); 537 hrtimer_cancel(&ts->timer);
539 input_unregister_device(ts->input_dev); 538 input_unregister_device(ts->input_dev);
540 i2c_set_clientdata(client, NULL);
541 kfree(ts); 539 kfree(ts);
542 return 0; 540 return 0;
543} 541}
diff --git a/drivers/staging/dt3155/allocator.c b/drivers/staging/dt3155/allocator.c
index bd5adbc2a238..d33947b0378f 100644
--- a/drivers/staging/dt3155/allocator.c
+++ b/drivers/staging/dt3155/allocator.c
@@ -176,9 +176,7 @@ int allocator_free_dma(unsigned long address)
176 prev = ptr; ptr = ptr->next; 176 prev = ptr; ptr = ptr->next;
177 177
178 if (!ptr) { 178 if (!ptr) {
179 printk(KERN_ERR ALL_MSG 179 pr_err(ALL_MSG "free_dma but add. not allocated\n");
180 "free_dma(0x%08lx) but add. not allocated\n",
181 ptr->address);
182 return -EINVAL; 180 return -EINVAL;
183 } 181 }
184 PDEBUGG("freeing: %08lx (%li) next %08lx\n", ptr->address, ptr->size, 182 PDEBUGG("freeing: %08lx (%li) next %08lx\n", ptr->address, ptr->size,
diff --git a/drivers/staging/go7007/saa7134-go7007.c b/drivers/staging/go7007/saa7134-go7007.c
index 49f0d31c118a..cf7c34a99459 100644
--- a/drivers/staging/go7007/saa7134-go7007.c
+++ b/drivers/staging/go7007/saa7134-go7007.c
@@ -242,13 +242,13 @@ static void saa7134_go7007_irq_ts_done(struct saa7134_dev *dev,
242 printk(KERN_DEBUG "saa7134-go7007: irq: lost %ld\n", 242 printk(KERN_DEBUG "saa7134-go7007: irq: lost %ld\n",
243 (status >> 16) & 0x0f); 243 (status >> 16) & 0x0f);
244 if (status & 0x100000) { 244 if (status & 0x100000) {
245 dma_sync_single(&dev->pci->dev, 245 dma_sync_single_for_cpu(&dev->pci->dev,
246 saa->bottom_dma, PAGE_SIZE, DMA_FROM_DEVICE); 246 saa->bottom_dma, PAGE_SIZE, DMA_FROM_DEVICE);
247 go7007_parse_video_stream(go, saa->bottom, PAGE_SIZE); 247 go7007_parse_video_stream(go, saa->bottom, PAGE_SIZE);
248 saa_writel(SAA7134_RS_BA2(5), cpu_to_le32(saa->bottom_dma)); 248 saa_writel(SAA7134_RS_BA2(5), cpu_to_le32(saa->bottom_dma));
249 } else { 249 } else {
250 dma_sync_single(&dev->pci->dev, 250 dma_sync_single_for_cpu(&dev->pci->dev,
251 saa->top_dma, PAGE_SIZE, DMA_FROM_DEVICE); 251 saa->top_dma, PAGE_SIZE, DMA_FROM_DEVICE);
252 go7007_parse_video_stream(go, saa->top, PAGE_SIZE); 252 go7007_parse_video_stream(go, saa->top, PAGE_SIZE);
253 saa_writel(SAA7134_RS_BA1(5), cpu_to_le32(saa->top_dma)); 253 saa_writel(SAA7134_RS_BA1(5), cpu_to_le32(saa->top_dma));
254 } 254 }
diff --git a/drivers/staging/go7007/wis-saa7113.c b/drivers/staging/go7007/wis-saa7113.c
index bd925457f8b7..72f5c1f56d19 100644
--- a/drivers/staging/go7007/wis-saa7113.c
+++ b/drivers/staging/go7007/wis-saa7113.c
@@ -289,7 +289,6 @@ static int wis_saa7113_probe(struct i2c_client *client,
289 if (write_regs(client, initial_registers) < 0) { 289 if (write_regs(client, initial_registers) < 0) {
290 printk(KERN_ERR 290 printk(KERN_ERR
291 "wis-saa7113: error initializing SAA7113\n"); 291 "wis-saa7113: error initializing SAA7113\n");
292 i2c_set_clientdata(client, NULL);
293 kfree(dec); 292 kfree(dec);
294 return -ENODEV; 293 return -ENODEV;
295 } 294 }
@@ -301,7 +300,6 @@ static int wis_saa7113_remove(struct i2c_client *client)
301{ 300{
302 struct wis_saa7113 *dec = i2c_get_clientdata(client); 301 struct wis_saa7113 *dec = i2c_get_clientdata(client);
303 302
304 i2c_set_clientdata(client, NULL);
305 kfree(dec); 303 kfree(dec);
306 return 0; 304 return 0;
307} 305}
diff --git a/drivers/staging/go7007/wis-saa7115.c b/drivers/staging/go7007/wis-saa7115.c
index b2eb804c1954..cd950b61cf70 100644
--- a/drivers/staging/go7007/wis-saa7115.c
+++ b/drivers/staging/go7007/wis-saa7115.c
@@ -422,7 +422,6 @@ static int wis_saa7115_probe(struct i2c_client *client,
422 if (write_regs(client, initial_registers) < 0) { 422 if (write_regs(client, initial_registers) < 0) {
423 printk(KERN_ERR 423 printk(KERN_ERR
424 "wis-saa7115: error initializing SAA7115\n"); 424 "wis-saa7115: error initializing SAA7115\n");
425 i2c_set_clientdata(client, NULL);
426 kfree(dec); 425 kfree(dec);
427 return -ENODEV; 426 return -ENODEV;
428 } 427 }
@@ -434,7 +433,6 @@ static int wis_saa7115_remove(struct i2c_client *client)
434{ 433{
435 struct wis_saa7115 *dec = i2c_get_clientdata(client); 434 struct wis_saa7115 *dec = i2c_get_clientdata(client);
436 435
437 i2c_set_clientdata(client, NULL);
438 kfree(dec); 436 kfree(dec);
439 return 0; 437 return 0;
440} 438}
diff --git a/drivers/staging/go7007/wis-sony-tuner.c b/drivers/staging/go7007/wis-sony-tuner.c
index b1013291190f..981c9b311b8b 100644
--- a/drivers/staging/go7007/wis-sony-tuner.c
+++ b/drivers/staging/go7007/wis-sony-tuner.c
@@ -684,7 +684,6 @@ static int wis_sony_tuner_remove(struct i2c_client *client)
684{ 684{
685 struct wis_sony_tuner *t = i2c_get_clientdata(client); 685 struct wis_sony_tuner *t = i2c_get_clientdata(client);
686 686
687 i2c_set_clientdata(client, NULL);
688 kfree(t); 687 kfree(t);
689 return 0; 688 return 0;
690} 689}
diff --git a/drivers/staging/go7007/wis-tw2804.c b/drivers/staging/go7007/wis-tw2804.c
index 315268d130dd..ee28a99dc388 100644
--- a/drivers/staging/go7007/wis-tw2804.c
+++ b/drivers/staging/go7007/wis-tw2804.c
@@ -323,7 +323,6 @@ static int wis_tw2804_remove(struct i2c_client *client)
323{ 323{
324 struct wis_tw2804 *dec = i2c_get_clientdata(client); 324 struct wis_tw2804 *dec = i2c_get_clientdata(client);
325 325
326 i2c_set_clientdata(client, NULL);
327 kfree(dec); 326 kfree(dec);
328 return 0; 327 return 0;
329} 328}
diff --git a/drivers/staging/go7007/wis-tw9903.c b/drivers/staging/go7007/wis-tw9903.c
index 2afea09091b9..80d47269b1c0 100644
--- a/drivers/staging/go7007/wis-tw9903.c
+++ b/drivers/staging/go7007/wis-tw9903.c
@@ -294,7 +294,6 @@ static int wis_tw9903_probe(struct i2c_client *client,
294 294
295 if (write_regs(client, initial_registers) < 0) { 295 if (write_regs(client, initial_registers) < 0) {
296 printk(KERN_ERR "wis-tw9903: error initializing TW9903\n"); 296 printk(KERN_ERR "wis-tw9903: error initializing TW9903\n");
297 i2c_set_clientdata(client, NULL);
298 kfree(dec); 297 kfree(dec);
299 return -ENODEV; 298 return -ENODEV;
300 } 299 }
@@ -306,7 +305,6 @@ static int wis_tw9903_remove(struct i2c_client *client)
306{ 305{
307 struct wis_tw9903 *dec = i2c_get_clientdata(client); 306 struct wis_tw9903 *dec = i2c_get_clientdata(client);
308 307
309 i2c_set_clientdata(client, NULL);
310 kfree(dec); 308 kfree(dec);
311 return 0; 309 return 0;
312} 310}
diff --git a/drivers/staging/iio/Documentation/iio_utils.h b/drivers/staging/iio/Documentation/iio_utils.h
index a4555e6f133f..014f6684faba 100644
--- a/drivers/staging/iio/Documentation/iio_utils.h
+++ b/drivers/staging/iio/Documentation/iio_utils.h
@@ -62,9 +62,8 @@ inline int find_type_by_name(const char *name, const char *type)
62 1) != 0) { 62 1) != 0) {
63 filename = malloc(strlen(iio_dir) 63 filename = malloc(strlen(iio_dir)
64 + strlen(type) 64 + strlen(type)
65 + 1
66 + numstrlen 65 + numstrlen
67 + 1); 66 + 6);
68 if (filename == NULL) 67 if (filename == NULL)
69 return -ENOMEM; 68 return -ENOMEM;
70 sprintf(filename, "%s%s%d/name", 69 sprintf(filename, "%s%s%d/name",
diff --git a/drivers/staging/iio/adc/max1363_core.c b/drivers/staging/iio/adc/max1363_core.c
index 20e267448d1f..905f8560d31f 100644
--- a/drivers/staging/iio/adc/max1363_core.c
+++ b/drivers/staging/iio/adc/max1363_core.c
@@ -1011,7 +1011,6 @@ error_put_reg:
1011 if (!IS_ERR(st->reg)) 1011 if (!IS_ERR(st->reg))
1012 regulator_put(st->reg); 1012 regulator_put(st->reg);
1013error_free_st: 1013error_free_st:
1014 i2c_set_clientdata(client, NULL);
1015 kfree(st); 1014 kfree(st);
1016 1015
1017error_ret: 1016error_ret:
@@ -1030,7 +1029,6 @@ static int max1363_remove(struct i2c_client *client)
1030 regulator_disable(st->reg); 1029 regulator_disable(st->reg);
1031 regulator_put(st->reg); 1030 regulator_put(st->reg);
1032 } 1031 }
1033 i2c_set_clientdata(client, NULL);
1034 kfree(st); 1032 kfree(st);
1035 1033
1036 return 0; 1034 return 0;
diff --git a/drivers/staging/iio/light/tsl2563.c b/drivers/staging/iio/light/tsl2563.c
index 43aaacff4e74..e4b0a5ef1c1f 100644
--- a/drivers/staging/iio/light/tsl2563.c
+++ b/drivers/staging/iio/light/tsl2563.c
@@ -694,7 +694,6 @@ static int __devinit tsl2563_probe(struct i2c_client *client,
694fail2: 694fail2:
695 iio_device_unregister(chip->indio_dev); 695 iio_device_unregister(chip->indio_dev);
696fail1: 696fail1:
697 i2c_set_clientdata(client, NULL);
698 kfree(chip); 697 kfree(chip);
699 return err; 698 return err;
700} 699}
@@ -705,7 +704,6 @@ static int tsl2563_remove(struct i2c_client *client)
705 704
706 iio_device_unregister(chip->indio_dev); 705 iio_device_unregister(chip->indio_dev);
707 706
708 i2c_set_clientdata(client, NULL);
709 kfree(chip); 707 kfree(chip);
710 return 0; 708 return 0;
711} 709}
diff --git a/drivers/staging/iio/ring_sw.c b/drivers/staging/iio/ring_sw.c
index 1f14cd4770e7..294272d0619f 100644
--- a/drivers/staging/iio/ring_sw.c
+++ b/drivers/staging/iio/ring_sw.c
@@ -20,7 +20,7 @@ static inline int __iio_allocate_sw_ring_buffer(struct iio_sw_ring_buffer *ring,
20 if ((length == 0) || (bytes_per_datum == 0)) 20 if ((length == 0) || (bytes_per_datum == 0))
21 return -EINVAL; 21 return -EINVAL;
22 __iio_update_ring_buffer(&ring->buf, bytes_per_datum, length); 22 __iio_update_ring_buffer(&ring->buf, bytes_per_datum, length);
23 ring->data = kmalloc(length*ring->buf.bpd, GFP_KERNEL); 23 ring->data = kmalloc(length*ring->buf.bpd, GFP_ATOMIC);
24 ring->read_p = NULL; 24 ring->read_p = NULL;
25 ring->write_p = NULL; 25 ring->write_p = NULL;
26 ring->last_written_p = NULL; 26 ring->last_written_p = NULL;
diff --git a/drivers/staging/mrst-touchscreen/Kconfig b/drivers/staging/mrst-touchscreen/Kconfig
new file mode 100644
index 000000000000..c2af49217084
--- /dev/null
+++ b/drivers/staging/mrst-touchscreen/Kconfig
@@ -0,0 +1,7 @@
1config TOUCHSCREEN_INTEL_MID
2 tristate "Intel MID platform resistive touchscreen"
3 depends on INTEL_SCU_IPC
4 default y
5 help
6 Say Y here if you have a Intel MID based touchscreen
7 If unsure, say N.
diff --git a/drivers/staging/mrst-touchscreen/Makefile b/drivers/staging/mrst-touchscreen/Makefile
new file mode 100644
index 000000000000..2d638b0d70bf
--- /dev/null
+++ b/drivers/staging/mrst-touchscreen/Makefile
@@ -0,0 +1,3 @@
1obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) := intel_mid_touch.o
2
3
diff --git a/drivers/staging/mrst-touchscreen/TODO b/drivers/staging/mrst-touchscreen/TODO
new file mode 100644
index 000000000000..7157028d634a
--- /dev/null
+++ b/drivers/staging/mrst-touchscreen/TODO
@@ -0,0 +1,2 @@
1- Move the driver to not think it is SPI (requires fixing some of the SFI
2 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
index 000000000000..1db00975a594
--- /dev/null
+++ b/drivers/staging/mrst-touchscreen/intel-mid-touch.c
@@ -0,0 +1,864 @@
1/*
2 * intel_mid_touch.c - Intel MID Resistive Touch Screen Driver
3 *
4 * Copyright (C) 2008 Intel Corp
5 *
6 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; ifnot, write to the Free Software Foundation, Inc.,
19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
20 *
21 * Questions/Comments/Bug fixes to Sreedhara (sreedhara.ds@intel.com)
22 * Ramesh Agarwal (ramesh.agarwal@intel.com)
23 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24 *
25 * TODO:
26 * kill off mrstouch_debug eventually
27 * review conversion of r/m/w sequences
28 * Replace interrupt mutex abuse
29 * Kill of mrstouchdevp pointer
30 *
31 */
32
33#include <linux/module.h>
34#include <linux/init.h>
35#include <linux/input.h>
36#include <linux/interrupt.h>
37#include <linux/err.h>
38#include <linux/param.h>
39#include <linux/spi/spi.h>
40#include <linux/irq.h>
41#include <linux/delay.h>
42#include <linux/kthread.h>
43#include <asm/intel_scu_ipc.h>
44
45
46#if defined(MRSTOUCH_DEBUG)
47#define mrstouch_debug(fmt, args...)\
48 do { \
49 printk(KERN_DEBUG "\n[MRSTOUCH(%d)] - ", __LINE__); \
50 printk(KERN_DEBUG fmt, ##args); \
51 } while (0);
52#else
53#define mrstouch_debug(fmt, args...)
54#endif
55
56/* PMIC Interrupt registers */
57#define PMIC_REG_ID1 0x00 /*PMIC ID1 register */
58
59/* PMIC Interrupt registers */
60#define PMIC_REG_INT 0x04 /*PMIC interrupt register */
61#define PMIC_REG_MINT 0x05 /*PMIC interrupt mask register */
62
63/* ADC Interrupt registers */
64#define PMIC_REG_ADCINT 0x5F /*ADC interrupt register */
65#define PMIC_REG_MADCINT 0x60 /*ADC interrupt mask register */
66
67/* ADC Control registers */
68#define PMIC_REG_ADCCNTL1 0x61 /*ADC control register */
69
70/* ADC Channel Selection registers */
71#define PMICADDR0 0xA4
72#define END_OF_CHANNEL 0x1F
73
74/* ADC Result register */
75#define PMIC_REG_ADCSNS0H 0x64
76
77/* ADC channels for touch screen */
78#define MRST_TS_CHAN10 0xA /* Touch screen X+ connection */
79#define MRST_TS_CHAN11 0xB /* Touch screen X- connection */
80#define MRST_TS_CHAN12 0xC /* Touch screen Y+ connection */
81#define MRST_TS_CHAN13 0xD /* Touch screen Y- connection */
82
83/* Touch screen coordinate constants */
84#define TOUCH_PRESSURE 50
85#define TOUCH_PRESSURE_FS 100
86
87#define XMOVE_LIMIT 5
88#define YMOVE_LIMIT 5
89#define XYMOVE_CNT 3
90
91#define MAX_10BIT ((1<<10)-1)
92
93/* Touch screen channel BIAS constants */
94#define XBIAS 0x20
95#define YBIAS 0x40
96#define ZBIAS 0x80
97
98/* Touch screen coordinates */
99#define MIN_X 10
100#define MAX_X 1024
101#define MIN_Y 10
102#define MAX_Y 1024
103#define WAIT_ADC_COMPLETION 10
104
105/* PMIC ADC round robin delays */
106#define ADC_LOOP_DELAY0 0x0 /* Continuous loop */
107#define ADC_LOOP_DELAY1 0x1 /* 4.5 ms approximate */
108
109/* PMIC Vendor Identifiers */
110#define PMIC_VENDOR_FS 0 /* PMIC vendor FreeScale */
111#define PMIC_VENDOR_MAXIM 1 /* PMIC vendor MAXIM */
112#define PMIC_VENDOR_NEC 2 /* PMIC vendor NEC */
113#define MRSTOUCH_MAX_CHANNELS 32 /* Maximum ADC channels */
114
115/* Touch screen device structure */
116struct mrstouch_dev {
117 struct spi_device *spi; /* SPI device associated with touch screen */
118 struct input_dev *input; /* input device for touchscreen*/
119 char phys[32]; /* Device name */
120 struct task_struct *pendet_thrd; /* PENDET interrupt handler */
121 struct mutex lock; /* Sync between interrupt and PENDET handler */
122 bool busy; /* Busy flag */
123 u16 asr; /* Address selection register */
124 int irq; /* Touch screen IRQ # */
125 uint vendor; /* PMIC vendor */
126 uint rev; /* PMIC revision */
127 bool suspended; /* Device suspended status */
128 bool disabled; /* Device disabled status */
129 u16 x; /* X coordinate */
130 u16 y; /* Y coordinate */
131 bool pendown; /* PEN position */
132} ;
133
134
135/* Global Pointer to Touch screen device */
136static struct mrstouch_dev *mrstouchdevp;
137
138/* Utility to read PMIC ID */
139static int mrstouch_pmic_id(uint *vendor, uint *rev)
140{
141 int err;
142 u8 r;
143
144 err = intel_scu_ipc_ioread8(PMIC_REG_ID1, &r);
145 if (err)
146 return err;
147
148 *vendor = r & 0x7;
149 *rev = (r >> 3) & 0x7;
150
151 return 0;
152}
153
154/*
155 * Parse ADC channels to find end of the channel configured by other ADC user
156 * NEC and MAXIM requires 4 channels and FreeScale needs 18 channels
157 */
158static int mrstouch_chan_parse(struct mrstouch_dev *tsdev)
159{
160 int err, i, j, found;
161 u32 r32;
162
163 found = -1;
164
165 for (i = 0; i < MRSTOUCH_MAX_CHANNELS; i++) {
166 if (found >= 0)
167 break;
168
169 err = intel_scu_ipc_ioread32(PMICADDR0, &r32);
170 if (err)
171 return err;
172
173 for (j = 0; j < 32; j+= 8) {
174 if (((r32 >> j) & 0xFF) == END_OF_CHANNEL) {
175 found = i;
176 break;
177 }
178 }
179 }
180 if (found < 0)
181 return 0;
182
183 if (tsdev->vendor == PMIC_VENDOR_FS) {
184 if (found && found > (MRSTOUCH_MAX_CHANNELS - 18))
185 return -ENOSPC;
186 } else {
187 if (found && found > (MRSTOUCH_MAX_CHANNELS - 4))
188 return -ENOSPC;
189 }
190 return found;
191}
192
193/* Utility to enable/disable pendet.
194 * pendet set to true enables PENDET interrupt
195 * pendet set to false disables PENDET interrupt
196 * Also clears RND mask bit
197*/
198static int pendet_enable(struct mrstouch_dev *tsdev, bool pendet)
199{
200 u16 reg;
201 u8 r;
202 u8 pendet_enabled = 0;
203 int retry = 0;
204 int err;
205
206 err = intel_scu_ipc_ioread16(PMIC_REG_MADCINT, &reg);
207 if (err)
208 return err;
209
210 if (pendet) {
211 reg &= ~0x0005;
212 reg |= 0x2000; /* Enable pendet */
213 } else
214 reg &= 0xDFFF; /* Disable pendet */
215
216 /* Set MADCINT and update ADCCNTL1 (next reg byte) */
217 err = intel_scu_ipc_iowrite16(PMIC_REG_MADCINT, reg);
218 if (!pendet || err)
219 return err;
220
221 /*
222 * Sometimes even after the register write succeeds
223 * the PMIC register value is not updated. Retry few iterations
224 * to enable pendet.
225 */
226
227 err = intel_scu_ipc_ioread8(PMIC_REG_ADCCNTL1, &r);
228 pendet_enabled = (r >> 5) & 0x01;
229
230 retry = 0;
231 while (!err && !pendet_enabled) {
232 retry++;
233 msleep(10);
234 err = intel_scu_ipc_iowrite8(PMIC_REG_ADCCNTL1, reg >> 8);
235 if (err)
236 break;
237 err = intel_scu_ipc_ioread8(PMIC_REG_ADCCNTL1, &r);
238 if (err == 0)
239 pendet_enabled = (r >> 5) & 0x01;
240 if (retry >= 10) {
241 dev_err(&tsdev->spi->dev, "Touch screen disabled.\n");
242 return -EIO;
243 }
244 }
245 return 0;
246}
247
248/* To read PMIC ADC touch screen result
249 * Reads ADC storage registers for higher 7 and lower 3 bits
250 * converts the two readings to single value and turns off gain bit
251 */
252static int mrstouch_ts_chan_read(u16 offset, u16 chan, u16 *vp, u16 *vm)
253{
254 int err;
255 u16 result;
256 u32 res;
257
258 result = PMIC_REG_ADCSNS0H + offset;
259
260 if (chan == MRST_TS_CHAN12)
261 result += 4;
262
263 err = intel_scu_ipc_ioread32(result, &res);
264 if (err)
265 return err;
266
267 /* Mash the bits up */
268
269 *vp = (res & 0xFF) << 3; /* Highest 7 bits */
270 *vp |= (res >> 8) & 0x07; /* Lower 3 bits */
271 *vp &= 0x3FF;
272
273 res >>= 16;
274
275 *vm = (res & 0xFF) << 3; /* Highest 7 bits */
276 *vm |= (res >> 8) & 0x07; /* Lower 3 bits */
277 *vm &= 0x3FF;
278
279 return 0;
280}
281
282/* To configure touch screen channels
283 * Writes touch screen channels to ADC address selection registers
284 */
285static int mrstouch_ts_chan_set(uint offset)
286{
287 int count;
288 u16 chan;
289 u16 reg[5];
290 u8 data[5];
291
292 chan = PMICADDR0 + offset;
293 for (count = 0; count <= 3; count++) {
294 reg[count] = chan++;
295 data[count] = MRST_TS_CHAN10 + count;
296 }
297 reg[count] = chan;
298 data[count] = END_OF_CHANNEL;
299
300 return intel_scu_ipc_writev(reg, data, 5);
301}
302
303/* Initialize ADC */
304static int mrstouch_adc_init(struct mrstouch_dev *tsdev)
305{
306 int err, start;
307 u8 ra, rm;
308
309 err = mrstouch_pmic_id(&tsdev->vendor, &tsdev->rev);
310 if (err) {
311 dev_err(&tsdev->spi->dev, "Unable to read PMIC id\n");
312 return err;
313 }
314
315 start = mrstouch_chan_parse(tsdev);
316 if (start < 0) {
317 dev_err(&tsdev->spi->dev, "Unable to parse channels\n");
318 return start;
319 }
320
321 tsdev->asr = start;
322
323 mrstouch_debug("Channel offset(%d): 0x%X\n", tsdev->asr, tsdev->vendor);
324
325 /* ADC power on, start, enable PENDET and set loop delay
326 * ADC loop delay is set to 4.5 ms approximately
327 * Loop delay more than this results in jitter in adc readings
328 * Setting loop delay to 0 (continous loop) in MAXIM stops PENDET
329 * interrupt generation sometimes.
330 */
331
332 if (tsdev->vendor == PMIC_VENDOR_FS) {
333 ra = 0xE0 | ADC_LOOP_DELAY0;
334 rm = 0x5;
335 } else {
336 /* NEC and MAXIm not consistent with loop delay 0 */
337 ra = 0xE0 | ADC_LOOP_DELAY1;
338 rm = 0x0;
339
340 /* configure touch screen channels */
341 err = mrstouch_ts_chan_set(tsdev->asr);
342 if (err)
343 return err;
344 }
345 err = intel_scu_ipc_update_register(PMIC_REG_ADCCNTL1, ra, 0xE7);
346 if (err == 0)
347 err = intel_scu_ipc_update_register(PMIC_REG_MADCINT, rm, 0x03);
348 return err;
349}
350
351/* Reports x,y coordinates to event subsystem */
352static void mrstouch_report_xy(struct mrstouch_dev *tsdev, u16 x, u16 y, u16 z)
353{
354 int xdiff, ydiff;
355
356 if (tsdev->pendown && z <= TOUCH_PRESSURE) {
357 /* Pen removed, report button release */
358 mrstouch_debug("BTN REL(%d)", z);
359 input_report_key(tsdev->input, BTN_TOUCH, 0);
360 tsdev->pendown = false;
361 }
362
363 xdiff = abs(x - tsdev->x);
364 ydiff = abs(y - tsdev->y);
365
366 /*
367 if x and y values changes for XYMOVE_CNT readings it is considered
368 as stylus is moving. This is required to differentiate between stylus
369 movement and jitter
370 */
371 if (x < MIN_X || x > MAX_X || y < MIN_Y || y > MAX_Y) {
372 /* Spurious values, release button if touched and return */
373 if (tsdev->pendown) {
374 mrstouch_debug("BTN REL(%d)", z);
375 input_report_key(tsdev->input, BTN_TOUCH, 0);
376 tsdev->pendown = false;
377 }
378 return;
379 } else if (xdiff >= XMOVE_LIMIT || ydiff >= YMOVE_LIMIT) {
380 tsdev->x = x;
381 tsdev->y = y;
382
383 input_report_abs(tsdev->input, ABS_X, x);
384 input_report_abs(tsdev->input, ABS_Y, y);
385 input_sync(tsdev->input);
386 }
387
388
389 if (!tsdev->pendown && z > TOUCH_PRESSURE) {
390 /* Pen touched, report button touch */
391 mrstouch_debug("BTN TCH(%d, %d, %d)", x, y, z);
392 input_report_key(tsdev->input, BTN_TOUCH, 1);
393 tsdev->pendown = true;
394 }
395}
396
397
398/* Utility to start ADC, used by freescale handler */
399static int pendet_mask(void)
400{
401 return intel_scu_ipc_update_register(PMIC_REG_MADCINT, 0x02, 0x02);
402}
403
404/* Utility to stop ADC, used by freescale handler */
405static int pendet_umask(void)
406{
407 return intel_scu_ipc_update_register(PMIC_REG_MADCINT, 0x00, 0x02);
408}
409
410/* Utility to read ADC, used by freescale handler */
411static int mrstouch_pmic_fs_adc_read(struct mrstouch_dev *tsdev)
412{
413 int err;
414 u16 x, y, z, result;
415 u16 reg[4];
416 u8 data[4];
417
418 result = PMIC_REG_ADCSNS0H + tsdev->asr;
419
420 reg[0] = result + 4;
421 reg[1] = result + 5;
422 reg[2] = result + 16;
423 reg[3] = result + 17;
424
425 err = intel_scu_ipc_readv(reg, data, 4);
426 if (err)
427 goto ipc_error;
428
429 x = data[0] << 3; /* Higher 7 bits */
430 x |= data[1] & 0x7; /* Lower 3 bits */
431 x &= 0x3FF;
432
433 y = data[2] << 3; /* Higher 7 bits */
434 y |= data[3] & 0x7; /* Lower 3 bits */
435 y &= 0x3FF;
436
437 /* Read Z value */
438 reg[0] = result + 28;
439 reg[1] = result + 29;
440
441 err = intel_scu_ipc_readv(reg, data, 4);
442 if (err)
443 goto ipc_error;
444
445 z = data[0] << 3; /* Higher 7 bits */
446 z |= data[1] & 0x7; /* Lower 3 bits */
447 z &= 0x3FF;
448
449#if defined(MRSTOUCH_PRINT_XYZP)
450 mrstouch_debug("X: %d, Y: %d, Z: %d", x, y, z);
451#endif
452
453 if (z >= TOUCH_PRESSURE_FS) {
454 mrstouch_report_xy(tsdev, x, y, TOUCH_PRESSURE - 1); /* Pen Removed */
455 return TOUCH_PRESSURE - 1;
456 } else {
457 mrstouch_report_xy(tsdev, x, y, TOUCH_PRESSURE + 1); /* Pen Touched */
458 return TOUCH_PRESSURE + 1;
459 }
460
461 return 0;
462
463ipc_error:
464 dev_err(&tsdev->spi->dev, "ipc error during fs_adc read\n");
465 return err;
466}
467
468/* To handle free scale pmic pendet interrupt */
469static int pmic0_pendet(void *dev_id)
470{
471 int err, count;
472 u16 chan;
473 unsigned int touched;
474 struct mrstouch_dev *tsdev = (struct mrstouch_dev *)dev_id;
475 u16 reg[5];
476 u8 data[5];
477
478 chan = PMICADDR0 + tsdev->asr;
479
480 /* Set X BIAS */
481 for (count = 0; count <= 3; count++) {
482 reg[count] = chan++;
483 data[count] = 0x2A;
484 }
485 reg[count] = chan++; /* Dummy */
486 data[count] = 0;
487
488 err = intel_scu_ipc_writev(reg, data, 5);
489 if (err)
490 goto ipc_error;
491
492 msleep(WAIT_ADC_COMPLETION);
493
494 /* Set Y BIAS */
495 for (count = 0; count <= 3; count++) {
496 reg[count] = chan++;
497 data[count] = 0x4A;
498 }
499 reg[count] = chan++; /* Dummy */
500 data[count] = 0;
501
502 err = intel_scu_ipc_writev(reg, data, 5);
503 if (err)
504 goto ipc_error;
505
506 msleep(WAIT_ADC_COMPLETION);
507
508 /* Set Z BIAS */
509 err = intel_scu_ipc_iowrite32(chan + 2, 0x8A8A8A8A);
510 if (err)
511 goto ipc_error;
512
513 msleep(WAIT_ADC_COMPLETION);
514
515 /*Read touch screen channels till pen removed
516 * Freescale reports constant value of z for all points
517 * z is high when screen is not touched and low when touched
518 * Map high z value to not touched and low z value to pen touched
519 */
520 touched = mrstouch_pmic_fs_adc_read(tsdev);
521 while (touched > TOUCH_PRESSURE) {
522 touched = mrstouch_pmic_fs_adc_read(tsdev);
523 msleep(WAIT_ADC_COMPLETION);
524 }
525
526 /* Clear all TS channels */
527 chan = PMICADDR0 + tsdev->asr;
528 for (count = 0; count <= 4; count++) {
529 reg[count] = chan++;
530 data[count] = 0;
531 }
532 err = intel_scu_ipc_writev(reg, data, 5);
533 if (err)
534 goto ipc_error;
535
536 for (count = 0; count <= 4; count++) {
537 reg[count] = chan++;
538 data[count] = 0;
539 }
540 err = intel_scu_ipc_writev(reg, data, 5);
541 if (err)
542 goto ipc_error;
543
544 err = intel_scu_ipc_iowrite32(chan + 2, 0x00000000);
545 if (err)
546 goto ipc_error;
547
548 return 0;
549
550ipc_error:
551 dev_err(&tsdev->spi->dev, "ipc error during pendet\n");
552 return err;
553}
554
555
556/* To enable X, Y and Z bias values
557 * Enables YPYM for X channels and XPXM for Y channels
558 */
559static int mrstouch_ts_bias_set(uint offset, uint bias)
560{
561 int count;
562 u16 chan, start;
563 u16 reg[4];
564 u8 data[4];
565
566 chan = PMICADDR0 + offset;
567 start = MRST_TS_CHAN10;
568
569 for (count = 0; count <= 3; count++) {
570 reg[count] = chan++;
571 data[count] = bias | (start + count);
572 }
573 return intel_scu_ipc_writev(reg, data, 4);
574}
575
576/* To read touch screen channel values */
577static int mrstouch_adc_read(struct mrstouch_dev *tsdev)
578{
579 int err;
580 u16 xp, xm, yp, ym, zp, zm;
581
582 /* configure Y bias for X channels */
583 err = mrstouch_ts_bias_set(tsdev->asr, YBIAS);
584 if (err)
585 goto ipc_error;
586
587 msleep(WAIT_ADC_COMPLETION);
588
589 /* read x+ and x- channels */
590 err = mrstouch_ts_chan_read(tsdev->asr, MRST_TS_CHAN10, &xp, &xm);
591 if (err)
592 goto ipc_error;
593
594 /* configure x bias for y channels */
595 err = mrstouch_ts_bias_set(tsdev->asr, XBIAS);
596 if (err)
597 goto ipc_error;
598
599 msleep(WAIT_ADC_COMPLETION);
600
601 /* read y+ and y- channels */
602 err = mrstouch_ts_chan_read(tsdev->asr, MRST_TS_CHAN12, &yp, &ym);
603 if (err)
604 goto ipc_error;
605
606 /* configure z bias for x and y channels */
607 err = mrstouch_ts_bias_set(tsdev->asr, ZBIAS);
608 if (err)
609 goto ipc_error;
610
611 msleep(WAIT_ADC_COMPLETION);
612
613 /* read z+ and z- channels */
614 err = mrstouch_ts_chan_read(tsdev->asr, MRST_TS_CHAN10, &zp, &zm);
615 if (err)
616 goto ipc_error;
617
618#if defined(MRSTOUCH_PRINT_XYZP)
619 printk(KERN_INFO "X+: %d, Y+: %d, Z+: %d\n", xp, yp, zp);
620#endif
621
622#if defined(MRSTOUCH_PRINT_XYZM)
623 printk(KERN_INFO "X-: %d, Y-: %d, Z-: %d\n", xm, ym, zm);
624#endif
625
626 mrstouch_report_xy(tsdev, xp, yp, zp); /* report x and y to eventX */
627
628 return zp;
629
630ipc_error:
631 dev_err(&tsdev->spi->dev, "ipc error during adc read\n");
632 return err;
633}
634
635/* PENDET interrupt handler function for NEC and MAXIM */
636static void pmic12_pendet(void *data)
637{
638 unsigned int touched;
639 struct mrstouch_dev *tsdev = (struct mrstouch_dev *)data;
640
641 /* read touch screen channels till pen removed */
642 do {
643 touched = mrstouch_adc_read(tsdev);
644 } while (touched > TOUCH_PRESSURE);
645}
646
647/* Handler to process PENDET interrupt */
648int mrstouch_pendet(void *data)
649{
650 struct mrstouch_dev *tsdev = (struct mrstouch_dev *)data;
651 while (1) {
652 /* Wait for PENDET interrupt */
653 if (mutex_lock_interruptible(&tsdev->lock)) {
654 msleep(WAIT_ADC_COMPLETION);
655 continue;
656 }
657
658 if (tsdev->busy)
659 return 0;
660
661 tsdev->busy = true;
662
663 if (tsdev->vendor == PMIC_VENDOR_NEC ||
664 tsdev->vendor == PMIC_VENDOR_MAXIM) {
665 /* PENDET must be disabled in NEC before reading ADC */
666 pendet_enable(tsdev,false); /* Disbale PENDET */
667 pmic12_pendet(tsdev);
668 pendet_enable(tsdev, true); /*Enable PENDET */
669 } else if (tsdev->vendor == PMIC_VENDOR_FS) {
670 pendet_umask(); /* Stop ADC */
671 pmic0_pendet(tsdev);
672 pendet_mask(); /* Stop ADC */
673 } else
674 dev_err(&tsdev->spi->dev, "Unsupported touchscreen: %d\n",
675 tsdev->vendor);
676
677 tsdev->busy = false;
678
679 }
680 return 0;
681}
682
683/* PENDET interrupt handler */
684static irqreturn_t pendet_intr_handler(int irq, void *handle)
685{
686 struct mrstouch_dev *tsdev = (struct mrstouch_dev *)handle;
687
688 mutex_unlock(&tsdev->lock);
689 return IRQ_HANDLED;
690}
691
692/* Intializes input device and registers with input subsystem */
693static int ts_input_dev_init(struct mrstouch_dev *tsdev, struct spi_device *spi)
694{
695 int err = 0;
696
697 mrstouch_debug("%s", __func__);
698
699 tsdev->input = input_allocate_device();
700 if (!tsdev->input) {
701 dev_err(&tsdev->spi->dev, "Unable to allocate input device.\n");
702 return -EINVAL;
703 }
704
705 tsdev->input->name = "mrst_touchscreen";
706 snprintf(tsdev->phys, sizeof(tsdev->phys),
707 "%s/input0", dev_name(&spi->dev));
708 tsdev->input->phys = tsdev->phys;
709 tsdev->input->dev.parent = &spi->dev;
710
711 tsdev->input->id.vendor = tsdev->vendor;
712 tsdev->input->id.version = tsdev->rev;
713
714 tsdev->input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
715 tsdev->input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
716
717 input_set_abs_params(tsdev->input, ABS_X, MIN_X, MIN_Y, 0, 0);
718 input_set_abs_params(tsdev->input, ABS_Y, MIN_X, MIN_Y, 0, 0);
719
720 err = input_register_device(tsdev->input);
721 if (err) {
722 dev_err(&tsdev->spi->dev, "unable to register input device\n");
723 input_free_device(tsdev->input);
724 return err;
725 }
726
727 mrstouch_debug("%s", "mrstouch initialized");
728
729 return 0;
730
731}
732
733/* Probe function for touch screen driver */
734static int __devinit mrstouch_probe(struct spi_device *mrstouch_spi)
735{
736 int err;
737 unsigned int myirq;
738 struct mrstouch_dev *tsdev;
739
740 mrstouch_debug("%s(%p)", __func__, mrstouch_spi);
741
742 mrstouchdevp = NULL;
743 myirq = mrstouch_spi->irq;
744
745 if (!mrstouch_spi->irq) {
746 dev_err(&mrstouch_spi->dev, "no interrupt assigned\n");
747 return -EINVAL;
748 }
749
750 tsdev = kzalloc(sizeof(struct mrstouch_dev), GFP_KERNEL);
751 if (!tsdev) {
752 dev_err(&mrstouch_spi->dev, "unable to allocate memory\n");
753 return -ENOMEM;
754 }
755
756 tsdev->irq = myirq;
757 mrstouchdevp = tsdev;
758
759 err = mrstouch_adc_init(tsdev);
760 if (err) {
761 dev_err(&mrstouch_spi->dev, "ADC init failed\n");
762 goto mrstouch_err_free_mem;
763 }
764
765 dev_set_drvdata(&mrstouch_spi->dev, tsdev);
766 tsdev->spi = mrstouch_spi;
767
768 err = ts_input_dev_init(tsdev, mrstouch_spi);
769 if (err) {
770 dev_err(&tsdev->spi->dev, "ts_input_dev_init failed");
771 goto mrstouch_err_free_mem;
772 }
773
774 mutex_init(&tsdev->lock);
775 mutex_lock(&tsdev->lock)
776
777 mrstouch_debug("Requesting IRQ-%d", myirq);
778 err = request_irq(myirq, pendet_intr_handler,
779 0, "mrstouch", tsdev);
780 if (err) {
781 dev_err(&tsdev->spi->dev, "unable to allocate irq\n");
782 goto mrstouch_err_free_mem;
783 }
784
785 tsdev->pendet_thrd = kthread_run(mrstouch_pendet,
786 (void *)tsdev, "pendet handler");
787 if (IS_ERR(tsdev->pendet_thrd)) {
788 dev_err(&tsdev->spi->dev, "kthread_run failed\n");
789 err = PTR_ERR(tsdev->pendet_thrd);
790 goto mrstouch_err_free_mem;
791 }
792 mrstouch_debug("%s", "Driver initialized");
793 return 0;
794
795mrstouch_err_free_mem:
796 kfree(tsdev);
797 return err;
798}
799
800static int mrstouch_suspend(struct spi_device *spi, pm_message_t msg)
801{
802 mrstouch_debug("%s", __func__);
803 mrstouchdevp->suspended = 1;
804 return 0;
805}
806
807static int mrstouch_resume(struct spi_device *spi)
808{
809 mrstouch_debug("%s", __func__);
810 mrstouchdevp->suspended = 0;
811 return 0;
812}
813
814static int mrstouch_remove(struct spi_device *spi)
815{
816 mrstouch_debug("%s", __func__);
817 free_irq(mrstouchdevp->irq, mrstouchdevp);
818 input_unregister_device(mrstouchdevp->input);
819 input_free_device(mrstouchdevp->input);
820 kfree(mrstouchdevp);
821 if (mrstouchdevp->pendet_thrd)
822 kthread_stop(mrstouchdevp->pendet_thrd);
823 return 0;
824}
825
826static struct spi_driver mrstouch_driver = {
827 .driver = {
828 .name = "pmic_touch",
829 .bus = &spi_bus_type,
830 .owner = THIS_MODULE,
831 },
832 .probe = mrstouch_probe,
833 .suspend = mrstouch_suspend,
834 .resume = mrstouch_resume,
835 .remove = mrstouch_remove,
836};
837
838static int __init mrstouch_module_init(void)
839{
840 int err;
841
842 mrstouch_debug("%s", __func__);
843 err = spi_register_driver(&mrstouch_driver);
844 if (err) {
845 mrstouch_debug("%s(%d)", "SPI PENDET failed", err);
846 return -1;
847 }
848
849 return 0;
850}
851
852static void __exit mrstouch_module_exit(void)
853{
854 mrstouch_debug("%s", __func__);
855 spi_unregister_driver(&mrstouch_driver);
856 return;
857}
858
859module_init(mrstouch_module_init);
860module_exit(mrstouch_module_exit);
861
862MODULE_AUTHOR("Sreedhara Murthy. D.S, sreedhara.ds@intel.com");
863MODULE_DESCRIPTION("Intel Moorestown Resistive Touch Screen Driver");
864MODULE_LICENSE("GPL");
diff --git a/drivers/staging/msm/Kconfig b/drivers/staging/msm/Kconfig
new file mode 100644
index 000000000000..c57039f2060b
--- /dev/null
+++ b/drivers/staging/msm/Kconfig
@@ -0,0 +1,134 @@
1config MSM_STAGING
2 tristate "MSM Frame Buffer Support"
3 depends on FB && ARCH_MSM && !FB_MSM
4 select FB_BACKLIGHT if FB_MSM_BACKLIGHT
5 select NEW_LEDS
6 select LEDS_CLASS
7 select FB_CFB_FILLRECT
8 select FB_CFB_COPYAREA
9 select FB_CFB_IMAGEBLIT
10 ---help---
11 Support for MSM Framebuffer.
12
13if MSM_STAGING
14
15config FB_MSM_LCDC_HW
16 bool
17 default n
18
19choice
20 prompt "MDP HW version"
21 default FB_MSM_MDP31
22
23config FB_MSM_MDP31
24 select FB_MSM_LCDC_HW
25 bool "MDP HW ver3.1"
26 ---help---
27 Support for MSM MDP HW revision 3.1
28 Say Y here if this is msm8x50 variant platform.
29endchoice
30
31config FB_MSM_LCDC
32 bool
33 default n
34
35config FB_MSM_TVOUT
36 bool
37 default n
38
39config FB_MSM_LCDC_PANEL
40 bool
41 select FB_MSM_LCDC
42 default n
43
44config FB_MSM_LCDC_PRISM_WVGA
45 bool
46 select FB_MSM_LCDC_PANEL
47 default n
48
49config FB_MSM_LCDC_ST1_WXGA
50 bool
51 select FB_MSM_LCDC_PANEL
52 default n
53
54config FB_MSM_LCDC_ST15_WXGA
55 bool
56 select FB_MSM_LCDC_PANEL
57 default n
58
59config FB_MSM_LCDC_WXGA
60 bool
61 select FB_MSM_LCDC_PANEL
62 default n
63
64choice
65 prompt "LCD Panel"
66 default FB_MSM_LCDC_ST15_PANEL
67
68config FB_MSM_LCDC_PRISM_WVGA_PANEL
69 depends on FB_MSM_LCDC_HW
70 bool "LCDC Prism WVGA Panel"
71 select FB_MSM_LCDC_PRISM_WVGA
72 ---help---
73 Support for LCDC Prism WVGA (800x480) panel
74
75
76config FB_MSM_LCDC_ST15_PANEL
77 depends on FB_MSM_LCDC_HW
78 bool "LCDC ST1.5 Panel"
79 select FB_MSM_LCDC_ST15_WXGA
80 ---help---
81 Support for ST1.5 WXGA (1366x768) panel
82
83config FB_MSM_PANEL_NONE
84 bool "NONE"
85 ---help---
86 This will disable LCD panel
87endchoice
88
89choice
90 prompt "Secondary LCD Panel"
91 depends on FB_MSM_MDP31
92 default FB_MSM_SECONDARY_PANEL_NONE
93
94config FB_MSM_SECONDARY_PANEL_NONE
95 bool "NONE"
96 ---help---
97 No secondary panel
98endchoice
99
100config FB_MSM_TVOUT_NTSC
101 bool
102 select FB_MSM_TVOUT
103 default n
104
105config FB_MSM_TVOUT_PAL
106 bool
107 select FB_MSM_TVOUT
108 default n
109
110choice
111 depends on (FB_MSM_MDP22 || FB_MSM_MDP31)
112 prompt "TVOut Region"
113 default FB_MSM_TVOUT_NTSC_M
114
115config FB_MSM_TVOUT_NTSC_M
116 bool "NTSC M"
117 select FB_MSM_TVOUT_NTSC
118 ---help---
119 Support for NTSC M region (North American and Korea)
120
121config FB_MSM_TVOUT_NONE
122 bool "NONE"
123 ---help---
124 This will disable TV Out functionality.
125endchoice
126
127config PMEM_KERNEL_SIZE
128 int "PMEM for kernel components (in MB)"
129 default 2
130 depends on ARCH_QSD8X50
131 help
132 Configures the amount of PMEM for use by kernel components
133 (in MB; minimum 2MB)
134endif
diff --git a/drivers/staging/msm/Makefile b/drivers/staging/msm/Makefile
new file mode 100644
index 000000000000..98a0ce177cb2
--- /dev/null
+++ b/drivers/staging/msm/Makefile
@@ -0,0 +1,93 @@
1obj-y := msm_fb.o staging-devices.o memory.o
2
3obj-$(CONFIG_FB_MSM_LOGO) += logo.o
4obj-$(CONFIG_FB_BACKLIGHT) += msm_fb_bl.o
5
6# MDP
7obj-y += mdp.o
8
9ifeq ($(CONFIG_FB_MSM_MDP40),y)
10obj-y += mdp4_util.o
11obj-$(CONFIG_DEBUG_FS) += mdp4_debugfs.o
12else
13obj-y += mdp_hw_init.o
14obj-y += mdp_ppp.o
15ifeq ($(CONFIG_FB_MSM_MDP31),y)
16obj-y += mdp_ppp_v31.o
17obj-$(CONFIG_MDP_PPP_ASYNC_OP) += mdp_ppp_dq.o
18else
19obj-y += mdp_ppp_v20.o
20endif
21endif
22
23ifeq ($(CONFIG_FB_MSM_OVERLAY),y)
24obj-y += mdp4_overlay.o
25obj-y += mdp4_overlay_lcdc.o
26obj-y += mdp4_overlay_mddi.o
27else
28obj-y += mdp_dma_lcdc.o
29endif
30
31obj-y += mdp_dma.o
32obj-y += mdp_dma_s.o
33obj-y += mdp_vsync.o
34obj-y += mdp_cursor.o
35obj-y += mdp_dma_tv.o
36
37# EBI2
38obj-$(CONFIG_FB_MSM_EBI2) += ebi2_lcd.o
39
40# LCDC
41obj-$(CONFIG_FB_MSM_LCDC) += lcdc.o
42
43# MDDI
44msm_mddi-objs := mddi.o mddihost.o mddihosti.o
45obj-$(CONFIG_FB_MSM_MDDI) += msm_mddi.o
46
47# External MDDI
48msm_mddi_ext-objs := mddihost_e.o mddi_ext.o
49obj-$(CONFIG_FB_MSM_EXTMDDI) += msm_mddi_ext.o
50
51# TVEnc
52obj-$(CONFIG_FB_MSM_TVOUT) += tvenc.o
53
54# MSM FB Panel
55obj-y += msm_fb_panel.o
56obj-$(CONFIG_FB_MSM_EBI2_TMD_QVGA_EPSON_QCIF) += ebi2_tmd20.o
57obj-$(CONFIG_FB_MSM_EBI2_TMD_QVGA_EPSON_QCIF) += ebi2_l2f.o
58
59ifeq ($(CONFIG_FB_MSM_MDDI_AUTO_DETECT),y)
60obj-y += mddi_prism.o
61obj-y += mddi_toshiba.o
62obj-y += mddi_toshiba_vga.o
63obj-y += mddi_toshiba_wvga_pt.o
64obj-y += mddi_toshiba_wvga.o
65obj-y += mddi_sharp.o
66else
67obj-$(CONFIG_FB_MSM_MDDI_PRISM_WVGA) += mddi_prism.o
68obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_COMMON) += mddi_toshiba.o
69obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_COMMON_VGA) += mddi_toshiba_vga.o
70obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_WVGA_PORTRAIT) += mddi_toshiba_wvga_pt.o
71obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_WVGA) += mddi_toshiba_wvga.o
72obj-$(CONFIG_FB_MSM_MDDI_SHARP_QVGA_128x128) += mddi_sharp.o
73endif
74
75obj-$(CONFIG_FB_MSM_LCDC_PANEL) += lcdc_panel.o
76obj-$(CONFIG_FB_MSM_LCDC_PRISM_WVGA) += lcdc_prism.o
77obj-$(CONFIG_FB_MSM_LCDC_EXTERNAL_WXGA) += lcdc_external.o
78obj-$(CONFIG_FB_MSM_LCDC_GORDON_VGA) += lcdc_gordon.o
79obj-$(CONFIG_FB_MSM_LCDC_WXGA) += lcdc_wxga.o
80obj-$(CONFIG_FB_MSM_LCDC_TOSHIBA_WVGA_PT) += lcdc_toshiba_wvga_pt.o
81obj-$(CONFIG_FB_MSM_LCDC_SHARP_WVGA_PT) += lcdc_sharp_wvga_pt.o
82obj-$(CONFIG_FB_MSM_LCDC_GRAPEFRUIT_VGA) += lcdc_grapefruit.o
83obj-$(CONFIG_FB_MSM_LCDC_ST1_WXGA) += lcdc_st1_wxga.o
84obj-$(CONFIG_FB_MSM_LCDC_ST15_WXGA) += lcdc_st15.o
85obj-$(CONFIG_FB_MSM_HDMI_SII_EXTERNAL_720P) += hdmi_sii9022.o
86
87obj-$(CONFIG_FB_MSM_TVOUT_NTSC) += tv_ntsc.o
88obj-$(CONFIG_FB_MSM_TVOUT_PAL) += tv_pal.o
89
90obj-$(CONFIG_FB_MSM_EXTMDDI_SVGA) += mddi_ext_lcd.o
91
92clean:
93 rm *.o .*cmd
diff --git a/drivers/staging/msm/TODO b/drivers/staging/msm/TODO
new file mode 100644
index 000000000000..05107a7d516a
--- /dev/null
+++ b/drivers/staging/msm/TODO
@@ -0,0 +1,3 @@
1- Merge this code with the existing MSM framebuffer
2- General style clean ups.
3
diff --git a/drivers/staging/msm/ebi2_l2f.c b/drivers/staging/msm/ebi2_l2f.c
new file mode 100644
index 000000000000..eea891d8f0f8
--- /dev/null
+++ b/drivers/staging/msm/ebi2_l2f.c
@@ -0,0 +1,569 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include "msm_fb.h"
19
20#include <linux/memory.h>
21#include <linux/kernel.h>
22#include <linux/sched.h>
23#include <linux/time.h>
24#include <linux/init.h>
25#include <linux/interrupt.h>
26#include "linux/proc_fs.h"
27
28#include <linux/delay.h>
29
30#include <mach/hardware.h>
31#include <linux/io.h>
32
33#include <asm/system.h>
34#include <asm/mach-types.h>
35
36/* The following are for MSM5100 on Gator
37*/
38#ifdef FEATURE_PM1000
39#include "pm1000.h"
40#endif /* FEATURE_PM1000 */
41/* The following are for MSM6050 on Bambi
42*/
43#ifdef FEATURE_PMIC_LCDKBD_LED_DRIVER
44#include "pm.h"
45#endif /* FEATURE_PMIC_LCDKBD_LED_DRIVER */
46
47#ifdef DISP_DEVICE_18BPP
48#undef DISP_DEVICE_18BPP
49#define DISP_DEVICE_16BPP
50#endif
51
52#define QCIF_WIDTH 176
53#define QCIF_HEIGHT 220
54
55static void *DISP_CMD_PORT;
56static void *DISP_DATA_PORT;
57
58#define DISP_CMD_DISON 0xaf
59#define DISP_CMD_DISOFF 0xae
60#define DISP_CMD_DISNOR 0xa6
61#define DISP_CMD_DISINV 0xa7
62#define DISP_CMD_DISCTL 0xca
63#define DISP_CMD_GCP64 0xcb
64#define DISP_CMD_GCP16 0xcc
65#define DISP_CMD_GSSET 0xcd
66#define DISP_GS_2 0x02
67#define DISP_GS_16 0x01
68#define DISP_GS_64 0x00
69#define DISP_CMD_SLPIN 0x95
70#define DISP_CMD_SLPOUT 0x94
71#define DISP_CMD_SD_PSET 0x75
72#define DISP_CMD_MD_PSET 0x76
73#define DISP_CMD_SD_CSET 0x15
74#define DISP_CMD_MD_CSET 0x16
75#define DISP_CMD_DATCTL 0xbc
76#define DISP_DATCTL_666 0x08
77#define DISP_DATCTL_565 0x28
78#define DISP_DATCTL_444 0x38
79#define DISP_CMD_RAMWR 0x5c
80#define DISP_CMD_RAMRD 0x5d
81#define DISP_CMD_PTLIN 0xa8
82#define DISP_CMD_PTLOUT 0xa9
83#define DISP_CMD_ASCSET 0xaa
84#define DISP_CMD_SCSTART 0xab
85#define DISP_CMD_VOLCTL 0xc6
86#define DISP_VOLCTL_TONE 0x80
87#define DISP_CMD_NOp 0x25
88#define DISP_CMD_OSSEL 0xd0
89#define DISP_CMD_3500KSET 0xd1
90#define DISP_CMD_3500KEND 0xd2
91#define DISP_CMD_14MSET 0xd3
92#define DISP_CMD_14MEND 0xd4
93
94#define DISP_CMD_OUT(cmd) outpw(DISP_CMD_PORT, cmd);
95
96#define DISP_DATA_OUT(data) outpw(DISP_DATA_PORT, data);
97
98#define DISP_DATA_IN() inpw(DISP_DATA_PORT);
99
100/* Epson device column number starts at 2
101*/
102#define DISP_SET_RECT(ulhc_row, lrhc_row, ulhc_col, lrhc_col) \
103 DISP_CMD_OUT(DISP_CMD_SD_PSET) \
104 DISP_DATA_OUT((ulhc_row) & 0xFF) \
105 DISP_DATA_OUT((ulhc_row) >> 8) \
106 DISP_DATA_OUT((lrhc_row) & 0xFF) \
107 DISP_DATA_OUT((lrhc_row) >> 8) \
108 DISP_CMD_OUT(DISP_CMD_SD_CSET) \
109 DISP_DATA_OUT(((ulhc_col)+2) & 0xFF) \
110 DISP_DATA_OUT(((ulhc_col)+2) >> 8) \
111 DISP_DATA_OUT(((lrhc_col)+2) & 0xFF) \
112 DISP_DATA_OUT(((lrhc_col)+2) >> 8)
113
114#define DISP_MIN_CONTRAST 0
115#define DISP_MAX_CONTRAST 127
116#define DISP_DEFAULT_CONTRAST 80
117
118#define DISP_MIN_BACKLIGHT 0
119#define DISP_MAX_BACKLIGHT 15
120#define DISP_DEFAULT_BACKLIGHT 2
121
122#define WAIT_SEC(sec) mdelay((sec)/1000)
123
124static word disp_area_start_row;
125static word disp_area_end_row;
126static byte disp_contrast = DISP_DEFAULT_CONTRAST;
127static boolean disp_powered_up;
128static boolean disp_initialized = FALSE;
129/* For some reason the contrast set at init time is not good. Need to do
130 * it again
131 */
132static boolean display_on = FALSE;
133static void epsonQcif_disp_init(struct platform_device *pdev);
134static void epsonQcif_disp_set_contrast(word contrast);
135static void epsonQcif_disp_set_display_area(word start_row, word end_row);
136static int epsonQcif_disp_off(struct platform_device *pdev);
137static int epsonQcif_disp_on(struct platform_device *pdev);
138static void epsonQcif_disp_set_rect(int x, int y, int xres, int yres);
139
140volatile word databack;
141static void epsonQcif_disp_init(struct platform_device *pdev)
142{
143 struct msm_fb_data_type *mfd;
144
145 int i;
146
147 if (disp_initialized)
148 return;
149
150 mfd = platform_get_drvdata(pdev);
151
152 DISP_CMD_PORT = mfd->cmd_port;
153 DISP_DATA_PORT = mfd->data_port;
154
155 /* Sleep in */
156 DISP_CMD_OUT(DISP_CMD_SLPIN);
157
158 /* Display off */
159 DISP_CMD_OUT(DISP_CMD_DISOFF);
160
161 /* Display normal */
162 DISP_CMD_OUT(DISP_CMD_DISNOR);
163
164 /* Set data mode */
165 DISP_CMD_OUT(DISP_CMD_DATCTL);
166 DISP_DATA_OUT(DISP_DATCTL_565);
167
168 /* Set display timing */
169 DISP_CMD_OUT(DISP_CMD_DISCTL);
170 DISP_DATA_OUT(0x1c); /* p1 */
171 DISP_DATA_OUT(0x02); /* p1 */
172 DISP_DATA_OUT(0x82); /* p2 */
173 DISP_DATA_OUT(0x00); /* p3 */
174 DISP_DATA_OUT(0x00); /* p4 */
175 DISP_DATA_OUT(0xe0); /* p5 */
176 DISP_DATA_OUT(0x00); /* p5 */
177 DISP_DATA_OUT(0xdc); /* p6 */
178 DISP_DATA_OUT(0x00); /* p6 */
179 DISP_DATA_OUT(0x02); /* p7 */
180 DISP_DATA_OUT(0x00); /* p8 */
181
182 /* Set 64 gray scale level */
183 DISP_CMD_OUT(DISP_CMD_GCP64);
184 DISP_DATA_OUT(0x08); /* p01 */
185 DISP_DATA_OUT(0x00);
186 DISP_DATA_OUT(0x2a); /* p02 */
187 DISP_DATA_OUT(0x00);
188 DISP_DATA_OUT(0x4e); /* p03 */
189 DISP_DATA_OUT(0x00);
190 DISP_DATA_OUT(0x6b); /* p04 */
191 DISP_DATA_OUT(0x00);
192 DISP_DATA_OUT(0x88); /* p05 */
193 DISP_DATA_OUT(0x00);
194 DISP_DATA_OUT(0xa3); /* p06 */
195 DISP_DATA_OUT(0x00);
196 DISP_DATA_OUT(0xba); /* p07 */
197 DISP_DATA_OUT(0x00);
198 DISP_DATA_OUT(0xd1); /* p08 */
199 DISP_DATA_OUT(0x00);
200 DISP_DATA_OUT(0xe5); /* p09 */
201 DISP_DATA_OUT(0x00);
202 DISP_DATA_OUT(0xf3); /* p10 */
203 DISP_DATA_OUT(0x00);
204 DISP_DATA_OUT(0x03); /* p11 */
205 DISP_DATA_OUT(0x01);
206 DISP_DATA_OUT(0x13); /* p12 */
207 DISP_DATA_OUT(0x01);
208 DISP_DATA_OUT(0x22); /* p13 */
209 DISP_DATA_OUT(0x01);
210 DISP_DATA_OUT(0x2f); /* p14 */
211 DISP_DATA_OUT(0x01);
212 DISP_DATA_OUT(0x3b); /* p15 */
213 DISP_DATA_OUT(0x01);
214 DISP_DATA_OUT(0x46); /* p16 */
215 DISP_DATA_OUT(0x01);
216 DISP_DATA_OUT(0x51); /* p17 */
217 DISP_DATA_OUT(0x01);
218 DISP_DATA_OUT(0x5b); /* p18 */
219 DISP_DATA_OUT(0x01);
220 DISP_DATA_OUT(0x64); /* p19 */
221 DISP_DATA_OUT(0x01);
222 DISP_DATA_OUT(0x6c); /* p20 */
223 DISP_DATA_OUT(0x01);
224 DISP_DATA_OUT(0x74); /* p21 */
225 DISP_DATA_OUT(0x01);
226 DISP_DATA_OUT(0x7c); /* p22 */
227 DISP_DATA_OUT(0x01);
228 DISP_DATA_OUT(0x83); /* p23 */
229 DISP_DATA_OUT(0x01);
230 DISP_DATA_OUT(0x8a); /* p24 */
231 DISP_DATA_OUT(0x01);
232 DISP_DATA_OUT(0x91); /* p25 */
233 DISP_DATA_OUT(0x01);
234 DISP_DATA_OUT(0x98); /* p26 */
235 DISP_DATA_OUT(0x01);
236 DISP_DATA_OUT(0x9f); /* p27 */
237 DISP_DATA_OUT(0x01);
238 DISP_DATA_OUT(0xa6); /* p28 */
239 DISP_DATA_OUT(0x01);
240 DISP_DATA_OUT(0xac); /* p29 */
241 DISP_DATA_OUT(0x01);
242 DISP_DATA_OUT(0xb2); /* p30 */
243 DISP_DATA_OUT(0x01);
244 DISP_DATA_OUT(0xb7); /* p31 */
245 DISP_DATA_OUT(0x01);
246 DISP_DATA_OUT(0xbc); /* p32 */
247 DISP_DATA_OUT(0x01);
248 DISP_DATA_OUT(0xc1); /* p33 */
249 DISP_DATA_OUT(0x01);
250 DISP_DATA_OUT(0xc6); /* p34 */
251 DISP_DATA_OUT(0x01);
252 DISP_DATA_OUT(0xcb); /* p35 */
253 DISP_DATA_OUT(0x01);
254 DISP_DATA_OUT(0xd0); /* p36 */
255 DISP_DATA_OUT(0x01);
256 DISP_DATA_OUT(0xd4); /* p37 */
257 DISP_DATA_OUT(0x01);
258 DISP_DATA_OUT(0xd8); /* p38 */
259 DISP_DATA_OUT(0x01);
260 DISP_DATA_OUT(0xdc); /* p39 */
261 DISP_DATA_OUT(0x01);
262 DISP_DATA_OUT(0xe0); /* p40 */
263 DISP_DATA_OUT(0x01);
264 DISP_DATA_OUT(0xe4); /* p41 */
265 DISP_DATA_OUT(0x01);
266 DISP_DATA_OUT(0xe8); /* p42 */
267 DISP_DATA_OUT(0x01);
268 DISP_DATA_OUT(0xec); /* p43 */
269 DISP_DATA_OUT(0x01);
270 DISP_DATA_OUT(0xf0); /* p44 */
271 DISP_DATA_OUT(0x01);
272 DISP_DATA_OUT(0xf4); /* p45 */
273 DISP_DATA_OUT(0x01);
274 DISP_DATA_OUT(0xf8); /* p46 */
275 DISP_DATA_OUT(0x01);
276 DISP_DATA_OUT(0xfb); /* p47 */
277 DISP_DATA_OUT(0x01);
278 DISP_DATA_OUT(0xfe); /* p48 */
279 DISP_DATA_OUT(0x01);
280 DISP_DATA_OUT(0x01); /* p49 */
281 DISP_DATA_OUT(0x02);
282 DISP_DATA_OUT(0x03); /* p50 */
283 DISP_DATA_OUT(0x02);
284 DISP_DATA_OUT(0x05); /* p51 */
285 DISP_DATA_OUT(0x02);
286 DISP_DATA_OUT(0x07); /* p52 */
287 DISP_DATA_OUT(0x02);
288 DISP_DATA_OUT(0x09); /* p53 */
289 DISP_DATA_OUT(0x02);
290 DISP_DATA_OUT(0x0b); /* p54 */
291 DISP_DATA_OUT(0x02);
292 DISP_DATA_OUT(0x0d); /* p55 */
293 DISP_DATA_OUT(0x02);
294 DISP_DATA_OUT(0x0f); /* p56 */
295 DISP_DATA_OUT(0x02);
296 DISP_DATA_OUT(0x11); /* p57 */
297 DISP_DATA_OUT(0x02);
298 DISP_DATA_OUT(0x13); /* p58 */
299 DISP_DATA_OUT(0x02);
300 DISP_DATA_OUT(0x15); /* p59 */
301 DISP_DATA_OUT(0x02);
302 DISP_DATA_OUT(0x17); /* p60 */
303 DISP_DATA_OUT(0x02);
304 DISP_DATA_OUT(0x19); /* p61 */
305 DISP_DATA_OUT(0x02);
306 DISP_DATA_OUT(0x1b); /* p62 */
307 DISP_DATA_OUT(0x02);
308 DISP_DATA_OUT(0x1c); /* p63 */
309 DISP_DATA_OUT(0x02);
310
311 /* Set 16 gray scale level */
312 DISP_CMD_OUT(DISP_CMD_GCP16);
313 DISP_DATA_OUT(0x1a); /* p01 */
314 DISP_DATA_OUT(0x32); /* p02 */
315 DISP_DATA_OUT(0x42); /* p03 */
316 DISP_DATA_OUT(0x4c); /* p04 */
317 DISP_DATA_OUT(0x58); /* p05 */
318 DISP_DATA_OUT(0x5f); /* p06 */
319 DISP_DATA_OUT(0x66); /* p07 */
320 DISP_DATA_OUT(0x6b); /* p08 */
321 DISP_DATA_OUT(0x70); /* p09 */
322 DISP_DATA_OUT(0x74); /* p10 */
323 DISP_DATA_OUT(0x78); /* p11 */
324 DISP_DATA_OUT(0x7b); /* p12 */
325 DISP_DATA_OUT(0x7e); /* p13 */
326 DISP_DATA_OUT(0x80); /* p14 */
327 DISP_DATA_OUT(0x82); /* p15 */
328
329 /* Set DSP column */
330 DISP_CMD_OUT(DISP_CMD_MD_CSET);
331 DISP_DATA_OUT(0xff);
332 DISP_DATA_OUT(0x03);
333 DISP_DATA_OUT(0xff);
334 DISP_DATA_OUT(0x03);
335
336 /* Set DSP page */
337 DISP_CMD_OUT(DISP_CMD_MD_PSET);
338 DISP_DATA_OUT(0xff);
339 DISP_DATA_OUT(0x01);
340 DISP_DATA_OUT(0xff);
341 DISP_DATA_OUT(0x01);
342
343 /* Set ARM column */
344 DISP_CMD_OUT(DISP_CMD_SD_CSET);
345 DISP_DATA_OUT(0x02);
346 DISP_DATA_OUT(0x00);
347 DISP_DATA_OUT((QCIF_WIDTH + 1) & 0xFF);
348 DISP_DATA_OUT((QCIF_WIDTH + 1) >> 8);
349
350 /* Set ARM page */
351 DISP_CMD_OUT(DISP_CMD_SD_PSET);
352 DISP_DATA_OUT(0x00);
353 DISP_DATA_OUT(0x00);
354 DISP_DATA_OUT((QCIF_HEIGHT - 1) & 0xFF);
355 DISP_DATA_OUT((QCIF_HEIGHT - 1) >> 8);
356
357 /* Set 64 gray scales */
358 DISP_CMD_OUT(DISP_CMD_GSSET);
359 DISP_DATA_OUT(DISP_GS_64);
360
361 DISP_CMD_OUT(DISP_CMD_OSSEL);
362 DISP_DATA_OUT(0);
363
364 /* Sleep out */
365 DISP_CMD_OUT(DISP_CMD_SLPOUT);
366
367 WAIT_SEC(40000);
368
369 /* Initialize power IC */
370 DISP_CMD_OUT(DISP_CMD_VOLCTL);
371 DISP_DATA_OUT(DISP_VOLCTL_TONE);
372
373 WAIT_SEC(40000);
374
375 /* Set electronic volume, d'xx */
376 DISP_CMD_OUT(DISP_CMD_VOLCTL);
377 DISP_DATA_OUT(DISP_DEFAULT_CONTRAST); /* value from 0 to 127 */
378
379 /* Initialize display data */
380 DISP_SET_RECT(0, (QCIF_HEIGHT - 1), 0, (QCIF_WIDTH - 1));
381 DISP_CMD_OUT(DISP_CMD_RAMWR);
382 for (i = 0; i < QCIF_HEIGHT * QCIF_WIDTH; i++)
383 DISP_DATA_OUT(0xffff);
384
385 DISP_CMD_OUT(DISP_CMD_RAMRD);
386 databack = DISP_DATA_IN();
387 databack = DISP_DATA_IN();
388 databack = DISP_DATA_IN();
389 databack = DISP_DATA_IN();
390
391 WAIT_SEC(80000);
392
393 DISP_CMD_OUT(DISP_CMD_DISON);
394
395 disp_area_start_row = 0;
396 disp_area_end_row = QCIF_HEIGHT - 1;
397 disp_powered_up = TRUE;
398 disp_initialized = TRUE;
399 epsonQcif_disp_set_display_area(0, QCIF_HEIGHT - 1);
400 display_on = TRUE;
401}
402
403static void epsonQcif_disp_set_rect(int x, int y, int xres, int yres)
404{
405 if (!disp_initialized)
406 return;
407
408 DISP_SET_RECT(y, y + yres - 1, x, x + xres - 1);
409 DISP_CMD_OUT(DISP_CMD_RAMWR);
410}
411
412static void epsonQcif_disp_set_display_area(word start_row, word end_row)
413{
414 if (!disp_initialized)
415 return;
416
417 if ((start_row == disp_area_start_row)
418 && (end_row == disp_area_end_row))
419 return;
420 disp_area_start_row = start_row;
421 disp_area_end_row = end_row;
422
423 /* Range checking
424 */
425 if (end_row >= QCIF_HEIGHT)
426 end_row = QCIF_HEIGHT - 1;
427 if (start_row > end_row)
428 start_row = end_row;
429
430 /* When display is not the full screen, gray scale is set to
431 ** 2; otherwise it is set to 64.
432 */
433 if ((start_row == 0) && (end_row == (QCIF_HEIGHT - 1))) {
434 /* The whole screen */
435 DISP_CMD_OUT(DISP_CMD_PTLOUT);
436 WAIT_SEC(10000);
437 DISP_CMD_OUT(DISP_CMD_DISOFF);
438 WAIT_SEC(100000);
439 DISP_CMD_OUT(DISP_CMD_GSSET);
440 DISP_DATA_OUT(DISP_GS_64);
441 WAIT_SEC(100000);
442 DISP_CMD_OUT(DISP_CMD_DISON);
443 } else {
444 /* partial screen */
445 DISP_CMD_OUT(DISP_CMD_PTLIN);
446 DISP_DATA_OUT(start_row);
447 DISP_DATA_OUT(start_row >> 8);
448 DISP_DATA_OUT(end_row);
449 DISP_DATA_OUT(end_row >> 8);
450 DISP_CMD_OUT(DISP_CMD_GSSET);
451 DISP_DATA_OUT(DISP_GS_2);
452 }
453}
454
455static int epsonQcif_disp_off(struct platform_device *pdev)
456{
457 if (!disp_initialized)
458 epsonQcif_disp_init(pdev);
459
460 if (display_on) {
461 DISP_CMD_OUT(DISP_CMD_DISOFF);
462 DISP_CMD_OUT(DISP_CMD_SLPIN);
463 display_on = FALSE;
464 }
465
466 return 0;
467}
468
469static int epsonQcif_disp_on(struct platform_device *pdev)
470{
471 if (!disp_initialized)
472 epsonQcif_disp_init(pdev);
473
474 if (!display_on) {
475 DISP_CMD_OUT(DISP_CMD_SLPOUT);
476 WAIT_SEC(40000);
477 DISP_CMD_OUT(DISP_CMD_DISON);
478 epsonQcif_disp_set_contrast(disp_contrast);
479 display_on = TRUE;
480 }
481
482 return 0;
483}
484
485static void epsonQcif_disp_set_contrast(word contrast)
486{
487 if (!disp_initialized)
488 return;
489
490 /* Initialize power IC, d'24 */
491 DISP_CMD_OUT(DISP_CMD_VOLCTL);
492 DISP_DATA_OUT(DISP_VOLCTL_TONE);
493
494 WAIT_SEC(40000);
495
496 /* Set electronic volume, d'xx */
497 DISP_CMD_OUT(DISP_CMD_VOLCTL);
498 if (contrast > 127)
499 contrast = 127;
500 DISP_DATA_OUT(contrast); /* value from 0 to 127 */
501 disp_contrast = (byte) contrast;
502} /* End disp_set_contrast */
503
504static void epsonQcif_disp_clear_screen_area(
505 word start_row, word end_row, word start_column, word end_column) {
506 int32 i;
507
508 /* Clear the display screen */
509 DISP_SET_RECT(start_row, end_row, start_column, end_column);
510 DISP_CMD_OUT(DISP_CMD_RAMWR);
511 i = (end_row - start_row + 1) * (end_column - start_column + 1);
512 for (; i > 0; i--)
513 DISP_DATA_OUT(0xffff);
514}
515
516static int __init epsonQcif_probe(struct platform_device *pdev)
517{
518 msm_fb_add_device(pdev);
519
520 return 0;
521}
522
523static struct platform_driver this_driver = {
524 .probe = epsonQcif_probe,
525 .driver = {
526 .name = "ebi2_epson_qcif",
527 },
528};
529
530static struct msm_fb_panel_data epsonQcif_panel_data = {
531 .on = epsonQcif_disp_on,
532 .off = epsonQcif_disp_off,
533 .set_rect = epsonQcif_disp_set_rect,
534};
535
536static struct platform_device this_device = {
537 .name = "ebi2_epson_qcif",
538 .id = 0,
539 .dev = {
540 .platform_data = &epsonQcif_panel_data,
541 }
542};
543
544static int __init epsonQcif_init(void)
545{
546 int ret;
547 struct msm_panel_info *pinfo;
548
549 ret = platform_driver_register(&this_driver);
550 if (!ret) {
551 pinfo = &epsonQcif_panel_data.panel_info;
552 pinfo->xres = QCIF_WIDTH;
553 pinfo->yres = QCIF_HEIGHT;
554 pinfo->type = EBI2_PANEL;
555 pinfo->pdest = DISPLAY_2;
556 pinfo->wait_cycle = 0x808000;
557 pinfo->bpp = 16;
558 pinfo->fb_num = 2;
559 pinfo->lcd.vsync_enable = FALSE;
560
561 ret = platform_device_register(&this_device);
562 if (ret)
563 platform_driver_unregister(&this_driver);
564 }
565
566 return ret;
567}
568
569module_init(epsonQcif_init);
diff --git a/drivers/staging/msm/ebi2_lcd.c b/drivers/staging/msm/ebi2_lcd.c
new file mode 100644
index 000000000000..b41e1230ceca
--- /dev/null
+++ b/drivers/staging/msm/ebi2_lcd.c
@@ -0,0 +1,250 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include <linux/module.h>
19#include <linux/moduleparam.h>
20#include <linux/kernel.h>
21#include <linux/slab.h>
22#include <linux/delay.h>
23#include <linux/mm.h>
24#include <linux/fb.h>
25#include <linux/init.h>
26#include <linux/ioport.h>
27#include <linux/device.h>
28#include <linux/dma-mapping.h>
29#include <linux/uaccess.h>
30#include <linux/workqueue.h>
31#include <linux/string.h>
32#include <linux/version.h>
33#include <linux/proc_fs.h>
34#include <linux/vmalloc.h>
35#include <linux/debugfs.h>
36
37#include "msm_fb.h"
38
39static int ebi2_lcd_probe(struct platform_device *pdev);
40static int ebi2_lcd_remove(struct platform_device *pdev);
41
42static struct platform_driver ebi2_lcd_driver = {
43 .probe = ebi2_lcd_probe,
44 .remove = ebi2_lcd_remove,
45 .suspend = NULL,
46 .suspend_late = NULL,
47 .resume_early = NULL,
48 .resume = NULL,
49 .shutdown = NULL,
50 .driver = {
51 .name = "ebi2_lcd",
52 },
53};
54
55static void *ebi2_base;
56static void *ebi2_lcd_cfg0;
57static void *ebi2_lcd_cfg1;
58static void __iomem *lcd01_base;
59static void __iomem *lcd02_base;
60static int ebi2_lcd_resource_initialized;
61
62static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
63static int pdev_list_cnt;
64
65static int ebi2_lcd_probe(struct platform_device *pdev)
66{
67 struct msm_fb_data_type *mfd;
68 struct platform_device *mdp_dev = NULL;
69 struct msm_fb_panel_data *pdata = NULL;
70 int rc, i;
71
72 if (pdev->id == 0) {
73 for (i = 0; i < pdev->num_resources; i++) {
74 if (!strncmp(pdev->resource[i].name, "base", 4)) {
75 ebi2_base = ioremap(pdev->resource[i].start,
76 pdev->resource[i].end -
77 pdev->resource[i].start + 1);
78 if (!ebi2_base) {
79 printk(KERN_ERR
80 "ebi2_base ioremap failed!\n");
81 return -ENOMEM;
82 }
83 ebi2_lcd_cfg0 = (void *)(ebi2_base + 0x20);
84 ebi2_lcd_cfg1 = (void *)(ebi2_base + 0x24);
85 } else if (!strncmp(pdev->resource[i].name,
86 "lcd01", 5)) {
87 lcd01_base = ioremap(pdev->resource[i].start,
88 pdev->resource[i].end -
89 pdev->resource[i].start + 1);
90 if (!lcd01_base) {
91 printk(KERN_ERR
92 "lcd01_base ioremap failed!\n");
93 return -ENOMEM;
94 }
95 } else if (!strncmp(pdev->resource[i].name,
96 "lcd02", 5)) {
97 lcd02_base = ioremap(pdev->resource[i].start,
98 pdev->resource[i].end -
99 pdev->resource[i].start + 1);
100 if (!lcd02_base) {
101 printk(KERN_ERR
102 "lcd02_base ioremap failed!\n");
103 return -ENOMEM;
104 }
105 }
106 }
107 ebi2_lcd_resource_initialized = 1;
108 return 0;
109 }
110
111 if (!ebi2_lcd_resource_initialized)
112 return -EPERM;
113
114 mfd = platform_get_drvdata(pdev);
115
116 if (!mfd)
117 return -ENODEV;
118
119 if (mfd->key != MFD_KEY)
120 return -EINVAL;
121
122 if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
123 return -ENOMEM;
124
125 if (ebi2_base == NULL)
126 return -ENOMEM;
127
128 mdp_dev = platform_device_alloc("mdp", pdev->id);
129 if (!mdp_dev)
130 return -ENOMEM;
131
132 /* link to the latest pdev */
133 mfd->pdev = mdp_dev;
134 mfd->dest = DISPLAY_LCD;
135
136 /* add panel data */
137 if (platform_device_add_data
138 (mdp_dev, pdev->dev.platform_data,
139 sizeof(struct msm_fb_panel_data))) {
140 printk(KERN_ERR "ebi2_lcd_probe: platform_device_add_data failed!\n");
141 platform_device_put(mdp_dev);
142 return -ENOMEM;
143 }
144
145 /* data chain */
146 pdata = mdp_dev->dev.platform_data;
147 pdata->on = panel_next_on;
148 pdata->off = panel_next_off;
149 pdata->next = pdev;
150
151 /* get/set panel specific fb info */
152 mfd->panel_info = pdata->panel_info;
153
154 if (mfd->panel_info.bpp == 24)
155 mfd->fb_imgType = MDP_RGB_888;
156 else
157 mfd->fb_imgType = MDP_RGB_565;
158
159 /* config msm ebi2 lcd register */
160 if (mfd->panel_info.pdest == DISPLAY_1) {
161 outp32(ebi2_base,
162 (inp32(ebi2_base) & (~(EBI2_PRIM_LCD_CLR))) |
163 EBI2_PRIM_LCD_SEL);
164 /*
165 * current design has one set of cfg0/1 register to control
166 * both EBI2 channels. so, we're using the PRIM channel to
167 * configure both.
168 */
169 outp32(ebi2_lcd_cfg0, mfd->panel_info.wait_cycle);
170 if (mfd->panel_info.bpp == 18)
171 outp32(ebi2_lcd_cfg1, 0x01000000);
172 else
173 outp32(ebi2_lcd_cfg1, 0x0);
174 } else {
175#ifdef DEBUG_EBI2_LCD
176 /*
177 * confliting with QCOM SURF FPGA CS.
178 * OEM should enable below for their CS mapping
179 */
180 outp32(ebi2_base, (inp32(ebi2_base)&(~(EBI2_SECD_LCD_CLR)))
181 |EBI2_SECD_LCD_SEL);
182#endif
183 }
184
185 /*
186 * map cs (chip select) address
187 */
188 if (mfd->panel_info.pdest == DISPLAY_1) {
189 mfd->cmd_port = lcd01_base;
190 mfd->data_port =
191 (void *)((uint32) mfd->cmd_port + EBI2_PRIM_LCD_RS_PIN);
192 mfd->data_port_phys =
193 (void *)(LCD_PRIM_BASE_PHYS + EBI2_PRIM_LCD_RS_PIN);
194 } else {
195 mfd->cmd_port = lcd01_base;
196 mfd->data_port =
197 (void *)((uint32) mfd->cmd_port + EBI2_SECD_LCD_RS_PIN);
198 mfd->data_port_phys =
199 (void *)(LCD_SECD_BASE_PHYS + EBI2_SECD_LCD_RS_PIN);
200 }
201
202 /*
203 * set driver data
204 */
205 platform_set_drvdata(mdp_dev, mfd);
206
207 /*
208 * register in mdp driver
209 */
210 rc = platform_device_add(mdp_dev);
211 if (rc) {
212 goto ebi2_lcd_probe_err;
213 }
214
215 pdev_list[pdev_list_cnt++] = pdev;
216 return 0;
217
218 ebi2_lcd_probe_err:
219 platform_device_put(mdp_dev);
220 return rc;
221}
222
223static int ebi2_lcd_remove(struct platform_device *pdev)
224{
225 struct msm_fb_data_type *mfd;
226
227 mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
228
229 if (!mfd)
230 return 0;
231
232 if (mfd->key != MFD_KEY)
233 return 0;
234
235 iounmap(mfd->cmd_port);
236
237 return 0;
238}
239
240static int ebi2_lcd_register_driver(void)
241{
242 return platform_driver_register(&ebi2_lcd_driver);
243}
244
245static int __init ebi2_lcd_driver_init(void)
246{
247 return ebi2_lcd_register_driver();
248}
249
250module_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
index 000000000000..d66d03978253
--- /dev/null
+++ b/drivers/staging/msm/ebi2_tmd20.c
@@ -0,0 +1,1122 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include "msm_fb.h"
19
20#include <linux/memory.h>
21#include <linux/kernel.h>
22#include <linux/sched.h>
23#include <linux/time.h>
24#include <linux/init.h>
25#include <linux/interrupt.h>
26#include "linux/proc_fs.h"
27
28#include <linux/delay.h>
29
30#include <mach/hardware.h>
31#include <linux/io.h>
32
33#include <asm/system.h>
34#include <asm/mach-types.h>
35
36/* #define TMD20QVGA_LCD_18BPP */
37#define QVGA_WIDTH 240
38#define QVGA_HEIGHT 320
39
40#ifdef TMD20QVGA_LCD_18BPP
41#define DISP_QVGA_18BPP(x) ((((x)<<2) & 0x3FC00)|(( (x)<<1)& 0x1FE))
42#define DISP_REG(name) uint32 register_##name;
43#define OUTPORT(x, y) outpdw(x, y)
44#define INPORT(x) inpdw(x)
45#else
46#define DISP_QVGA_18BPP(x) (x)
47#define DISP_REG(name) uint16 register_##name;
48#define OUTPORT(x, y) outpw(x, y)
49#define INPORT(x) intpw(x)
50#endif
51
52static void *DISP_CMD_PORT;
53static void *DISP_DATA_PORT;
54
55#define DISP_RNTI 0x10
56
57#define DISP_CMD_OUT(cmd) OUTPORT(DISP_CMD_PORT, DISP_QVGA_18BPP(cmd))
58#define DISP_DATA_OUT(data) OUTPORT(DISP_DATA_PORT, data)
59#define DISP_DATA_IN() INPORT(DISP_DATA_PORT)
60
61#if (defined(TMD20QVGA_LCD_18BPP))
62#define DISP_DATA_OUT_16TO18BPP(x) \
63 DISP_DATA_OUT((((x)&0xf800)<<2|((x)&0x80000)>>3) \
64 | (((x)&0x7e0)<<1) \
65 | (((x)&0x1F)<<1|((x)&0x10)>>4))
66#else
67#define DISP_DATA_OUT_16TO18BPP(x) \
68 DISP_DATA_OUT(x)
69#endif
70
71#define DISP_WRITE_OUT(addr, data) \
72 register_##addr = DISP_QVGA_18BPP(data); \
73 DISP_CMD_OUT(addr); \
74 DISP_DATA_OUT(register_##addr);
75
76#define DISP_UPDATE_VALUE(addr, bitmask, data) \
77 DISP_WRITE_OUT(##addr, (register_##addr & ~(bitmask)) | (data));
78
79#define DISP_VAL_IF(bitvalue, bitmask) \
80 ((bitvalue) ? (bitmask) : 0)
81
82/* QVGA = 256 x 320 */
83/* actual display is 240 x 320...offset by 0x10 */
84#define DISP_ROW_COL_TO_ADDR(row, col) ((row) * 0x100 + col)
85#define DISP_SET_RECT(ulhc_row, lrhc_row, ulhc_col, lrhc_col) \
86 { \
87 DISP_WRITE_OUT(DISP_HORZ_RAM_ADDR_POS_1_ADDR, (ulhc_col) + tmd20qvga_panel_offset); \
88 DISP_WRITE_OUT(DISP_HORZ_RAM_ADDR_POS_2_ADDR, (lrhc_col) + tmd20qvga_panel_offset); \
89 DISP_WRITE_OUT(DISP_VERT_RAM_ADDR_POS_1_ADDR, (ulhc_row)); \
90 DISP_WRITE_OUT(DISP_VERT_RAM_ADDR_POS_2_ADDR, (lrhc_row)); \
91 DISP_WRITE_OUT(DISP_RAM_ADDR_SET_1_ADDR, (ulhc_col) + tmd20qvga_panel_offset); \
92 DISP_WRITE_OUT(DISP_RAM_ADDR_SET_2_ADDR, (ulhc_row)); \
93 }
94
95#define WAIT_MSEC(msec) mdelay(msec)
96
97/*
98 * TMD QVGA Address
99 */
100/* Display Control */
101#define DISP_START_OSCILLATION_ADDR 0x000
102DISP_REG(DISP_START_OSCILLATION_ADDR)
103#define DISP_DRIVER_OUTPUT_CTL_ADDR 0x001
104 DISP_REG(DISP_DRIVER_OUTPUT_CTL_ADDR)
105#define DISP_LCD_DRIVING_SIG_ADDR 0x002
106 DISP_REG(DISP_LCD_DRIVING_SIG_ADDR)
107#define DISP_ENTRY_MODE_ADDR 0x003
108 DISP_REG(DISP_ENTRY_MODE_ADDR)
109#define DISP_DISPLAY_CTL_1_ADDR 0x007
110 DISP_REG(DISP_DISPLAY_CTL_1_ADDR)
111#define DISP_DISPLAY_CTL_2_ADDR 0x008
112 DISP_REG(DISP_DISPLAY_CTL_2_ADDR)
113
114/* DISPLAY MODE 0x009 partial display not supported */
115#define DISP_POWER_SUPPLY_INTF_ADDR 0x00A
116 DISP_REG(DISP_POWER_SUPPLY_INTF_ADDR)
117
118/* DISPLAY MODE 0x00B xZoom feature is not supported */
119#define DISP_EXT_DISPLAY_CTL_1_ADDR 0x00C
120 DISP_REG(DISP_EXT_DISPLAY_CTL_1_ADDR)
121
122#define DISP_FRAME_CYCLE_CTL_ADDR 0x00D
123 DISP_REG(DISP_FRAME_CYCLE_CTL_ADDR)
124
125#define DISP_EXT_DISPLAY_CTL_2_ADDR 0x00E
126 DISP_REG(DISP_EXT_DISPLAY_CTL_2_ADDR)
127
128#define DISP_EXT_DISPLAY_CTL_3_ADDR 0x00F
129 DISP_REG(DISP_EXT_DISPLAY_CTL_3_ADDR)
130
131#define DISP_LTPS_CTL_1_ADDR 0x012
132 DISP_REG(DISP_LTPS_CTL_1_ADDR)
133#define DISP_LTPS_CTL_2_ADDR 0x013
134 DISP_REG(DISP_LTPS_CTL_2_ADDR)
135#define DISP_LTPS_CTL_3_ADDR 0x014
136 DISP_REG(DISP_LTPS_CTL_3_ADDR)
137#define DISP_LTPS_CTL_4_ADDR 0x018
138 DISP_REG(DISP_LTPS_CTL_4_ADDR)
139#define DISP_LTPS_CTL_5_ADDR 0x019
140 DISP_REG(DISP_LTPS_CTL_5_ADDR)
141#define DISP_LTPS_CTL_6_ADDR 0x01A
142 DISP_REG(DISP_LTPS_CTL_6_ADDR)
143#define DISP_AMP_SETTING_ADDR 0x01C
144 DISP_REG(DISP_AMP_SETTING_ADDR)
145#define DISP_MODE_SETTING_ADDR 0x01D
146 DISP_REG(DISP_MODE_SETTING_ADDR)
147#define DISP_POFF_LN_SETTING_ADDR 0x01E
148 DISP_REG(DISP_POFF_LN_SETTING_ADDR)
149/* Power Contol */
150#define DISP_POWER_CTL_1_ADDR 0x100
151 DISP_REG(DISP_POWER_CTL_1_ADDR)
152#define DISP_POWER_CTL_2_ADDR 0x101
153 DISP_REG(DISP_POWER_CTL_2_ADDR)
154#define DISP_POWER_CTL_3_ADDR 0x102
155 DISP_REG(DISP_POWER_CTL_3_ADDR)
156#define DISP_POWER_CTL_4_ADDR 0x103
157 DISP_REG(DISP_POWER_CTL_4_ADDR)
158#define DISP_POWER_CTL_5_ADDR 0x104
159 DISP_REG(DISP_POWER_CTL_5_ADDR)
160#define DISP_POWER_CTL_6_ADDR 0x105
161 DISP_REG(DISP_POWER_CTL_6_ADDR)
162#define DISP_POWER_CTL_7_ADDR 0x106
163 DISP_REG(DISP_POWER_CTL_7_ADDR)
164/* RAM Access */
165#define DISP_RAM_ADDR_SET_1_ADDR 0x200
166 DISP_REG(DISP_RAM_ADDR_SET_1_ADDR)
167#define DISP_RAM_ADDR_SET_2_ADDR 0x201
168 DISP_REG(DISP_RAM_ADDR_SET_2_ADDR)
169#define DISP_CMD_RAMRD DISP_CMD_RAMWR
170#define DISP_CMD_RAMWR 0x202
171 DISP_REG(DISP_CMD_RAMWR)
172#define DISP_RAM_DATA_MASK_1_ADDR 0x203
173 DISP_REG(DISP_RAM_DATA_MASK_1_ADDR)
174#define DISP_RAM_DATA_MASK_2_ADDR 0x204
175 DISP_REG(DISP_RAM_DATA_MASK_2_ADDR)
176/* Gamma Control, Contrast, Gray Scale Setting */
177#define DISP_GAMMA_CONTROL_1_ADDR 0x300
178 DISP_REG(DISP_GAMMA_CONTROL_1_ADDR)
179#define DISP_GAMMA_CONTROL_2_ADDR 0x301
180 DISP_REG(DISP_GAMMA_CONTROL_2_ADDR)
181#define DISP_GAMMA_CONTROL_3_ADDR 0x302
182 DISP_REG(DISP_GAMMA_CONTROL_3_ADDR)
183#define DISP_GAMMA_CONTROL_4_ADDR 0x303
184 DISP_REG(DISP_GAMMA_CONTROL_4_ADDR)
185#define DISP_GAMMA_CONTROL_5_ADDR 0x304
186 DISP_REG(DISP_GAMMA_CONTROL_5_ADDR)
187/* Coordinate Control */
188#define DISP_VERT_SCROLL_CTL_1_ADDR 0x400
189 DISP_REG(DISP_VERT_SCROLL_CTL_1_ADDR)
190#define DISP_VERT_SCROLL_CTL_2_ADDR 0x401
191 DISP_REG(DISP_VERT_SCROLL_CTL_2_ADDR)
192#define DISP_SCREEN_1_DRV_POS_1_ADDR 0x402
193 DISP_REG(DISP_SCREEN_1_DRV_POS_1_ADDR)
194#define DISP_SCREEN_1_DRV_POS_2_ADDR 0x403
195 DISP_REG(DISP_SCREEN_1_DRV_POS_2_ADDR)
196#define DISP_SCREEN_2_DRV_POS_1_ADDR 0x404
197 DISP_REG(DISP_SCREEN_2_DRV_POS_1_ADDR)
198#define DISP_SCREEN_2_DRV_POS_2_ADDR 0x405
199 DISP_REG(DISP_SCREEN_2_DRV_POS_2_ADDR)
200#define DISP_HORZ_RAM_ADDR_POS_1_ADDR 0x406
201 DISP_REG(DISP_HORZ_RAM_ADDR_POS_1_ADDR)
202#define DISP_HORZ_RAM_ADDR_POS_2_ADDR 0x407
203 DISP_REG(DISP_HORZ_RAM_ADDR_POS_2_ADDR)
204#define DISP_VERT_RAM_ADDR_POS_1_ADDR 0x408
205 DISP_REG(DISP_VERT_RAM_ADDR_POS_1_ADDR)
206#define DISP_VERT_RAM_ADDR_POS_2_ADDR 0x409
207 DISP_REG(DISP_VERT_RAM_ADDR_POS_2_ADDR)
208#define DISP_TMD_700_ADDR 0x700 /* 0x700 */
209 DISP_REG(DISP_TMD_700_ADDR)
210#define DISP_TMD_015_ADDR 0x015 /* 0x700 */
211 DISP_REG(DISP_TMD_015_ADDR)
212#define DISP_TMD_305_ADDR 0x305 /* 0x700 */
213 DISP_REG(DISP_TMD_305_ADDR)
214
215/*
216 * TMD QVGA Bit Definations
217 */
218
219#define DISP_BIT_IB15 0x8000
220#define DISP_BIT_IB14 0x4000
221#define DISP_BIT_IB13 0x2000
222#define DISP_BIT_IB12 0x1000
223#define DISP_BIT_IB11 0x0800
224#define DISP_BIT_IB10 0x0400
225#define DISP_BIT_IB09 0x0200
226#define DISP_BIT_IB08 0x0100
227#define DISP_BIT_IB07 0x0080
228#define DISP_BIT_IB06 0x0040
229#define DISP_BIT_IB05 0x0020
230#define DISP_BIT_IB04 0x0010
231#define DISP_BIT_IB03 0x0008
232#define DISP_BIT_IB02 0x0004
233#define DISP_BIT_IB01 0x0002
234#define DISP_BIT_IB00 0x0001
235/*
236 * Display Control
237 * DISP_START_OSCILLATION_ADDR Start Oscillation
238 * DISP_DRIVER_OUTPUT_CTL_ADDR Driver Output Control
239 */
240#define DISP_BITMASK_SS DISP_BIT_IB08
241#define DISP_BITMASK_NL5 DISP_BIT_IB05
242#define DISP_BITMASK_NL4 DISP_BIT_IB04
243#define DISP_BITMASK_NL3 DISP_BIT_IB03
244#define DISP_BITMASK_NL2 DISP_BIT_IB02
245#define DISP_BITMASK_NL1 DISP_BIT_IB01
246#define DISP_BITMASK_NL0 DISP_BIT_IB00
247/* DISP_LCD_DRIVING_SIG_ADDR LCD Driving Signal Setting */
248#define DISP_BITMASK_BC DISP_BIT_IB09
249/* DISP_ENTRY_MODE_ADDR Entry Mode */
250#define DISP_BITMASK_TRI DISP_BIT_IB15
251#define DISP_BITMASK_DFM1 DISP_BIT_IB14
252#define DISP_BITMASK_DFM0 DISP_BIT_IB13
253#define DISP_BITMASK_BGR DISP_BIT_IB12
254#define DISP_BITMASK_HWM0 DISP_BIT_IB08
255#define DISP_BITMASK_ID1 DISP_BIT_IB05
256#define DISP_BITMASK_ID0 DISP_BIT_IB04
257#define DISP_BITMASK_AM DISP_BIT_IB03
258/* DISP_DISPLAY_CTL_1_ADDR Display Control (1) */
259#define DISP_BITMASK_COL1 DISP_BIT_IB15
260#define DISP_BITMASK_COL0 DISP_BIT_IB14
261#define DISP_BITMASK_VLE2 DISP_BIT_IB10
262#define DISP_BITMASK_VLE1 DISP_BIT_IB09
263#define DISP_BITMASK_SPT DISP_BIT_IB08
264#define DISP_BITMASK_PT1 DISP_BIT_IB07
265#define DISP_BITMASK_PT0 DISP_BIT_IB06
266#define DISP_BITMASK_REV DISP_BIT_IB02
267/* DISP_DISPLAY_CTL_2_ADDR Display Control (2) */
268#define DISP_BITMASK_FP3 DISP_BIT_IB11
269#define DISP_BITMASK_FP2 DISP_BIT_IB10
270#define DISP_BITMASK_FP1 DISP_BIT_IB09
271#define DISP_BITMASK_FP0 DISP_BIT_IB08
272#define DISP_BITMASK_BP3 DISP_BIT_IB03
273#define DISP_BITMASK_BP2 DISP_BIT_IB02
274#define DISP_BITMASK_BP1 DISP_BIT_IB01
275#define DISP_BITMASK_BP0 DISP_BIT_IB00
276/* DISP_POWER_SUPPLY_INTF_ADDR Power Supply IC Interface Control */
277#define DISP_BITMASK_CSE DISP_BIT_IB12
278#define DISP_BITMASK_TE DISP_BIT_IB08
279#define DISP_BITMASK_IX3 DISP_BIT_IB03
280#define DISP_BITMASK_IX2 DISP_BIT_IB02
281#define DISP_BITMASK_IX1 DISP_BIT_IB01
282#define DISP_BITMASK_IX0 DISP_BIT_IB00
283/* DISP_EXT_DISPLAY_CTL_1_ADDR External Display Interface Control (1) */
284#define DISP_BITMASK_RM DISP_BIT_IB08
285#define DISP_BITMASK_DM1 DISP_BIT_IB05
286#define DISP_BITMASK_DM0 DISP_BIT_IB04
287#define DISP_BITMASK_RIM1 DISP_BIT_IB01
288#define DISP_BITMASK_RIM0 DISP_BIT_IB00
289/* DISP_FRAME_CYCLE_CTL_ADDR Frame Frequency Adjustment Control */
290#define DISP_BITMASK_DIVI1 DISP_BIT_IB09
291#define DISP_BITMASK_DIVI0 DISP_BIT_IB08
292#define DISP_BITMASK_RTNI4 DISP_BIT_IB04
293#define DISP_BITMASK_RTNI3 DISP_BIT_IB03
294#define DISP_BITMASK_RTNI2 DISP_BIT_IB02
295#define DISP_BITMASK_RTNI1 DISP_BIT_IB01
296#define DISP_BITMASK_RTNI0 DISP_BIT_IB00
297/* DISP_EXT_DISPLAY_CTL_2_ADDR External Display Interface Control (2) */
298#define DISP_BITMASK_DIVE1 DISP_BIT_IB09
299#define DISP_BITMASK_DIVE0 DISP_BIT_IB08
300#define DISP_BITMASK_RTNE7 DISP_BIT_IB07
301#define DISP_BITMASK_RTNE6 DISP_BIT_IB06
302#define DISP_BITMASK_RTNE5 DISP_BIT_IB05
303#define DISP_BITMASK_RTNE4 DISP_BIT_IB04
304#define DISP_BITMASK_RTNE3 DISP_BIT_IB03
305#define DISP_BITMASK_RTNE2 DISP_BIT_IB02
306#define DISP_BITMASK_RTNE1 DISP_BIT_IB01
307#define DISP_BITMASK_RTNE0 DISP_BIT_IB00
308/* DISP_EXT_DISPLAY_CTL_3_ADDR External Display Interface Control (3) */
309#define DISP_BITMASK_VSPL DISP_BIT_IB04
310#define DISP_BITMASK_HSPL DISP_BIT_IB03
311#define DISP_BITMASK_VPL DISP_BIT_IB02
312#define DISP_BITMASK_EPL DISP_BIT_IB01
313#define DISP_BITMASK_DPL DISP_BIT_IB00
314/* DISP_LTPS_CTL_1_ADDR LTPS Interface Control (1) */
315#define DISP_BITMASK_CLWI3 DISP_BIT_IB11
316#define DISP_BITMASK_CLWI2 DISP_BIT_IB10
317#define DISP_BITMASK_CLWI1 DISP_BIT_IB09
318#define DISP_BITMASK_CLWI0 DISP_BIT_IB08
319#define DISP_BITMASK_CLTI1 DISP_BIT_IB01
320#define DISP_BITMASK_CLTI0 DISP_BIT_IB00
321/* DISP_LTPS_CTL_2_ADDR LTPS Interface Control (2) */
322#define DISP_BITMASK_OEVBI1 DISP_BIT_IB09
323#define DISP_BITMASK_OEVBI0 DISP_BIT_IB08
324#define DISP_BITMASK_OEVFI1 DISP_BIT_IB01
325#define DISP_BITMASK_OEVFI0 DISP_BIT_IB00
326/* DISP_LTPS_CTL_3_ADDR LTPS Interface Control (3) */
327#define DISP_BITMASK_SHI1 DISP_BIT_IB01
328#define DISP_BITMASK_SHI0 DISP_BIT_IB00
329/* DISP_LTPS_CTL_4_ADDR LTPS Interface Control (4) */
330#define DISP_BITMASK_CLWE5 DISP_BIT_IB13
331#define DISP_BITMASK_CLWE4 DISP_BIT_IB12
332#define DISP_BITMASK_CLWE3 DISP_BIT_IB11
333#define DISP_BITMASK_CLWE2 DISP_BIT_IB10
334#define DISP_BITMASK_CLWE1 DISP_BIT_IB09
335#define DISP_BITMASK_CLWE0 DISP_BIT_IB08
336#define DISP_BITMASK_CLTE3 DISP_BIT_IB03
337#define DISP_BITMASK_CLTE2 DISP_BIT_IB02
338#define DISP_BITMASK_CLTE1 DISP_BIT_IB01
339#define DISP_BITMASK_CLTE0 DISP_BIT_IB00
340/* DISP_LTPS_CTL_5_ADDR LTPS Interface Control (5) */
341#define DISP_BITMASK_OEVBE3 DISP_BIT_IB11
342#define DISP_BITMASK_OEVBE2 DISP_BIT_IB10
343#define DISP_BITMASK_OEVBE1 DISP_BIT_IB09
344#define DISP_BITMASK_OEVBE0 DISP_BIT_IB08
345#define DISP_BITMASK_OEVFE3 DISP_BIT_IB03
346#define DISP_BITMASK_OEVFE2 DISP_BIT_IB02
347#define DISP_BITMASK_OEVFE1 DISP_BIT_IB01
348#define DISP_BITMASK_OEVFE0 DISP_BIT_IB00
349/* DISP_LTPS_CTL_6_ADDR LTPS Interface Control (6) */
350#define DISP_BITMASK_SHE3 DISP_BIT_IB03
351#define DISP_BITMASK_SHE2 DISP_BIT_IB02
352#define DISP_BITMASK_SHE1 DISP_BIT_IB01
353#define DISP_BITMASK_SHE0 DISP_BIT_IB00
354/* DISP_AMP_SETTING_ADDR Amplify Setting */
355#define DISP_BITMASK_ABSW1 DISP_BIT_IB01
356#define DISP_BITMASK_ABSW0 DISP_BIT_IB00
357/* DISP_MODE_SETTING_ADDR Mode Setting */
358#define DISP_BITMASK_DSTB DISP_BIT_IB02
359#define DISP_BITMASK_STB DISP_BIT_IB00
360/* DISP_POFF_LN_SETTING_ADDR Power Off Line Setting */
361#define DISP_BITMASK_POFH3 DISP_BIT_IB03
362#define DISP_BITMASK_POFH2 DISP_BIT_IB02
363#define DISP_BITMASK_POFH1 DISP_BIT_IB01
364#define DISP_BITMASK_POFH0 DISP_BIT_IB00
365
366/* Power Contol */
367/* DISP_POWER_CTL_1_ADDR Power Control (1) */
368#define DISP_BITMASK_PO DISP_BIT_IB11
369#define DISP_BITMASK_VCD DISP_BIT_IB09
370#define DISP_BITMASK_VSC DISP_BIT_IB08
371#define DISP_BITMASK_CON DISP_BIT_IB07
372#define DISP_BITMASK_ASW1 DISP_BIT_IB06
373#define DISP_BITMASK_ASW0 DISP_BIT_IB05
374#define DISP_BITMASK_OEV DISP_BIT_IB04
375#define DISP_BITMASK_OEVE DISP_BIT_IB03
376#define DISP_BITMASK_FR DISP_BIT_IB02
377#define DISP_BITMASK_D1 DISP_BIT_IB01
378#define DISP_BITMASK_D0 DISP_BIT_IB00
379/* DISP_POWER_CTL_2_ADDR Power Control (2) */
380#define DISP_BITMASK_DC4 DISP_BIT_IB15
381#define DISP_BITMASK_DC3 DISP_BIT_IB14
382#define DISP_BITMASK_SAP2 DISP_BIT_IB13
383#define DISP_BITMASK_SAP1 DISP_BIT_IB12
384#define DISP_BITMASK_SAP0 DISP_BIT_IB11
385#define DISP_BITMASK_BT2 DISP_BIT_IB10
386#define DISP_BITMASK_BT1 DISP_BIT_IB09
387#define DISP_BITMASK_BT0 DISP_BIT_IB08
388#define DISP_BITMASK_DC2 DISP_BIT_IB07
389#define DISP_BITMASK_DC1 DISP_BIT_IB06
390#define DISP_BITMASK_DC0 DISP_BIT_IB05
391#define DISP_BITMASK_AP2 DISP_BIT_IB04
392#define DISP_BITMASK_AP1 DISP_BIT_IB03
393#define DISP_BITMASK_AP0 DISP_BIT_IB02
394/* DISP_POWER_CTL_3_ADDR Power Control (3) */
395#define DISP_BITMASK_VGL4 DISP_BIT_IB10
396#define DISP_BITMASK_VGL3 DISP_BIT_IB09
397#define DISP_BITMASK_VGL2 DISP_BIT_IB08
398#define DISP_BITMASK_VGL1 DISP_BIT_IB07
399#define DISP_BITMASK_VGL0 DISP_BIT_IB06
400#define DISP_BITMASK_VGH4 DISP_BIT_IB04
401#define DISP_BITMASK_VGH3 DISP_BIT_IB03
402#define DISP_BITMASK_VGH2 DISP_BIT_IB02
403#define DISP_BITMASK_VGH1 DISP_BIT_IB01
404#define DISP_BITMASK_VGH0 DISP_BIT_IB00
405/* DISP_POWER_CTL_4_ADDR Power Control (4) */
406#define DISP_BITMASK_VC2 DISP_BIT_IB02
407#define DISP_BITMASK_VC1 DISP_BIT_IB01
408#define DISP_BITMASK_VC0 DISP_BIT_IB00
409/* DISP_POWER_CTL_5_ADDR Power Control (5) */
410#define DISP_BITMASK_VRL3 DISP_BIT_IB11
411#define DISP_BITMASK_VRL2 DISP_BIT_IB10
412#define DISP_BITMASK_VRL1 DISP_BIT_IB09
413#define DISP_BITMASK_VRL0 DISP_BIT_IB08
414#define DISP_BITMASK_PON DISP_BIT_IB04
415#define DISP_BITMASK_VRH3 DISP_BIT_IB03
416#define DISP_BITMASK_VRH2 DISP_BIT_IB02
417#define DISP_BITMASK_VRH1 DISP_BIT_IB01
418#define DISP_BITMASK_VRH0 DISP_BIT_IB00
419/* DISP_POWER_CTL_6_ADDR Power Control (6) */
420#define DISP_BITMASK_VCOMG DISP_BIT_IB13
421#define DISP_BITMASK_VDV4 DISP_BIT_IB12
422#define DISP_BITMASK_VDV3 DISP_BIT_IB11
423#define DISP_BITMASK_VDV2 DISP_BIT_IB10
424#define DISP_BITMASK_VDV1 DISP_BIT_IB09
425#define DISP_BITMASK_VDV0 DISP_BIT_IB08
426#define DISP_BITMASK_VCM4 DISP_BIT_IB04
427#define DISP_BITMASK_VCM3 DISP_BIT_IB03
428#define DISP_BITMASK_VCM2 DISP_BIT_IB02
429#define DISP_BITMASK_VCM1 DISP_BIT_IB01
430#define DISP_BITMASK_VCM0 DISP_BIT_IB00
431/* RAM Access */
432/* DISP_RAM_ADDR_SET_1_ADDR RAM Address Set (1) */
433#define DISP_BITMASK_AD7 DISP_BIT_IB07
434#define DISP_BITMASK_AD6 DISP_BIT_IB06
435#define DISP_BITMASK_AD5 DISP_BIT_IB05
436#define DISP_BITMASK_AD4 DISP_BIT_IB04
437#define DISP_BITMASK_AD3 DISP_BIT_IB03
438#define DISP_BITMASK_AD2 DISP_BIT_IB02
439#define DISP_BITMASK_AD1 DISP_BIT_IB01
440#define DISP_BITMASK_AD0 DISP_BIT_IB00
441/* DISP_RAM_ADDR_SET_2_ADDR RAM Address Set (2) */
442#define DISP_BITMASK_AD16 DISP_BIT_IB08
443#define DISP_BITMASK_AD15 DISP_BIT_IB07
444#define DISP_BITMASK_AD14 DISP_BIT_IB06
445#define DISP_BITMASK_AD13 DISP_BIT_IB05
446#define DISP_BITMASK_AD12 DISP_BIT_IB04
447#define DISP_BITMASK_AD11 DISP_BIT_IB03
448#define DISP_BITMASK_AD10 DISP_BIT_IB02
449#define DISP_BITMASK_AD9 DISP_BIT_IB01
450#define DISP_BITMASK_AD8 DISP_BIT_IB00
451/*
452 * DISP_CMD_RAMWR RAM Data Read/Write
453 * Use Data Bit Configuration
454 */
455/* DISP_RAM_DATA_MASK_1_ADDR RAM Write Data Mask (1) */
456#define DISP_BITMASK_WM11 DISP_BIT_IB13
457#define DISP_BITMASK_WM10 DISP_BIT_IB12
458#define DISP_BITMASK_WM9 DISP_BIT_IB11
459#define DISP_BITMASK_WM8 DISP_BIT_IB10
460#define DISP_BITMASK_WM7 DISP_BIT_IB09
461#define DISP_BITMASK_WM6 DISP_BIT_IB08
462#define DISP_BITMASK_WM5 DISP_BIT_IB05
463#define DISP_BITMASK_WM4 DISP_BIT_IB04
464#define DISP_BITMASK_WM3 DISP_BIT_IB03
465#define DISP_BITMASK_WM2 DISP_BIT_IB02
466#define DISP_BITMASK_WM1 DISP_BIT_IB01
467#define DISP_BITMASK_WM0 DISP_BIT_IB00
468/* DISP_RAM_DATA_MASK_2_ADDR RAM Write Data Mask (2) */
469#define DISP_BITMASK_WM17 DISP_BIT_IB05
470#define DISP_BITMASK_WM16 DISP_BIT_IB04
471#define DISP_BITMASK_WM15 DISP_BIT_IB03
472#define DISP_BITMASK_WM14 DISP_BIT_IB02
473#define DISP_BITMASK_WM13 DISP_BIT_IB01
474#define DISP_BITMASK_WM12 DISP_BIT_IB00
475/*Gamma Control */
476/* DISP_GAMMA_CONTROL_1_ADDR Gamma Control (1) */
477#define DISP_BITMASK_PKP12 DISP_BIT_IB10
478#define DISP_BITMASK_PKP11 DISP_BIT_IB08
479#define DISP_BITMASK_PKP10 DISP_BIT_IB09
480#define DISP_BITMASK_PKP02 DISP_BIT_IB02
481#define DISP_BITMASK_PKP01 DISP_BIT_IB01
482#define DISP_BITMASK_PKP00 DISP_BIT_IB00
483/* DISP_GAMMA_CONTROL_2_ADDR Gamma Control (2) */
484#define DISP_BITMASK_PKP32 DISP_BIT_IB10
485#define DISP_BITMASK_PKP31 DISP_BIT_IB09
486#define DISP_BITMASK_PKP30 DISP_BIT_IB08
487#define DISP_BITMASK_PKP22 DISP_BIT_IB02
488#define DISP_BITMASK_PKP21 DISP_BIT_IB01
489#define DISP_BITMASK_PKP20 DISP_BIT_IB00
490/* DISP_GAMMA_CONTROL_3_ADDR Gamma Control (3) */
491#define DISP_BITMASK_PKP52 DISP_BIT_IB10
492#define DISP_BITMASK_PKP51 DISP_BIT_IB09
493#define DISP_BITMASK_PKP50 DISP_BIT_IB08
494#define DISP_BITMASK_PKP42 DISP_BIT_IB02
495#define DISP_BITMASK_PKP41 DISP_BIT_IB01
496#define DISP_BITMASK_PKP40 DISP_BIT_IB00
497/* DISP_GAMMA_CONTROL_4_ADDR Gamma Control (4) */
498#define DISP_BITMASK_PRP12 DISP_BIT_IB10
499#define DISP_BITMASK_PRP11 DISP_BIT_IB08
500#define DISP_BITMASK_PRP10 DISP_BIT_IB09
501#define DISP_BITMASK_PRP02 DISP_BIT_IB02
502#define DISP_BITMASK_PRP01 DISP_BIT_IB01
503#define DISP_BITMASK_PRP00 DISP_BIT_IB00
504/* DISP_GAMMA_CONTROL_5_ADDR Gamma Control (5) */
505#define DISP_BITMASK_VRP14 DISP_BIT_IB12
506#define DISP_BITMASK_VRP13 DISP_BIT_IB11
507#define DISP_BITMASK_VRP12 DISP_BIT_IB10
508#define DISP_BITMASK_VRP11 DISP_BIT_IB08
509#define DISP_BITMASK_VRP10 DISP_BIT_IB09
510#define DISP_BITMASK_VRP03 DISP_BIT_IB03
511#define DISP_BITMASK_VRP02 DISP_BIT_IB02
512#define DISP_BITMASK_VRP01 DISP_BIT_IB01
513#define DISP_BITMASK_VRP00 DISP_BIT_IB00
514/* DISP_GAMMA_CONTROL_6_ADDR Gamma Control (6) */
515#define DISP_BITMASK_PKN12 DISP_BIT_IB10
516#define DISP_BITMASK_PKN11 DISP_BIT_IB08
517#define DISP_BITMASK_PKN10 DISP_BIT_IB09
518#define DISP_BITMASK_PKN02 DISP_BIT_IB02
519#define DISP_BITMASK_PKN01 DISP_BIT_IB01
520#define DISP_BITMASK_PKN00 DISP_BIT_IB00
521/* DISP_GAMMA_CONTROL_7_ADDR Gamma Control (7) */
522#define DISP_BITMASK_PKN32 DISP_BIT_IB10
523#define DISP_BITMASK_PKN31 DISP_BIT_IB08
524#define DISP_BITMASK_PKN30 DISP_BIT_IB09
525#define DISP_BITMASK_PKN22 DISP_BIT_IB02
526#define DISP_BITMASK_PKN21 DISP_BIT_IB01
527#define DISP_BITMASK_PKN20 DISP_BIT_IB00
528/* DISP_GAMMA_CONTROL_8_ADDR Gamma Control (8) */
529#define DISP_BITMASK_PKN52 DISP_BIT_IB10
530#define DISP_BITMASK_PKN51 DISP_BIT_IB08
531#define DISP_BITMASK_PKN50 DISP_BIT_IB09
532#define DISP_BITMASK_PKN42 DISP_BIT_IB02
533#define DISP_BITMASK_PKN41 DISP_BIT_IB01
534#define DISP_BITMASK_PKN40 DISP_BIT_IB00
535/* DISP_GAMMA_CONTROL_9_ADDR Gamma Control (9) */
536#define DISP_BITMASK_PRN12 DISP_BIT_IB10
537#define DISP_BITMASK_PRN11 DISP_BIT_IB08
538#define DISP_BITMASK_PRN10 DISP_BIT_IB09
539#define DISP_BITMASK_PRN02 DISP_BIT_IB02
540#define DISP_BITMASK_PRN01 DISP_BIT_IB01
541#define DISP_BITMASK_PRN00 DISP_BIT_IB00
542/* DISP_GAMMA_CONTROL_10_ADDR Gamma Control (10) */
543#define DISP_BITMASK_VRN14 DISP_BIT_IB12
544#define DISP_BITMASK_VRN13 DISP_BIT_IB11
545#define DISP_BITMASK_VRN12 DISP_BIT_IB10
546#define DISP_BITMASK_VRN11 DISP_BIT_IB08
547#define DISP_BITMASK_VRN10 DISP_BIT_IB09
548#define DISP_BITMASK_VRN03 DISP_BIT_IB03
549#define DISP_BITMASK_VRN02 DISP_BIT_IB02
550#define DISP_BITMASK_VRN01 DISP_BIT_IB01
551#define DISP_BITMASK_VRN00 DISP_BIT_IB00
552/* Coordinate Control */
553/* DISP_VERT_SCROLL_CTL_1_ADDR Vertical Scroll Control (1) */
554#define DISP_BITMASK_VL18 DISP_BIT_IB08
555#define DISP_BITMASK_VL17 DISP_BIT_IB07
556#define DISP_BITMASK_VL16 DISP_BIT_IB06
557#define DISP_BITMASK_VL15 DISP_BIT_IB05
558#define DISP_BITMASK_VL14 DISP_BIT_IB04
559#define DISP_BITMASK_VL13 DISP_BIT_IB03
560#define DISP_BITMASK_VL12 DISP_BIT_IB02
561#define DISP_BITMASK_VL11 DISP_BIT_IB01
562#define DISP_BITMASK_VL10 DISP_BIT_IB00
563/* DISP_VERT_SCROLL_CTL_2_ADDR Vertical Scroll Control (2) */
564#define DISP_BITMASK_VL28 DISP_BIT_IB08
565#define DISP_BITMASK_VL27 DISP_BIT_IB07
566#define DISP_BITMASK_VL26 DISP_BIT_IB06
567#define DISP_BITMASK_VL25 DISP_BIT_IB05
568#define DISP_BITMASK_VL24 DISP_BIT_IB04
569#define DISP_BITMASK_VL23 DISP_BIT_IB03
570#define DISP_BITMASK_VL22 DISP_BIT_IB02
571#define DISP_BITMASK_VL21 DISP_BIT_IB01
572#define DISP_BITMASK_VL20 DISP_BIT_IB00
573/* DISP_SCREEN_1_DRV_POS_1_ADDR First Screen Driving Position (1) */
574#define DISP_BITMASK_SS18 DISP_BIT_IB08
575#define DISP_BITMASK_SS17 DISP_BIT_IB07
576#define DISP_BITMASK_SS16 DISP_BIT_IB06
577#define DISP_BITMASK_SS15 DISP_BIT_IB05
578#define DISP_BITMASK_SS14 DISP_BIT_IB04
579#define DISP_BITMASK_SS13 DISP_BIT_IB03
580#define DISP_BITMASK_SS12 DISP_BIT_IB02
581#define DISP_BITMASK_SS11 DISP_BIT_IB01
582#define DISP_BITMASK_SS10 DISP_BIT_IB00
583/* DISP_SCREEN_1_DRV_POS_2_ADDR First Screen Driving Position (2) */
584#define DISP_BITMASK_SE18 DISP_BIT_IB08
585#define DISP_BITMASK_SE17 DISP_BIT_IB07
586#define DISP_BITMASK_SE16 DISP_BIT_IB06
587#define DISP_BITMASK_SE15 DISP_BIT_IB05
588#define DISP_BITMASK_SE14 DISP_BIT_IB04
589#define DISP_BITMASK_SE13 DISP_BIT_IB03
590#define DISP_BITMASK_SE12 DISP_BIT_IB02
591#define DISP_BITMASK_SE11 DISP_BIT_IB01
592#define DISP_BITMASK_SE10 DISP_BIT_IB00
593/* DISP_SCREEN_2_DRV_POS_1_ADDR Second Screen Driving Position (1) */
594#define DISP_BITMASK_SS28 DISP_BIT_IB08
595#define DISP_BITMASK_SS27 DISP_BIT_IB07
596#define DISP_BITMASK_SS26 DISP_BIT_IB06
597#define DISP_BITMASK_SS25 DISP_BIT_IB05
598#define DISP_BITMASK_SS24 DISP_BIT_IB04
599#define DISP_BITMASK_SS23 DISP_BIT_IB03
600#define DISP_BITMASK_SS22 DISP_BIT_IB02
601#define DISP_BITMASK_SS21 DISP_BIT_IB01
602#define DISP_BITMASK_SS20 DISP_BIT_IB00
603/* DISP_SCREEN_3_DRV_POS_2_ADDR Second Screen Driving Position (2) */
604#define DISP_BITMASK_SE28 DISP_BIT_IB08
605#define DISP_BITMASK_SE27 DISP_BIT_IB07
606#define DISP_BITMASK_SE26 DISP_BIT_IB06
607#define DISP_BITMASK_SE25 DISP_BIT_IB05
608#define DISP_BITMASK_SE24 DISP_BIT_IB04
609#define DISP_BITMASK_SE23 DISP_BIT_IB03
610#define DISP_BITMASK_SE22 DISP_BIT_IB02
611#define DISP_BITMASK_SE21 DISP_BIT_IB01
612#define DISP_BITMASK_SE20 DISP_BIT_IB00
613/* DISP_HORZ_RAM_ADDR_POS_1_ADDR Horizontal RAM Address Position (1) */
614#define DISP_BITMASK_HSA7 DISP_BIT_IB07
615#define DISP_BITMASK_HSA6 DISP_BIT_IB06
616#define DISP_BITMASK_HSA5 DISP_BIT_IB05
617#define DISP_BITMASK_HSA4 DISP_BIT_IB04
618#define DISP_BITMASK_HSA3 DISP_BIT_IB03
619#define DISP_BITMASK_HSA2 DISP_BIT_IB02
620#define DISP_BITMASK_HSA1 DISP_BIT_IB01
621#define DISP_BITMASK_HSA0 DISP_BIT_IB00
622/* DISP_HORZ_RAM_ADDR_POS_2_ADDR Horizontal RAM Address Position (2) */
623#define DISP_BITMASK_HEA7 DISP_BIT_IB07
624#define DISP_BITMASK_HEA6 DISP_BIT_IB06
625#define DISP_BITMASK_HEA5 DISP_BIT_IB05
626#define DISP_BITMASK_HEA4 DISP_BIT_IB04
627#define DISP_BITMASK_HEA3 DISP_BIT_IB03
628#define DISP_BITMASK_HEA2 DISP_BIT_IB02
629#define DISP_BITMASK_HEA1 DISP_BIT_IB01
630#define DISP_BITMASK_HEA0 DISP_BIT_IB00
631/* DISP_VERT_RAM_ADDR_POS_1_ADDR Vertical RAM Address Position (1) */
632#define DISP_BITMASK_VSA8 DISP_BIT_IB08
633#define DISP_BITMASK_VSA7 DISP_BIT_IB07
634#define DISP_BITMASK_VSA6 DISP_BIT_IB06
635#define DISP_BITMASK_VSA5 DISP_BIT_IB05
636#define DISP_BITMASK_VSA4 DISP_BIT_IB04
637#define DISP_BITMASK_VSA3 DISP_BIT_IB03
638#define DISP_BITMASK_VSA2 DISP_BIT_IB02
639#define DISP_BITMASK_VSA1 DISP_BIT_IB01
640#define DISP_BITMASK_VSA0 DISP_BIT_IB00
641/* DISP_VERT_RAM_ADDR_POS_2_ADDR Vertical RAM Address Position (2) */
642#define DISP_BITMASK_VEA8 DISP_BIT_IB08
643#define DISP_BITMASK_VEA7 DISP_BIT_IB07
644#define DISP_BITMASK_VEA6 DISP_BIT_IB06
645#define DISP_BITMASK_VEA5 DISP_BIT_IB05
646#define DISP_BITMASK_VEA4 DISP_BIT_IB04
647#define DISP_BITMASK_VEA3 DISP_BIT_IB03
648#define DISP_BITMASK_VEA2 DISP_BIT_IB02
649#define DISP_BITMASK_VEA1 DISP_BIT_IB01
650#define DISP_BITMASK_VEA0 DISP_BIT_IB00
651static word disp_area_start_row;
652static word disp_area_end_row;
653static boolean disp_initialized = FALSE;
654/* For some reason the contrast set at init time is not good. Need to do
655* it again
656*/
657static boolean display_on = FALSE;
658
659static uint32 tmd20qvga_lcd_rev;
660uint16 tmd20qvga_panel_offset;
661
662#ifdef DISP_DEVICE_8BPP
663static word convert_8_to_16_tbl[256] = {
664 0x0000, 0x2000, 0x4000, 0x6000, 0x8000, 0xA000, 0xC000, 0xE000,
665 0x0100, 0x2100, 0x4100, 0x6100, 0x8100, 0xA100, 0xC100, 0xE100,
666 0x0200, 0x2200, 0x4200, 0x6200, 0x8200, 0xA200, 0xC200, 0xE200,
667 0x0300, 0x2300, 0x4300, 0x6300, 0x8300, 0xA300, 0xC300, 0xE300,
668 0x0400, 0x2400, 0x4400, 0x6400, 0x8400, 0xA400, 0xC400, 0xE400,
669 0x0500, 0x2500, 0x4500, 0x6500, 0x8500, 0xA500, 0xC500, 0xE500,
670 0x0600, 0x2600, 0x4600, 0x6600, 0x8600, 0xA600, 0xC600, 0xE600,
671 0x0700, 0x2700, 0x4700, 0x6700, 0x8700, 0xA700, 0xC700, 0xE700,
672 0x0008, 0x2008, 0x4008, 0x6008, 0x8008, 0xA008, 0xC008, 0xE008,
673 0x0108, 0x2108, 0x4108, 0x6108, 0x8108, 0xA108, 0xC108, 0xE108,
674 0x0208, 0x2208, 0x4208, 0x6208, 0x8208, 0xA208, 0xC208, 0xE208,
675 0x0308, 0x2308, 0x4308, 0x6308, 0x8308, 0xA308, 0xC308, 0xE308,
676 0x0408, 0x2408, 0x4408, 0x6408, 0x8408, 0xA408, 0xC408, 0xE408,
677 0x0508, 0x2508, 0x4508, 0x6508, 0x8508, 0xA508, 0xC508, 0xE508,
678 0x0608, 0x2608, 0x4608, 0x6608, 0x8608, 0xA608, 0xC608, 0xE608,
679 0x0708, 0x2708, 0x4708, 0x6708, 0x8708, 0xA708, 0xC708, 0xE708,
680 0x0010, 0x2010, 0x4010, 0x6010, 0x8010, 0xA010, 0xC010, 0xE010,
681 0x0110, 0x2110, 0x4110, 0x6110, 0x8110, 0xA110, 0xC110, 0xE110,
682 0x0210, 0x2210, 0x4210, 0x6210, 0x8210, 0xA210, 0xC210, 0xE210,
683 0x0310, 0x2310, 0x4310, 0x6310, 0x8310, 0xA310, 0xC310, 0xE310,
684 0x0410, 0x2410, 0x4410, 0x6410, 0x8410, 0xA410, 0xC410, 0xE410,
685 0x0510, 0x2510, 0x4510, 0x6510, 0x8510, 0xA510, 0xC510, 0xE510,
686 0x0610, 0x2610, 0x4610, 0x6610, 0x8610, 0xA610, 0xC610, 0xE610,
687 0x0710, 0x2710, 0x4710, 0x6710, 0x8710, 0xA710, 0xC710, 0xE710,
688 0x0018, 0x2018, 0x4018, 0x6018, 0x8018, 0xA018, 0xC018, 0xE018,
689 0x0118, 0x2118, 0x4118, 0x6118, 0x8118, 0xA118, 0xC118, 0xE118,
690 0x0218, 0x2218, 0x4218, 0x6218, 0x8218, 0xA218, 0xC218, 0xE218,
691 0x0318, 0x2318, 0x4318, 0x6318, 0x8318, 0xA318, 0xC318, 0xE318,
692 0x0418, 0x2418, 0x4418, 0x6418, 0x8418, 0xA418, 0xC418, 0xE418,
693 0x0518, 0x2518, 0x4518, 0x6518, 0x8518, 0xA518, 0xC518, 0xE518,
694 0x0618, 0x2618, 0x4618, 0x6618, 0x8618, 0xA618, 0xC618, 0xE618,
695 0x0718, 0x2718, 0x4718, 0x6718, 0x8718, 0xA718, 0xC718, 0xE718
696};
697#endif /* DISP_DEVICE_8BPP */
698
699static void tmd20qvga_disp_set_rect(int x, int y, int xres, int yres);
700static void tmd20qvga_disp_init(struct platform_device *pdev);
701static void tmd20qvga_disp_set_contrast(void);
702static void tmd20qvga_disp_set_display_area(word start_row, word end_row);
703static int tmd20qvga_disp_off(struct platform_device *pdev);
704static int tmd20qvga_disp_on(struct platform_device *pdev);
705static void tmd20qvga_set_revId(int);
706
707/* future use */
708void tmd20qvga_disp_clear_screen_area(word start_row, word end_row,
709 word start_column, word end_column);
710
711static void tmd20qvga_set_revId(int id)
712{
713
714 tmd20qvga_lcd_rev = id;
715
716 if (tmd20qvga_lcd_rev == 1)
717 tmd20qvga_panel_offset = 0x10;
718 else
719 tmd20qvga_panel_offset = 0;
720}
721
722static void tmd20qvga_disp_init(struct platform_device *pdev)
723{
724 struct msm_fb_data_type *mfd;
725
726 if (disp_initialized)
727 return;
728
729 mfd = platform_get_drvdata(pdev);
730
731 DISP_CMD_PORT = mfd->cmd_port;
732 DISP_DATA_PORT = mfd->data_port;
733
734#ifdef TMD20QVGA_LCD_18BPP
735 tmd20qvga_set_revId(2);
736#else
737 tmd20qvga_set_revId(1);
738#endif
739
740 disp_initialized = TRUE;
741 tmd20qvga_disp_set_contrast();
742 tmd20qvga_disp_set_display_area(0, QVGA_HEIGHT - 1);
743}
744
745static void tmd20qvga_disp_set_rect(int x, int y, int xres, int yres)
746{
747 if (!disp_initialized)
748 return;
749
750 DISP_SET_RECT(y, y + yres - 1, x, x + xres - 1);
751
752 DISP_CMD_OUT(DISP_CMD_RAMWR);
753}
754
755static void tmd20qvga_disp_set_display_area(word start_row, word end_row)
756{
757 word start_driving = start_row;
758 word end_driving = end_row;
759
760 if (!disp_initialized)
761 return;
762
763 /* Range checking
764 */
765 if (end_driving >= QVGA_HEIGHT)
766 end_driving = QVGA_HEIGHT - 1;
767 if (start_driving > end_driving) {
768 /* Probably Backwards Switch */
769 start_driving = end_driving;
770 end_driving = start_row; /* Has not changed */
771 if (end_driving >= QVGA_HEIGHT)
772 end_driving = QVGA_HEIGHT - 1;
773 }
774
775 if ((start_driving == disp_area_start_row)
776 && (end_driving == disp_area_end_row))
777 return;
778
779 disp_area_start_row = start_driving;
780 disp_area_end_row = end_driving;
781
782 DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_1_ADDR,
783 DISP_VAL_IF(start_driving & 0x100,
784 DISP_BITMASK_SS18) |
785 DISP_VAL_IF(start_driving & 0x080,
786 DISP_BITMASK_SS17) |
787 DISP_VAL_IF(start_driving & 0x040,
788 DISP_BITMASK_SS16) |
789 DISP_VAL_IF(start_driving & 0x020,
790 DISP_BITMASK_SS15) |
791 DISP_VAL_IF(start_driving & 0x010,
792 DISP_BITMASK_SS14) |
793 DISP_VAL_IF(start_driving & 0x008,
794 DISP_BITMASK_SS13) |
795 DISP_VAL_IF(start_driving & 0x004,
796 DISP_BITMASK_SS12) |
797 DISP_VAL_IF(start_driving & 0x002,
798 DISP_BITMASK_SS11) |
799 DISP_VAL_IF(start_driving & 0x001, DISP_BITMASK_SS10));
800
801 DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_2_ADDR,
802 DISP_VAL_IF(end_driving & 0x100, DISP_BITMASK_SE18) |
803 DISP_VAL_IF(end_driving & 0x080, DISP_BITMASK_SE17) |
804 DISP_VAL_IF(end_driving & 0x040, DISP_BITMASK_SE16) |
805 DISP_VAL_IF(end_driving & 0x020, DISP_BITMASK_SE15) |
806 DISP_VAL_IF(end_driving & 0x010, DISP_BITMASK_SE14) |
807 DISP_VAL_IF(end_driving & 0x008, DISP_BITMASK_SE13) |
808 DISP_VAL_IF(end_driving & 0x004, DISP_BITMASK_SE12) |
809 DISP_VAL_IF(end_driving & 0x002, DISP_BITMASK_SE11) |
810 DISP_VAL_IF(end_driving & 0x001, DISP_BITMASK_SE10));
811}
812
813static int tmd20qvga_disp_off(struct platform_device *pdev)
814{
815 if (!disp_initialized)
816 tmd20qvga_disp_init(pdev);
817
818 if (display_on) {
819 if (tmd20qvga_lcd_rev == 2) {
820 DISP_WRITE_OUT(DISP_POFF_LN_SETTING_ADDR, 0x000A);
821 DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xFFEE);
822 WAIT_MSEC(40);
823 DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xF812);
824 WAIT_MSEC(40);
825 DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xE811);
826 WAIT_MSEC(40);
827 DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xC011);
828 WAIT_MSEC(40);
829 DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x4011);
830 WAIT_MSEC(20);
831 DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0010);
832
833 } else {
834 DISP_WRITE_OUT(DISP_POFF_LN_SETTING_ADDR, 0x000F);
835 DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0BFE);
836 DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
837 WAIT_MSEC(40);
838 DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0BED);
839 DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
840 WAIT_MSEC(40);
841 DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x00CD);
842 DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
843 WAIT_MSEC(20);
844 DISP_WRITE_OUT(DISP_START_OSCILLATION_ADDR, 0x0);
845 }
846
847 DISP_WRITE_OUT(DISP_MODE_SETTING_ADDR, 0x0004);
848 DISP_WRITE_OUT(DISP_MODE_SETTING_ADDR, 0x0000);
849
850 display_on = FALSE;
851 }
852
853 return 0;
854}
855
856static int tmd20qvga_disp_on(struct platform_device *pdev)
857{
858 if (!disp_initialized)
859 tmd20qvga_disp_init(pdev);
860
861 if (!display_on) {
862 /* Deep Stand-by -> Stand-by */
863 DISP_CMD_OUT(DISP_START_OSCILLATION_ADDR);
864 WAIT_MSEC(1);
865 DISP_CMD_OUT(DISP_START_OSCILLATION_ADDR);
866 WAIT_MSEC(1);
867 DISP_CMD_OUT(DISP_START_OSCILLATION_ADDR);
868 WAIT_MSEC(1);
869
870 /* OFF -> Deep Stan-By -> Stand-by */
871 /* let's change the state from "Stand-by" to "Sleep" */
872 DISP_WRITE_OUT(DISP_MODE_SETTING_ADDR, 0x0005);
873 WAIT_MSEC(1);
874
875 /* Sleep -> Displaying */
876 DISP_WRITE_OUT(DISP_START_OSCILLATION_ADDR, 0x0001);
877 DISP_WRITE_OUT(DISP_DRIVER_OUTPUT_CTL_ADDR, 0x0127);
878 DISP_WRITE_OUT(DISP_LCD_DRIVING_SIG_ADDR, 0x200);
879 /* fast write mode */
880 DISP_WRITE_OUT(DISP_ENTRY_MODE_ADDR, 0x0130);
881 if (tmd20qvga_lcd_rev == 2)
882 DISP_WRITE_OUT(DISP_TMD_700_ADDR, 0x0003);
883 /* back porch = 14 + front porch = 2 --> 16 lines */
884 if (tmd20qvga_lcd_rev == 2) {
885#ifdef TMD20QVGA_LCD_18BPP
886 /* 256k color */
887 DISP_WRITE_OUT(DISP_DISPLAY_CTL_1_ADDR, 0x0000);
888#else
889 /* 65k color */
890 DISP_WRITE_OUT(DISP_DISPLAY_CTL_1_ADDR, 0x4000);
891#endif
892 DISP_WRITE_OUT(DISP_DISPLAY_CTL_2_ADDR, 0x0302);
893 } else {
894#ifdef TMD20QVGA_LCD_18BPP
895 /* 256k color */
896 DISP_WRITE_OUT(DISP_DISPLAY_CTL_1_ADDR, 0x0004);
897#else
898 /* 65k color */
899 DISP_WRITE_OUT(DISP_DISPLAY_CTL_1_ADDR, 0x4004);
900#endif
901 DISP_WRITE_OUT(DISP_DISPLAY_CTL_2_ADDR, 0x020E);
902 }
903 /* 16 bit one transfer */
904 if (tmd20qvga_lcd_rev == 2) {
905 DISP_WRITE_OUT(DISP_EXT_DISPLAY_CTL_1_ADDR, 0x0000);
906 DISP_WRITE_OUT(DISP_FRAME_CYCLE_CTL_ADDR, 0x0010);
907 DISP_WRITE_OUT(DISP_LTPS_CTL_1_ADDR, 0x0302);
908 DISP_WRITE_OUT(DISP_LTPS_CTL_2_ADDR, 0x0102);
909 DISP_WRITE_OUT(DISP_LTPS_CTL_3_ADDR, 0x0000);
910 DISP_WRITE_OUT(DISP_TMD_015_ADDR, 0x2000);
911
912 DISP_WRITE_OUT(DISP_AMP_SETTING_ADDR, 0x0000);
913 DISP_WRITE_OUT(DISP_GAMMA_CONTROL_1_ADDR, 0x0403);
914 DISP_WRITE_OUT(DISP_GAMMA_CONTROL_2_ADDR, 0x0304);
915 DISP_WRITE_OUT(DISP_GAMMA_CONTROL_3_ADDR, 0x0403);
916 DISP_WRITE_OUT(DISP_GAMMA_CONTROL_4_ADDR, 0x0303);
917 DISP_WRITE_OUT(DISP_GAMMA_CONTROL_5_ADDR, 0x0101);
918 DISP_WRITE_OUT(DISP_TMD_305_ADDR, 0);
919
920 DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_1_ADDR, 0x0000);
921 DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_2_ADDR, 0x013F);
922
923 DISP_WRITE_OUT(DISP_POWER_CTL_3_ADDR, 0x077D);
924
925 DISP_WRITE_OUT(DISP_POWER_CTL_4_ADDR, 0x0005);
926 DISP_WRITE_OUT(DISP_POWER_CTL_5_ADDR, 0x0000);
927 DISP_WRITE_OUT(DISP_POWER_CTL_6_ADDR, 0x0015);
928 DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xC010);
929 WAIT_MSEC(1);
930
931 DISP_WRITE_OUT(DISP_POWER_CTL_2_ADDR, 0x0001);
932 DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xFFFE);
933 WAIT_MSEC(60);
934 } else {
935 DISP_WRITE_OUT(DISP_EXT_DISPLAY_CTL_1_ADDR, 0x0001);
936 DISP_WRITE_OUT(DISP_FRAME_CYCLE_CTL_ADDR, 0x0010);
937 DISP_WRITE_OUT(DISP_LTPS_CTL_1_ADDR, 0x0301);
938 DISP_WRITE_OUT(DISP_LTPS_CTL_2_ADDR, 0x0001);
939 DISP_WRITE_OUT(DISP_LTPS_CTL_3_ADDR, 0x0000);
940 DISP_WRITE_OUT(DISP_AMP_SETTING_ADDR, 0x0000);
941 DISP_WRITE_OUT(DISP_GAMMA_CONTROL_1_ADDR, 0x0507);
942 DISP_WRITE_OUT(DISP_GAMMA_CONTROL_2_ADDR, 0x0405);
943 DISP_WRITE_OUT(DISP_GAMMA_CONTROL_3_ADDR, 0x0607);
944 DISP_WRITE_OUT(DISP_GAMMA_CONTROL_4_ADDR, 0x0502);
945 DISP_WRITE_OUT(DISP_GAMMA_CONTROL_5_ADDR, 0x0301);
946 DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_1_ADDR, 0x0000);
947 DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_2_ADDR, 0x013F);
948 DISP_WRITE_OUT(DISP_POWER_CTL_3_ADDR, 0x0795);
949
950 DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0102);
951 WAIT_MSEC(1);
952
953 DISP_WRITE_OUT(DISP_POWER_CTL_4_ADDR, 0x0450);
954 DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0103);
955 WAIT_MSEC(1);
956
957 DISP_WRITE_OUT(DISP_POWER_CTL_5_ADDR, 0x0008);
958 DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0104);
959 WAIT_MSEC(1);
960
961 DISP_WRITE_OUT(DISP_POWER_CTL_6_ADDR, 0x0C00);
962 DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0105);
963 WAIT_MSEC(1);
964
965 DISP_WRITE_OUT(DISP_POWER_CTL_7_ADDR, 0x0000);
966 DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0106);
967 WAIT_MSEC(1);
968
969 DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0801);
970 DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
971 WAIT_MSEC(1);
972
973 DISP_WRITE_OUT(DISP_POWER_CTL_2_ADDR, 0x001F);
974 DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0101);
975 WAIT_MSEC(60);
976
977 DISP_WRITE_OUT(DISP_POWER_CTL_2_ADDR, 0x009F);
978 DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0101);
979 WAIT_MSEC(10);
980
981 DISP_WRITE_OUT(DISP_HORZ_RAM_ADDR_POS_1_ADDR, 0x0010);
982 DISP_WRITE_OUT(DISP_HORZ_RAM_ADDR_POS_2_ADDR, 0x00FF);
983 DISP_WRITE_OUT(DISP_VERT_RAM_ADDR_POS_1_ADDR, 0x0000);
984 DISP_WRITE_OUT(DISP_VERT_RAM_ADDR_POS_2_ADDR, 0x013F);
985 /* RAM starts at address 0x10 */
986 DISP_WRITE_OUT(DISP_RAM_ADDR_SET_1_ADDR, 0x0010);
987 DISP_WRITE_OUT(DISP_RAM_ADDR_SET_2_ADDR, 0x0000);
988
989 /* lcd controller uses internal clock, not ext. vsync */
990 DISP_CMD_OUT(DISP_CMD_RAMWR);
991
992 DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0881);
993 DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
994 WAIT_MSEC(40);
995
996 DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0BE1);
997 DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
998 WAIT_MSEC(40);
999
1000 DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0BFF);
1001 DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
1002 }
1003 display_on = TRUE;
1004 }
1005
1006 return 0;
1007}
1008
1009static void tmd20qvga_disp_set_contrast(void)
1010{
1011#if (defined(TMD20QVGA_LCD_18BPP))
1012
1013 DISP_WRITE_OUT(DISP_GAMMA_CONTROL_1_ADDR, 0x0403);
1014 DISP_WRITE_OUT(DISP_GAMMA_CONTROL_2_ADDR, 0x0302);
1015 DISP_WRITE_OUT(DISP_GAMMA_CONTROL_3_ADDR, 0x0403);
1016 DISP_WRITE_OUT(DISP_GAMMA_CONTROL_4_ADDR, 0x0303);
1017 DISP_WRITE_OUT(DISP_GAMMA_CONTROL_5_ADDR, 0x0F07);
1018
1019#else
1020 int newcontrast = 0x46;
1021
1022 DISP_WRITE_OUT(DISP_GAMMA_CONTROL_1_ADDR, 0x0403);
1023
1024 DISP_WRITE_OUT(DISP_GAMMA_CONTROL_2_ADDR,
1025 DISP_VAL_IF(newcontrast & 0x0001, DISP_BITMASK_PKP20) |
1026 DISP_VAL_IF(newcontrast & 0x0002, DISP_BITMASK_PKP21) |
1027 DISP_VAL_IF(newcontrast & 0x0004, DISP_BITMASK_PKP22) |
1028 DISP_VAL_IF(newcontrast & 0x0010, DISP_BITMASK_PKP30) |
1029 DISP_VAL_IF(newcontrast & 0x0020, DISP_BITMASK_PKP31) |
1030 DISP_VAL_IF(newcontrast & 0x0040, DISP_BITMASK_PKP32));
1031
1032 DISP_WRITE_OUT(DISP_GAMMA_CONTROL_3_ADDR,
1033 DISP_VAL_IF(newcontrast & 0x0010, DISP_BITMASK_PKP40) |
1034 DISP_VAL_IF(newcontrast & 0x0020, DISP_BITMASK_PKP41) |
1035 DISP_VAL_IF(newcontrast & 0x0040, DISP_BITMASK_PKP42) |
1036 DISP_VAL_IF(newcontrast & 0x0001, DISP_BITMASK_PKP50) |
1037 DISP_VAL_IF(newcontrast & 0x0002, DISP_BITMASK_PKP51) |
1038 DISP_VAL_IF(newcontrast & 0x0004, DISP_BITMASK_PKP52));
1039
1040 DISP_WRITE_OUT(DISP_GAMMA_CONTROL_4_ADDR, 0x0303);
1041 DISP_WRITE_OUT(DISP_GAMMA_CONTROL_5_ADDR, 0x0F07);
1042
1043#endif /* defined(TMD20QVGA_LCD_18BPP) */
1044
1045} /* End disp_set_contrast */
1046
1047void tmd20qvga_disp_clear_screen_area
1048 (word start_row, word end_row, word start_column, word end_column) {
1049 int32 i;
1050
1051 /* Clear the display screen */
1052 DISP_SET_RECT(start_row, end_row, start_column, end_column);
1053 DISP_CMD_OUT(DISP_CMD_RAMWR);
1054 i = (end_row - start_row + 1) * (end_column - start_column + 1);
1055 for (; i > 0; i--)
1056 DISP_DATA_OUT_16TO18BPP(0x0);
1057}
1058
1059static int __init tmd20qvga_probe(struct platform_device *pdev)
1060{
1061 msm_fb_add_device(pdev);
1062
1063 return 0;
1064}
1065
1066static struct platform_driver this_driver = {
1067 .probe = tmd20qvga_probe,
1068 .driver = {
1069 .name = "ebi2_tmd_qvga",
1070 },
1071};
1072
1073static struct msm_fb_panel_data tmd20qvga_panel_data = {
1074 .on = tmd20qvga_disp_on,
1075 .off = tmd20qvga_disp_off,
1076 .set_rect = tmd20qvga_disp_set_rect,
1077};
1078
1079static struct platform_device this_device = {
1080 .name = "ebi2_tmd_qvga",
1081 .id = 0,
1082 .dev = {
1083 .platform_data = &tmd20qvga_panel_data,
1084 }
1085};
1086
1087static int __init tmd20qvga_init(void)
1088{
1089 int ret;
1090 struct msm_panel_info *pinfo;
1091
1092 ret = platform_driver_register(&this_driver);
1093 if (!ret) {
1094 pinfo = &tmd20qvga_panel_data.panel_info;
1095 pinfo->xres = 240;
1096 pinfo->yres = 320;
1097 pinfo->type = EBI2_PANEL;
1098 pinfo->pdest = DISPLAY_1;
1099 pinfo->wait_cycle = 0x808000;
1100#ifdef TMD20QVGA_LCD_18BPP
1101 pinfo->bpp = 18;
1102#else
1103 pinfo->bpp = 16;
1104#endif
1105 pinfo->fb_num = 2;
1106 pinfo->lcd.vsync_enable = TRUE;
1107 pinfo->lcd.refx100 = 6000;
1108 pinfo->lcd.v_back_porch = 16;
1109 pinfo->lcd.v_front_porch = 4;
1110 pinfo->lcd.v_pulse_width = 0;
1111 pinfo->lcd.hw_vsync_mode = FALSE;
1112 pinfo->lcd.vsync_notifier_period = 0;
1113
1114 ret = platform_device_register(&this_device);
1115 if (ret)
1116 platform_driver_unregister(&this_driver);
1117 }
1118
1119 return ret;
1120}
1121
1122module_init(tmd20qvga_init);
diff --git a/drivers/staging/msm/hdmi_sii9022.c b/drivers/staging/msm/hdmi_sii9022.c
new file mode 100644
index 000000000000..6b82b56a77b6
--- /dev/null
+++ b/drivers/staging/msm/hdmi_sii9022.c
@@ -0,0 +1,248 @@
1/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include <linux/i2c.h>
19#include <linux/delay.h>
20#include "msm_fb.h"
21
22#define DEVICE_NAME "sii9022"
23#define SII9022_DEVICE_ID 0xB0
24
25struct sii9022_i2c_addr_data{
26 u8 addr;
27 u8 data;
28};
29
30/* video mode data */
31static u8 video_mode_data[] = {
32 0x00,
33 0xF9, 0x1C, 0x70, 0x17, 0x72, 0x06, 0xEE, 0x02,
34};
35
36static u8 avi_io_format[] = {
37 0x09,
38 0x00, 0x00,
39};
40
41/* power state */
42static struct sii9022_i2c_addr_data regset0[] = {
43 { 0x60, 0x04 },
44 { 0x63, 0x00 },
45 { 0x1E, 0x00 },
46};
47
48static u8 video_infoframe[] = {
49 0x0C,
50 0xF0, 0x00, 0x68, 0x00, 0x04, 0x00, 0x19, 0x00,
51 0xE9, 0x02, 0x04, 0x01, 0x04, 0x06,
52};
53
54/* configure audio */
55static struct sii9022_i2c_addr_data regset1[] = {
56 { 0x26, 0x90 },
57 { 0x20, 0x90 },
58 { 0x1F, 0x80 },
59 { 0x26, 0x80 },
60 { 0x24, 0x02 },
61 { 0x25, 0x0B },
62 { 0xBC, 0x02 },
63 { 0xBD, 0x24 },
64 { 0xBE, 0x02 },
65};
66
67/* enable audio */
68static u8 misc_infoframe[] = {
69 0xBF,
70 0xC2, 0x84, 0x01, 0x0A, 0x6F, 0x02, 0x00, 0x00,
71 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72};
73
74/* set HDMI, active */
75static struct sii9022_i2c_addr_data regset2[] = {
76 { 0x1A, 0x01 },
77 { 0x3D, 0x00 },
78};
79
80static int send_i2c_data(struct i2c_client *client,
81 struct sii9022_i2c_addr_data *regset,
82 int size)
83{
84 int i;
85 int rc = 0;
86
87 for (i = 0; i < size; i++) {
88 rc = i2c_smbus_write_byte_data(
89 client,
90 regset[i].addr, regset[i].data);
91 if (rc)
92 break;
93 }
94 return rc;
95}
96
97static int hdmi_sii_enable(struct i2c_client *client)
98{
99 int rc;
100 int retries = 10;
101 int count;
102
103 rc = i2c_smbus_write_byte_data(client, 0xC7, 0x00);
104 if (rc)
105 goto enable_exit;
106
107 do {
108 msleep(1);
109 rc = i2c_smbus_read_byte_data(client, 0x1B);
110 } while ((rc != SII9022_DEVICE_ID) && retries--);
111
112 if (rc != SII9022_DEVICE_ID)
113 return -ENODEV;
114
115 rc = i2c_smbus_write_byte_data(client, 0x1A, 0x11);
116 if (rc)
117 goto enable_exit;
118
119 count = ARRAY_SIZE(video_mode_data);
120 rc = i2c_master_send(client, video_mode_data, count);
121 if (rc != count) {
122 rc = -EIO;
123 goto enable_exit;
124 }
125
126 rc = i2c_smbus_write_byte_data(client, 0x08, 0x20);
127 if (rc)
128 goto enable_exit;
129 count = ARRAY_SIZE(avi_io_format);
130 rc = i2c_master_send(client, avi_io_format, count);
131 if (rc != count) {
132 rc = -EIO;
133 goto enable_exit;
134 }
135
136 rc = send_i2c_data(client, regset0, ARRAY_SIZE(regset0));
137 if (rc)
138 goto enable_exit;
139
140 count = ARRAY_SIZE(video_infoframe);
141 rc = i2c_master_send(client, video_infoframe, count);
142 if (rc != count) {
143 rc = -EIO;
144 goto enable_exit;
145 }
146
147 rc = send_i2c_data(client, regset1, ARRAY_SIZE(regset1));
148 if (rc)
149 goto enable_exit;
150
151 count = ARRAY_SIZE(misc_infoframe);
152 rc = i2c_master_send(client, misc_infoframe, count);
153 if (rc != count) {
154 rc = -EIO;
155 goto enable_exit;
156 }
157
158 rc = send_i2c_data(client, regset2, ARRAY_SIZE(regset2));
159 if (rc)
160 goto enable_exit;
161
162 return 0;
163enable_exit:
164 printk(KERN_ERR "%s: exited rc=%d\n", __func__, rc);
165 return rc;
166}
167
168static const struct i2c_device_id hmdi_sii_id[] = {
169 { DEVICE_NAME, 0 },
170 { }
171};
172
173static int hdmi_sii_probe(struct i2c_client *client,
174 const struct i2c_device_id *id)
175{
176 int rc;
177
178 if (!i2c_check_functionality(client->adapter,
179 I2C_FUNC_SMBUS_BYTE | I2C_FUNC_I2C))
180 return -ENODEV;
181 rc = hdmi_sii_enable(client);
182 return rc;
183}
184
185
186static struct i2c_driver hdmi_sii_i2c_driver = {
187 .driver = {
188 .name = DEVICE_NAME,
189 .owner = THIS_MODULE,
190 },
191 .probe = hdmi_sii_probe,
192 .remove = __exit_p(hdmi_sii_remove),
193 .id_table = hmdi_sii_id,
194};
195
196static int __init hdmi_sii_init(void)
197{
198 int ret;
199 struct msm_panel_info pinfo;
200
201 if (msm_fb_detect_client("hdmi_sii9022"))
202 return 0;
203
204 pinfo.xres = 1280;
205 pinfo.yres = 720;
206 pinfo.type = HDMI_PANEL;
207 pinfo.pdest = DISPLAY_1;
208 pinfo.wait_cycle = 0;
209 pinfo.bpp = 24;
210 pinfo.fb_num = 2;
211 pinfo.clk_rate = 74250000;
212
213 pinfo.lcdc.h_back_porch = 124;
214 pinfo.lcdc.h_front_porch = 110;
215 pinfo.lcdc.h_pulse_width = 136;
216 pinfo.lcdc.v_back_porch = 19;
217 pinfo.lcdc.v_front_porch = 5;
218 pinfo.lcdc.v_pulse_width = 6;
219 pinfo.lcdc.border_clr = 0;
220 pinfo.lcdc.underflow_clr = 0xff;
221 pinfo.lcdc.hsync_skew = 0;
222
223 ret = lcdc_device_register(&pinfo);
224 if (ret) {
225 printk(KERN_ERR "%s: failed to register device\n", __func__);
226 goto init_exit;
227 }
228
229 ret = i2c_add_driver(&hdmi_sii_i2c_driver);
230 if (ret)
231 printk(KERN_ERR "%s: failed to add i2c driver\n", __func__);
232
233init_exit:
234 return ret;
235}
236
237static void __exit hdmi_sii_exit(void)
238{
239 i2c_del_driver(&hdmi_sii_i2c_driver);
240}
241
242module_init(hdmi_sii_init);
243module_exit(hdmi_sii_exit);
244MODULE_LICENSE("GPL v2");
245MODULE_VERSION("0.1");
246MODULE_AUTHOR("Qualcomm Innovation Center, Inc.");
247MODULE_DESCRIPTION("SiI9022 HDMI driver");
248MODULE_ALIAS("platform:hdmi-sii9022");
diff --git a/drivers/staging/msm/lcdc.c b/drivers/staging/msm/lcdc.c
new file mode 100644
index 000000000000..735280ab72cb
--- /dev/null
+++ b/drivers/staging/msm/lcdc.c
@@ -0,0 +1,239 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/sched.h>
21#include <linux/time.h>
22#include <linux/init.h>
23#include <linux/interrupt.h>
24#include <linux/spinlock.h>
25#include <linux/delay.h>
26#include <mach/hardware.h>
27#include <linux/io.h>
28
29#include <asm/system.h>
30#include <asm/mach-types.h>
31#include <linux/semaphore.h>
32#include <linux/uaccess.h>
33#include <linux/clk.h>
34#include <linux/platform_device.h>
35#include <linux/pm_qos_params.h>
36
37#include "msm_fb.h"
38
39static int lcdc_probe(struct platform_device *pdev);
40static int lcdc_remove(struct platform_device *pdev);
41
42static int lcdc_off(struct platform_device *pdev);
43static int lcdc_on(struct platform_device *pdev);
44
45static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
46static int pdev_list_cnt;
47
48static struct clk *mdp_lcdc_pclk_clk;
49static struct clk *mdp_lcdc_pad_pclk_clk;
50
51int mdp_lcdc_pclk_clk_rate;
52int mdp_lcdc_pad_pclk_clk_rate;
53
54static struct platform_driver lcdc_driver = {
55 .probe = lcdc_probe,
56 .remove = lcdc_remove,
57 .suspend = NULL,
58 .resume = NULL,
59 .shutdown = NULL,
60 .driver = {
61 .name = "lcdc",
62 },
63};
64
65static struct lcdc_platform_data *lcdc_pdata;
66
67static int lcdc_off(struct platform_device *pdev)
68{
69 int ret = 0;
70
71 ret = panel_next_off(pdev);
72
73 clk_disable(mdp_lcdc_pclk_clk);
74 clk_disable(mdp_lcdc_pad_pclk_clk);
75
76 if (lcdc_pdata && lcdc_pdata->lcdc_power_save)
77 lcdc_pdata->lcdc_power_save(0);
78
79 if (lcdc_pdata && lcdc_pdata->lcdc_gpio_config)
80 ret = lcdc_pdata->lcdc_gpio_config(0);
81
82// pm_qos_update_requirement(PM_QOS_SYSTEM_BUS_FREQ , "lcdc",
83// PM_QOS_DEFAULT_VALUE);
84
85 return ret;
86}
87
88static int lcdc_on(struct platform_device *pdev)
89{
90 int ret = 0;
91 struct msm_fb_data_type *mfd;
92 unsigned long panel_pixclock_freq , pm_qos_freq;
93
94 mfd = platform_get_drvdata(pdev);
95 panel_pixclock_freq = mfd->fbi->var.pixclock;
96
97 if (panel_pixclock_freq > 58000000)
98 /* pm_qos_freq should be in Khz */
99 pm_qos_freq = panel_pixclock_freq / 1000 ;
100 else
101 pm_qos_freq = 58000;
102
103// pm_qos_update_requirement(PM_QOS_SYSTEM_BUS_FREQ , "lcdc",
104// pm_qos_freq);
105 mfd = platform_get_drvdata(pdev);
106
107 clk_enable(mdp_lcdc_pclk_clk);
108 clk_enable(mdp_lcdc_pad_pclk_clk);
109
110 if (lcdc_pdata && lcdc_pdata->lcdc_power_save)
111 lcdc_pdata->lcdc_power_save(1);
112 if (lcdc_pdata && lcdc_pdata->lcdc_gpio_config)
113 ret = lcdc_pdata->lcdc_gpio_config(1);
114
115 clk_set_rate(mdp_lcdc_pclk_clk, mfd->fbi->var.pixclock);
116 clk_set_rate(mdp_lcdc_pad_pclk_clk, mfd->fbi->var.pixclock);
117 mdp_lcdc_pclk_clk_rate = clk_get_rate(mdp_lcdc_pclk_clk);
118 mdp_lcdc_pad_pclk_clk_rate = clk_get_rate(mdp_lcdc_pad_pclk_clk);
119
120 ret = panel_next_on(pdev);
121 return ret;
122}
123
124static int lcdc_probe(struct platform_device *pdev)
125{
126 struct msm_fb_data_type *mfd;
127 struct fb_info *fbi;
128 struct platform_device *mdp_dev = NULL;
129 struct msm_fb_panel_data *pdata = NULL;
130 int rc;
131
132 if (pdev->id == 0) {
133 lcdc_pdata = pdev->dev.platform_data;
134 return 0;
135 }
136
137 mfd = platform_get_drvdata(pdev);
138
139 if (!mfd)
140 return -ENODEV;
141
142 if (mfd->key != MFD_KEY)
143 return -EINVAL;
144
145 if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
146 return -ENOMEM;
147
148 mdp_dev = platform_device_alloc("mdp", pdev->id);
149 if (!mdp_dev)
150 return -ENOMEM;
151
152 /*
153 * link to the latest pdev
154 */
155 mfd->pdev = mdp_dev;
156 mfd->dest = DISPLAY_LCDC;
157
158 /*
159 * alloc panel device data
160 */
161 if (platform_device_add_data
162 (mdp_dev, pdev->dev.platform_data,
163 sizeof(struct msm_fb_panel_data))) {
164 printk(KERN_ERR "lcdc_probe: platform_device_add_data failed!\n");
165 platform_device_put(mdp_dev);
166 return -ENOMEM;
167 }
168 /*
169 * data chain
170 */
171 pdata = (struct msm_fb_panel_data *)mdp_dev->dev.platform_data;
172 pdata->on = lcdc_on;
173 pdata->off = lcdc_off;
174 pdata->next = pdev;
175
176 /*
177 * get/set panel specific fb info
178 */
179 mfd->panel_info = pdata->panel_info;
180 mfd->fb_imgType = MDP_RGB_565;
181
182 fbi = mfd->fbi;
183 fbi->var.pixclock = mfd->panel_info.clk_rate;
184 fbi->var.left_margin = mfd->panel_info.lcdc.h_back_porch;
185 fbi->var.right_margin = mfd->panel_info.lcdc.h_front_porch;
186 fbi->var.upper_margin = mfd->panel_info.lcdc.v_back_porch;
187 fbi->var.lower_margin = mfd->panel_info.lcdc.v_front_porch;
188 fbi->var.hsync_len = mfd->panel_info.lcdc.h_pulse_width;
189 fbi->var.vsync_len = mfd->panel_info.lcdc.v_pulse_width;
190
191 /*
192 * set driver data
193 */
194 platform_set_drvdata(mdp_dev, mfd);
195
196 /*
197 * register in mdp driver
198 */
199 rc = platform_device_add(mdp_dev);
200 if (rc)
201 goto lcdc_probe_err;
202
203 pdev_list[pdev_list_cnt++] = pdev;
204 return 0;
205
206lcdc_probe_err:
207 platform_device_put(mdp_dev);
208 return rc;
209}
210
211static int lcdc_remove(struct platform_device *pdev)
212{
213// pm_qos_remove_requirement(PM_QOS_SYSTEM_BUS_FREQ , "lcdc");
214 return 0;
215}
216
217static int lcdc_register_driver(void)
218{
219 return platform_driver_register(&lcdc_driver);
220}
221
222static int __init lcdc_driver_init(void)
223{
224 mdp_lcdc_pclk_clk = clk_get(NULL, "mdp_lcdc_pclk_clk");
225 if (IS_ERR(mdp_lcdc_pclk_clk)) {
226 printk(KERN_ERR "error: can't get mdp_lcdc_pclk_clk!\n");
227 return IS_ERR(mdp_lcdc_pclk_clk);
228 }
229 mdp_lcdc_pad_pclk_clk = clk_get(NULL, "mdp_lcdc_pad_pclk_clk");
230 if (IS_ERR(mdp_lcdc_pad_pclk_clk)) {
231 printk(KERN_ERR "error: can't get mdp_lcdc_pad_pclk_clk!\n");
232 return IS_ERR(mdp_lcdc_pad_pclk_clk);
233 }
234// pm_qos_add_requirement(PM_QOS_SYSTEM_BUS_FREQ , "lcdc",
235// PM_QOS_DEFAULT_VALUE);
236 return lcdc_register_driver();
237}
238
239module_init(lcdc_driver_init);
diff --git a/drivers/staging/msm/lcdc_external.c b/drivers/staging/msm/lcdc_external.c
new file mode 100644
index 000000000000..45ff78527111
--- /dev/null
+++ b/drivers/staging/msm/lcdc_external.c
@@ -0,0 +1,54 @@
1/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include "msm_fb.h"
19
20static int __init lcdc_external_init(void)
21{
22 int ret;
23 struct msm_panel_info pinfo;
24
25 if (msm_fb_detect_client("lcdc_external"))
26 return 0;
27
28 pinfo.xres = 1280;
29 pinfo.yres = 720;
30 pinfo.type = LCDC_PANEL;
31 pinfo.pdest = DISPLAY_1;
32 pinfo.wait_cycle = 0;
33 pinfo.bpp = 24;
34 pinfo.fb_num = 2;
35 pinfo.clk_rate = 74250000;
36
37 pinfo.lcdc.h_back_porch = 124;
38 pinfo.lcdc.h_front_porch = 110;
39 pinfo.lcdc.h_pulse_width = 136;
40 pinfo.lcdc.v_back_porch = 19;
41 pinfo.lcdc.v_front_porch = 5;
42 pinfo.lcdc.v_pulse_width = 6;
43 pinfo.lcdc.border_clr = 0; /* blk */
44 pinfo.lcdc.underflow_clr = 0xff; /* blue */
45 pinfo.lcdc.hsync_skew = 0;
46
47 ret = lcdc_device_register(&pinfo);
48 if (ret)
49 printk(KERN_ERR "%s: failed to register device!\n", __func__);
50
51 return ret;
52}
53
54module_init(lcdc_external_init);
diff --git a/drivers/staging/msm/lcdc_gordon.c b/drivers/staging/msm/lcdc_gordon.c
new file mode 100644
index 000000000000..399ec8c791ec
--- /dev/null
+++ b/drivers/staging/msm/lcdc_gordon.c
@@ -0,0 +1,446 @@
1/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include <linux/delay.h>
19#include <mach/gpio.h>
20#include "msm_fb.h"
21
22/* registers */
23#define GORDON_REG_NOP 0x00
24#define GORDON_REG_IMGCTL1 0x10
25#define GORDON_REG_IMGCTL2 0x11
26#define GORDON_REG_IMGSET1 0x12
27#define GORDON_REG_IMGSET2 0x13
28#define GORDON_REG_IVBP1 0x14
29#define GORDON_REG_IHBP1 0x15
30#define GORDON_REG_IVNUM1 0x16
31#define GORDON_REG_IHNUM1 0x17
32#define GORDON_REG_IVBP2 0x18
33#define GORDON_REG_IHBP2 0x19
34#define GORDON_REG_IVNUM2 0x1A
35#define GORDON_REG_IHNUM2 0x1B
36#define GORDON_REG_LCDIFCTL1 0x30
37#define GORDON_REG_VALTRAN 0x31
38#define GORDON_REG_AVCTL 0x33
39#define GORDON_REG_LCDIFCTL2 0x34
40#define GORDON_REG_LCDIFCTL3 0x35
41#define GORDON_REG_LCDIFSET1 0x36
42#define GORDON_REG_PCCTL 0x3C
43#define GORDON_REG_TPARAM1 0x40
44#define GORDON_REG_TLCDIF1 0x41
45#define GORDON_REG_TSSPB_ST1 0x42
46#define GORDON_REG_TSSPB_ED1 0x43
47#define GORDON_REG_TSCK_ST1 0x44
48#define GORDON_REG_TSCK_WD1 0x45
49#define GORDON_REG_TGSPB_VST1 0x46
50#define GORDON_REG_TGSPB_VED1 0x47
51#define GORDON_REG_TGSPB_CH1 0x48
52#define GORDON_REG_TGCK_ST1 0x49
53#define GORDON_REG_TGCK_ED1 0x4A
54#define GORDON_REG_TPCTL_ST1 0x4B
55#define GORDON_REG_TPCTL_ED1 0x4C
56#define GORDON_REG_TPCHG_ED1 0x4D
57#define GORDON_REG_TCOM_CH1 0x4E
58#define GORDON_REG_THBP1 0x4F
59#define GORDON_REG_TPHCTL1 0x50
60#define GORDON_REG_EVPH1 0x51
61#define GORDON_REG_EVPL1 0x52
62#define GORDON_REG_EVNH1 0x53
63#define GORDON_REG_EVNL1 0x54
64#define GORDON_REG_TBIAS1 0x55
65#define GORDON_REG_TPARAM2 0x56
66#define GORDON_REG_TLCDIF2 0x57
67#define GORDON_REG_TSSPB_ST2 0x58
68#define GORDON_REG_TSSPB_ED2 0x59
69#define GORDON_REG_TSCK_ST2 0x5A
70#define GORDON_REG_TSCK_WD2 0x5B
71#define GORDON_REG_TGSPB_VST2 0x5C
72#define GORDON_REG_TGSPB_VED2 0x5D
73#define GORDON_REG_TGSPB_CH2 0x5E
74#define GORDON_REG_TGCK_ST2 0x5F
75#define GORDON_REG_TGCK_ED2 0x60
76#define GORDON_REG_TPCTL_ST2 0x61
77#define GORDON_REG_TPCTL_ED2 0x62
78#define GORDON_REG_TPCHG_ED2 0x63
79#define GORDON_REG_TCOM_CH2 0x64
80#define GORDON_REG_THBP2 0x65
81#define GORDON_REG_TPHCTL2 0x66
82#define GORDON_REG_POWCTL 0x80
83
84static int lcdc_gordon_panel_off(struct platform_device *pdev);
85
86static int spi_cs;
87static int spi_sclk;
88static int spi_sdo;
89static int spi_sdi;
90static int spi_dac;
91static unsigned char bit_shift[8] = { (1 << 7), /* MSB */
92 (1 << 6),
93 (1 << 5),
94 (1 << 4),
95 (1 << 3),
96 (1 << 2),
97 (1 << 1),
98 (1 << 0) /* LSB */
99};
100
101struct gordon_state_type{
102 boolean disp_initialized;
103 boolean display_on;
104 boolean disp_powered_up;
105};
106
107static struct gordon_state_type gordon_state = { 0 };
108static struct msm_panel_common_pdata *lcdc_gordon_pdata;
109
110static void serigo(uint16 reg, uint8 data)
111{
112 unsigned int tx_val = ((0x00FF & reg) << 8) | data;
113 unsigned char i, val = 0;
114
115 /* Enable the Chip Select */
116 gpio_set_value(spi_cs, 1);
117 udelay(33);
118
119 /* Transmit it in two parts, Higher Byte first, then Lower Byte */
120 val = (unsigned char)((tx_val & 0xFF00) >> 8);
121
122 /* Clock should be Low before entering ! */
123 for (i = 0; i < 8; i++) {
124 /* #1: Drive the Data (High or Low) */
125 if (val & bit_shift[i])
126 gpio_set_value(spi_sdi, 1);
127 else
128 gpio_set_value(spi_sdi, 0);
129
130 /* #2: Drive the Clk High and then Low */
131 udelay(33);
132 gpio_set_value(spi_sclk, 1);
133 udelay(33);
134 gpio_set_value(spi_sclk, 0);
135 }
136
137 /* Idle state of SDO (MOSI) is Low */
138 gpio_set_value(spi_sdi, 0);
139 /* ..then Lower Byte */
140 val = (uint8) (tx_val & 0x00FF);
141 /* Before we enter here the Clock should be Low ! */
142
143 for (i = 0; i < 8; i++) {
144 /* #1: Drive the Data (High or Low) */
145 if (val & bit_shift[i])
146 gpio_set_value(spi_sdi, 1);
147 else
148 gpio_set_value(spi_sdi, 0);
149
150 /* #2: Drive the Clk High and then Low */
151 udelay(33);
152
153 gpio_set_value(spi_sclk, 1);
154 udelay(33);
155 gpio_set_value(spi_sclk, 0);
156 }
157
158 /* Idle state of SDO (MOSI) is Low */
159 gpio_set_value(spi_sdi, 0);
160
161 /* Now Disable the Chip Select */
162 udelay(33);
163 gpio_set_value(spi_cs, 0);
164}
165
166static void spi_init(void)
167{
168 /* Setting the Default GPIO's */
169 spi_sclk = *(lcdc_gordon_pdata->gpio_num);
170 spi_cs = *(lcdc_gordon_pdata->gpio_num + 1);
171 spi_sdi = *(lcdc_gordon_pdata->gpio_num + 2);
172 spi_sdo = *(lcdc_gordon_pdata->gpio_num + 3);
173
174 /* Set the output so that we dont disturb the slave device */
175 gpio_set_value(spi_sclk, 0);
176 gpio_set_value(spi_sdi, 0);
177
178 /* Set the Chip Select De-asserted */
179 gpio_set_value(spi_cs, 0);
180
181}
182
183static void gordon_disp_powerup(void)
184{
185 if (!gordon_state.disp_powered_up && !gordon_state.display_on) {
186 /* Reset the hardware first */
187 /* Include DAC power up implementation here */
188 gordon_state.disp_powered_up = TRUE;
189 }
190}
191
192static void gordon_init(void)
193{
194 /* Image interface settings */
195 serigo(GORDON_REG_IMGCTL2, 0x00);
196 serigo(GORDON_REG_IMGSET1, 0x00);
197
198 /* Exchange the RGB signal for J510(Softbank mobile) */
199 serigo(GORDON_REG_IMGSET2, 0x12);
200 serigo(GORDON_REG_LCDIFSET1, 0x00);
201
202 /* Pre-charge settings */
203 serigo(GORDON_REG_PCCTL, 0x09);
204 serigo(GORDON_REG_LCDIFCTL2, 0x7B);
205
206 mdelay(1);
207}
208
209static void gordon_disp_on(void)
210{
211 if (gordon_state.disp_powered_up && !gordon_state.display_on) {
212 gordon_init();
213 mdelay(20);
214 /* gordon_dispmode setting */
215 serigo(GORDON_REG_TPARAM1, 0x30);
216 serigo(GORDON_REG_TLCDIF1, 0x00);
217 serigo(GORDON_REG_TSSPB_ST1, 0x8B);
218 serigo(GORDON_REG_TSSPB_ED1, 0x93);
219 serigo(GORDON_REG_TSCK_ST1, 0x88);
220 serigo(GORDON_REG_TSCK_WD1, 0x00);
221 serigo(GORDON_REG_TGSPB_VST1, 0x01);
222 serigo(GORDON_REG_TGSPB_VED1, 0x02);
223 serigo(GORDON_REG_TGSPB_CH1, 0x5E);
224 serigo(GORDON_REG_TGCK_ST1, 0x80);
225 serigo(GORDON_REG_TGCK_ED1, 0x3C);
226 serigo(GORDON_REG_TPCTL_ST1, 0x50);
227 serigo(GORDON_REG_TPCTL_ED1, 0x74);
228 serigo(GORDON_REG_TPCHG_ED1, 0x78);
229 serigo(GORDON_REG_TCOM_CH1, 0x50);
230 serigo(GORDON_REG_THBP1, 0x84);
231 serigo(GORDON_REG_TPHCTL1, 0x00);
232 serigo(GORDON_REG_EVPH1, 0x70);
233 serigo(GORDON_REG_EVPL1, 0x64);
234 serigo(GORDON_REG_EVNH1, 0x56);
235 serigo(GORDON_REG_EVNL1, 0x48);
236 serigo(GORDON_REG_TBIAS1, 0x88);
237
238 /* QVGA settings */
239 serigo(GORDON_REG_TPARAM2, 0x28);
240 serigo(GORDON_REG_TLCDIF2, 0x14);
241 serigo(GORDON_REG_TSSPB_ST2, 0x49);
242 serigo(GORDON_REG_TSSPB_ED2, 0x4B);
243 serigo(GORDON_REG_TSCK_ST2, 0x4A);
244 serigo(GORDON_REG_TSCK_WD2, 0x02);
245 serigo(GORDON_REG_TGSPB_VST2, 0x02);
246 serigo(GORDON_REG_TGSPB_VED2, 0x03);
247 serigo(GORDON_REG_TGSPB_CH2, 0x2F);
248 serigo(GORDON_REG_TGCK_ST2, 0x40);
249 serigo(GORDON_REG_TGCK_ED2, 0x1E);
250 serigo(GORDON_REG_TPCTL_ST2, 0x2C);
251 serigo(GORDON_REG_TPCTL_ED2, 0x3A);
252 serigo(GORDON_REG_TPCHG_ED2, 0x3C);
253 serigo(GORDON_REG_TCOM_CH2, 0x28);
254 serigo(GORDON_REG_THBP2, 0x4D);
255 serigo(GORDON_REG_TPHCTL2, 0x1A);
256
257 /* VGA settings */
258 serigo(GORDON_REG_IVBP1, 0x02);
259 serigo(GORDON_REG_IHBP1, 0x90);
260 serigo(GORDON_REG_IVNUM1, 0xA0);
261 serigo(GORDON_REG_IHNUM1, 0x78);
262
263 /* QVGA settings */
264 serigo(GORDON_REG_IVBP2, 0x02);
265 serigo(GORDON_REG_IHBP2, 0x48);
266 serigo(GORDON_REG_IVNUM2, 0x50);
267 serigo(GORDON_REG_IHNUM2, 0x3C);
268
269 /* Gordon Charge pump settings and ON */
270 serigo(GORDON_REG_POWCTL, 0x03);
271 mdelay(15);
272 serigo(GORDON_REG_POWCTL, 0x07);
273 mdelay(15);
274
275 serigo(GORDON_REG_POWCTL, 0x0F);
276 mdelay(15);
277
278 serigo(GORDON_REG_AVCTL, 0x03);
279 mdelay(15);
280
281 serigo(GORDON_REG_POWCTL, 0x1F);
282 mdelay(15);
283
284 serigo(GORDON_REG_POWCTL, 0x5F);
285 mdelay(15);
286
287 serigo(GORDON_REG_POWCTL, 0x7F);
288 mdelay(15);
289
290 serigo(GORDON_REG_LCDIFCTL1, 0x02);
291 mdelay(15);
292
293 serigo(GORDON_REG_IMGCTL1, 0x00);
294 mdelay(15);
295
296 serigo(GORDON_REG_LCDIFCTL3, 0x00);
297 mdelay(15);
298
299 serigo(GORDON_REG_VALTRAN, 0x01);
300 mdelay(15);
301
302 serigo(GORDON_REG_LCDIFCTL1, 0x03);
303 mdelay(1);
304 gordon_state.display_on = TRUE;
305 }
306}
307
308static int lcdc_gordon_panel_on(struct platform_device *pdev)
309{
310 if (!gordon_state.disp_initialized) {
311 /* Configure reset GPIO that drives DAC */
312 lcdc_gordon_pdata->panel_config_gpio(1);
313 spi_dac = *(lcdc_gordon_pdata->gpio_num + 4);
314 gpio_set_value(spi_dac, 0);
315 udelay(15);
316 gpio_set_value(spi_dac, 1);
317 spi_init(); /* LCD needs SPI */
318 gordon_disp_powerup();
319 gordon_disp_on();
320 gordon_state.disp_initialized = TRUE;
321 }
322 return 0;
323}
324
325static int lcdc_gordon_panel_off(struct platform_device *pdev)
326{
327 if (gordon_state.disp_powered_up && gordon_state.display_on) {
328 serigo(GORDON_REG_LCDIFCTL2, 0x7B);
329 serigo(GORDON_REG_VALTRAN, 0x01);
330 serigo(GORDON_REG_LCDIFCTL1, 0x02);
331 serigo(GORDON_REG_LCDIFCTL3, 0x01);
332 mdelay(20);
333 serigo(GORDON_REG_VALTRAN, 0x01);
334 serigo(GORDON_REG_IMGCTL1, 0x01);
335 serigo(GORDON_REG_LCDIFCTL1, 0x00);
336 mdelay(20);
337
338 serigo(GORDON_REG_POWCTL, 0x1F);
339 mdelay(40);
340
341 serigo(GORDON_REG_POWCTL, 0x07);
342 mdelay(40);
343
344 serigo(GORDON_REG_POWCTL, 0x03);
345 mdelay(40);
346
347 serigo(GORDON_REG_POWCTL, 0x00);
348 mdelay(40);
349 lcdc_gordon_pdata->panel_config_gpio(0);
350 gordon_state.display_on = FALSE;
351 gordon_state.disp_initialized = FALSE;
352 }
353 return 0;
354}
355
356static void lcdc_gordon_set_backlight(struct msm_fb_data_type *mfd)
357{
358 int bl_level = mfd->bl_level;
359
360 if (bl_level <= 1) {
361 /* keep back light OFF */
362 serigo(GORDON_REG_LCDIFCTL2, 0x0B);
363 udelay(15);
364 serigo(GORDON_REG_VALTRAN, 0x01);
365 } else {
366 /* keep back light ON */
367 serigo(GORDON_REG_LCDIFCTL2, 0x7B);
368 udelay(15);
369 serigo(GORDON_REG_VALTRAN, 0x01);
370 }
371}
372
373static int __init gordon_probe(struct platform_device *pdev)
374{
375 if (pdev->id == 0) {
376 lcdc_gordon_pdata = pdev->dev.platform_data;
377 return 0;
378 }
379 msm_fb_add_device(pdev);
380 return 0;
381}
382
383static struct platform_driver this_driver = {
384 .probe = gordon_probe,
385 .driver = {
386 .name = "lcdc_gordon_vga",
387 },
388};
389
390static struct msm_fb_panel_data gordon_panel_data = {
391 .on = lcdc_gordon_panel_on,
392 .off = lcdc_gordon_panel_off,
393 .set_backlight = lcdc_gordon_set_backlight,
394};
395
396static struct platform_device this_device = {
397 .name = "lcdc_gordon_vga",
398 .id = 1,
399 .dev = {
400 .platform_data = &gordon_panel_data,
401 }
402};
403
404static int __init lcdc_gordon_panel_init(void)
405{
406 int ret;
407 struct msm_panel_info *pinfo;
408
409#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
410 if (msm_fb_detect_client("lcdc_gordon_vga"))
411 return 0;
412#endif
413 ret = platform_driver_register(&this_driver);
414 if (ret)
415 return ret;
416
417 pinfo = &gordon_panel_data.panel_info;
418 pinfo->xres = 480;
419 pinfo->yres = 640;
420 pinfo->type = LCDC_PANEL;
421 pinfo->pdest = DISPLAY_1;
422 pinfo->wait_cycle = 0;
423 pinfo->bpp = 24;
424 pinfo->fb_num = 2;
425 pinfo->clk_rate = 24500000;
426 pinfo->bl_max = 4;
427 pinfo->bl_min = 1;
428
429 pinfo->lcdc.h_back_porch = 84;
430 pinfo->lcdc.h_front_porch = 33;
431 pinfo->lcdc.h_pulse_width = 60;
432 pinfo->lcdc.v_back_porch = 0;
433 pinfo->lcdc.v_front_porch = 2;
434 pinfo->lcdc.v_pulse_width = 2;
435 pinfo->lcdc.border_clr = 0; /* blk */
436 pinfo->lcdc.underflow_clr = 0xff; /* blue */
437 pinfo->lcdc.hsync_skew = 0;
438
439 ret = platform_device_register(&this_device);
440 if (ret)
441 platform_driver_unregister(&this_driver);
442
443 return ret;
444}
445
446module_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
index 000000000000..7284649ea0ae
--- /dev/null
+++ b/drivers/staging/msm/lcdc_grapefruit.c
@@ -0,0 +1,60 @@
1/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include "msm_fb.h"
19
20#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
21#include "mddihosti.h"
22#endif
23
24static int __init lcdc_grapefruit_init(void)
25{
26 int ret;
27 struct msm_panel_info pinfo;
28
29#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
30 if (msm_fb_detect_client("lcdc_grapefruit_vga"))
31 return 0;
32#endif
33
34 pinfo.xres = 1024;
35 pinfo.yres = 600;
36 pinfo.type = LCDC_PANEL;
37 pinfo.pdest = DISPLAY_1;
38 pinfo.wait_cycle = 0;
39 pinfo.bpp = 18;
40 pinfo.fb_num = 2;
41 pinfo.clk_rate = 40000000;
42
43 pinfo.lcdc.h_back_porch = 88;
44 pinfo.lcdc.h_front_porch = 40;
45 pinfo.lcdc.h_pulse_width = 128;
46 pinfo.lcdc.v_back_porch = 23;
47 pinfo.lcdc.v_front_porch = 1;
48 pinfo.lcdc.v_pulse_width = 4;
49 pinfo.lcdc.border_clr = 0; /* blk */
50 pinfo.lcdc.underflow_clr = 0xff; /* blue */
51 pinfo.lcdc.hsync_skew = 0;
52
53 ret = lcdc_device_register(&pinfo);
54 if (ret)
55 printk(KERN_ERR "%s: failed to register device!\n", __func__);
56
57 return ret;
58}
59
60module_init(lcdc_grapefruit_init);
diff --git a/drivers/staging/msm/lcdc_panel.c b/drivers/staging/msm/lcdc_panel.c
new file mode 100644
index 000000000000..b40974e1f27c
--- /dev/null
+++ b/drivers/staging/msm/lcdc_panel.c
@@ -0,0 +1,88 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include "msm_fb.h"
19
20static int lcdc_panel_on(struct platform_device *pdev)
21{
22 return 0;
23}
24
25static int lcdc_panel_off(struct platform_device *pdev)
26{
27 return 0;
28}
29
30static int __init lcdc_panel_probe(struct platform_device *pdev)
31{
32 msm_fb_add_device(pdev);
33
34 return 0;
35}
36
37static struct platform_driver this_driver = {
38 .probe = lcdc_panel_probe,
39 .driver = {
40 .name = "lcdc_panel",
41 },
42};
43
44static struct msm_fb_panel_data lcdc_panel_data = {
45 .on = lcdc_panel_on,
46 .off = lcdc_panel_off,
47};
48
49static int lcdc_dev_id;
50
51int lcdc_device_register(struct msm_panel_info *pinfo)
52{
53 struct platform_device *pdev = NULL;
54 int ret;
55
56 pdev = platform_device_alloc("lcdc_panel", ++lcdc_dev_id);
57 if (!pdev)
58 return -ENOMEM;
59
60 lcdc_panel_data.panel_info = *pinfo;
61 ret = platform_device_add_data(pdev, &lcdc_panel_data,
62 sizeof(lcdc_panel_data));
63 if (ret) {
64 printk(KERN_ERR
65 "%s: platform_device_add_data failed!\n", __func__);
66 goto err_device_put;
67 }
68
69 ret = platform_device_add(pdev);
70 if (ret) {
71 printk(KERN_ERR
72 "%s: platform_device_register failed!\n", __func__);
73 goto err_device_put;
74 }
75
76 return 0;
77
78err_device_put:
79 platform_device_put(pdev);
80 return ret;
81}
82
83static int __init lcdc_panel_init(void)
84{
85 return platform_driver_register(&this_driver);
86}
87
88module_init(lcdc_panel_init);
diff --git a/drivers/staging/msm/lcdc_prism.c b/drivers/staging/msm/lcdc_prism.c
new file mode 100644
index 000000000000..d102c98447c1
--- /dev/null
+++ b/drivers/staging/msm/lcdc_prism.c
@@ -0,0 +1,64 @@
1/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include "msm_fb.h"
19
20#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
21#include "mddihosti.h"
22#endif
23
24static int __init lcdc_prism_init(void)
25{
26 int ret;
27 struct msm_panel_info pinfo;
28
29#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
30 ret = msm_fb_detect_client("lcdc_prism_wvga");
31 if (ret == -ENODEV)
32 return 0;
33
34 if (ret && (mddi_get_client_id() != 0))
35 return 0;
36#endif
37
38 pinfo.xres = 800;
39 pinfo.yres = 480;
40 pinfo.type = LCDC_PANEL;
41 pinfo.pdest = DISPLAY_1;
42 pinfo.wait_cycle = 0;
43 pinfo.bpp = 24;
44 pinfo.fb_num = 2;
45 pinfo.clk_rate = 38460000;
46
47 pinfo.lcdc.h_back_porch = 21;
48 pinfo.lcdc.h_front_porch = 81;
49 pinfo.lcdc.h_pulse_width = 60;
50 pinfo.lcdc.v_back_porch = 18;
51 pinfo.lcdc.v_front_porch = 27;
52 pinfo.lcdc.v_pulse_width = 2;
53 pinfo.lcdc.border_clr = 0; /* blk */
54 pinfo.lcdc.underflow_clr = 0xff; /* blue */
55 pinfo.lcdc.hsync_skew = 0;
56
57 ret = lcdc_device_register(&pinfo);
58 if (ret)
59 printk(KERN_ERR "%s: failed to register device!\n", __func__);
60
61 return ret;
62}
63
64module_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
index 000000000000..1f08cf9bc217
--- /dev/null
+++ b/drivers/staging/msm/lcdc_sharp_wvga_pt.c
@@ -0,0 +1,290 @@
1/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include <linux/delay.h>
19#ifdef CONFIG_ARCH_MSM7X30
20#include <linux/mfd/pmic8058.h>
21#endif
22#include <mach/gpio.h>
23#include "msm_fb.h"
24
25static int lcdc_sharp_panel_off(struct platform_device *pdev);
26
27static int spi_cs;
28static int spi_sclk;
29static int spi_mosi;
30static int spi_miso;
31static unsigned char bit_shift[8] = { (1 << 7), /* MSB */
32 (1 << 6),
33 (1 << 5),
34 (1 << 4),
35 (1 << 3),
36 (1 << 2),
37 (1 << 1),
38 (1 << 0) /* LSB */
39};
40
41struct sharp_state_type {
42 boolean disp_initialized;
43 boolean display_on;
44 boolean disp_powered_up;
45};
46
47struct sharp_spi_data {
48 u8 addr;
49 u8 data;
50};
51
52static struct sharp_spi_data init_sequence[] = {
53 { 15, 0x01 },
54 { 5, 0x01 },
55 { 7, 0x10 },
56 { 9, 0x1E },
57 { 10, 0x04 },
58 { 17, 0xFF },
59 { 21, 0x8A },
60 { 22, 0x00 },
61 { 23, 0x82 },
62 { 24, 0x24 },
63 { 25, 0x22 },
64 { 26, 0x6D },
65 { 27, 0xEB },
66 { 28, 0xB9 },
67 { 29, 0x3A },
68 { 49, 0x1A },
69 { 50, 0x16 },
70 { 51, 0x05 },
71 { 55, 0x7F },
72 { 56, 0x15 },
73 { 57, 0x7B },
74 { 60, 0x05 },
75 { 61, 0x0C },
76 { 62, 0x80 },
77 { 63, 0x00 },
78 { 92, 0x90 },
79 { 97, 0x01 },
80 { 98, 0xFF },
81 { 113, 0x11 },
82 { 114, 0x02 },
83 { 115, 0x08 },
84 { 123, 0xAB },
85 { 124, 0x04 },
86 { 6, 0x02 },
87 { 133, 0x00 },
88 { 134, 0xFE },
89 { 135, 0x22 },
90 { 136, 0x0B },
91 { 137, 0xFF },
92 { 138, 0x0F },
93 { 139, 0x00 },
94 { 140, 0xFE },
95 { 141, 0x22 },
96 { 142, 0x0B },
97 { 143, 0xFF },
98 { 144, 0x0F },
99 { 145, 0x00 },
100 { 146, 0xFE },
101 { 147, 0x22 },
102 { 148, 0x0B },
103 { 149, 0xFF },
104 { 150, 0x0F },
105 { 202, 0x30 },
106 { 30, 0x01 },
107 { 4, 0x01 },
108 { 31, 0x41 },
109};
110
111static struct sharp_state_type sharp_state = { 0 };
112static struct msm_panel_common_pdata *lcdc_sharp_pdata;
113
114static void sharp_spi_write_byte(u8 val)
115{
116 int i;
117
118 /* Clock should be Low before entering */
119 for (i = 0; i < 8; i++) {
120 /* #1: Drive the Data (High or Low) */
121 if (val & bit_shift[i])
122 gpio_set_value(spi_mosi, 1);
123 else
124 gpio_set_value(spi_mosi, 0);
125
126 /* #2: Drive the Clk High and then Low */
127 gpio_set_value(spi_sclk, 1);
128 gpio_set_value(spi_sclk, 0);
129 }
130}
131
132static void serigo(u8 reg, u8 data)
133{
134 /* Enable the Chip Select - low */
135 gpio_set_value(spi_cs, 0);
136 udelay(1);
137
138 /* Transmit register address first, then data */
139 sharp_spi_write_byte(reg);
140
141 /* Idle state of MOSI is Low */
142 gpio_set_value(spi_mosi, 0);
143 udelay(1);
144 sharp_spi_write_byte(data);
145
146 gpio_set_value(spi_mosi, 0);
147 gpio_set_value(spi_cs, 1);
148}
149
150static void sharp_spi_init(void)
151{
152 spi_sclk = *(lcdc_sharp_pdata->gpio_num);
153 spi_cs = *(lcdc_sharp_pdata->gpio_num + 1);
154 spi_mosi = *(lcdc_sharp_pdata->gpio_num + 2);
155 spi_miso = *(lcdc_sharp_pdata->gpio_num + 3);
156
157 /* Set the output so that we don't disturb the slave device */
158 gpio_set_value(spi_sclk, 0);
159 gpio_set_value(spi_mosi, 0);
160
161 /* Set the Chip Select deasserted (active low) */
162 gpio_set_value(spi_cs, 1);
163}
164
165static void sharp_disp_powerup(void)
166{
167 if (!sharp_state.disp_powered_up && !sharp_state.display_on)
168 sharp_state.disp_powered_up = TRUE;
169}
170
171static void sharp_disp_on(void)
172{
173 int i;
174
175 if (sharp_state.disp_powered_up && !sharp_state.display_on) {
176 for (i = 0; i < ARRAY_SIZE(init_sequence); i++) {
177 serigo(init_sequence[i].addr,
178 init_sequence[i].data);
179 }
180 mdelay(10);
181 serigo(31, 0xC1);
182 mdelay(10);
183 serigo(31, 0xD9);
184 serigo(31, 0xDF);
185
186 sharp_state.display_on = TRUE;
187 }
188}
189
190static int lcdc_sharp_panel_on(struct platform_device *pdev)
191{
192 if (!sharp_state.disp_initialized) {
193 lcdc_sharp_pdata->panel_config_gpio(1);
194 sharp_spi_init();
195 sharp_disp_powerup();
196 sharp_disp_on();
197 sharp_state.disp_initialized = TRUE;
198 }
199 return 0;
200}
201
202static int lcdc_sharp_panel_off(struct platform_device *pdev)
203{
204 if (sharp_state.disp_powered_up && sharp_state.display_on) {
205 serigo(4, 0x00);
206 mdelay(40);
207 serigo(31, 0xC1);
208 mdelay(40);
209 serigo(31, 0x00);
210 mdelay(100);
211 sharp_state.display_on = FALSE;
212 sharp_state.disp_initialized = FALSE;
213 }
214 return 0;
215}
216
217static int __init sharp_probe(struct platform_device *pdev)
218{
219 if (pdev->id == 0) {
220 lcdc_sharp_pdata = pdev->dev.platform_data;
221 return 0;
222 }
223 msm_fb_add_device(pdev);
224 return 0;
225}
226
227static struct platform_driver this_driver = {
228 .probe = sharp_probe,
229 .driver = {
230 .name = "lcdc_sharp_wvga",
231 },
232};
233
234static struct msm_fb_panel_data sharp_panel_data = {
235 .on = lcdc_sharp_panel_on,
236 .off = lcdc_sharp_panel_off,
237};
238
239static struct platform_device this_device = {
240 .name = "lcdc_sharp_wvga",
241 .id = 1,
242 .dev = {
243 .platform_data = &sharp_panel_data,
244 }
245};
246
247static int __init lcdc_sharp_panel_init(void)
248{
249 int ret;
250 struct msm_panel_info *pinfo;
251
252#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
253 if (msm_fb_detect_client("lcdc_sharp_wvga_pt"))
254 return 0;
255#endif
256
257 ret = platform_driver_register(&this_driver);
258 if (ret)
259 return ret;
260
261 pinfo = &sharp_panel_data.panel_info;
262 pinfo->xres = 480;
263 pinfo->yres = 800;
264 pinfo->type = LCDC_PANEL;
265 pinfo->pdest = DISPLAY_1;
266 pinfo->wait_cycle = 0;
267 pinfo->bpp = 18;
268 pinfo->fb_num = 2;
269 pinfo->clk_rate = 24500000;
270 pinfo->bl_max = 4;
271 pinfo->bl_min = 1;
272
273 pinfo->lcdc.h_back_porch = 20;
274 pinfo->lcdc.h_front_porch = 10;
275 pinfo->lcdc.h_pulse_width = 10;
276 pinfo->lcdc.v_back_porch = 2;
277 pinfo->lcdc.v_front_porch = 2;
278 pinfo->lcdc.v_pulse_width = 2;
279 pinfo->lcdc.border_clr = 0;
280 pinfo->lcdc.underflow_clr = 0xff;
281 pinfo->lcdc.hsync_skew = 0;
282
283 ret = platform_device_register(&this_device);
284 if (ret)
285 platform_driver_unregister(&this_driver);
286
287 return ret;
288}
289
290module_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
index 000000000000..fed8278eb153
--- /dev/null
+++ b/drivers/staging/msm/lcdc_st15.c
@@ -0,0 +1,237 @@
1/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include <linux/i2c.h>
19#include <linux/delay.h>
20#include "msm_fb.h"
21
22#define DEVICE_NAME "sii9022"
23#define SII9022_DEVICE_ID 0xB0
24
25struct sii9022_i2c_addr_data{
26 u8 addr;
27 u8 data;
28};
29
30/* video mode data */
31static u8 video_mode_data[] = {
32 0x00,
33 0xF9, 0x1C, 0x70, 0x17, 0x72, 0x06, 0xEE, 0x02,
34};
35
36static u8 avi_io_format[] = {
37 0x09,
38 0x00, 0x00,
39};
40
41/* power state */
42static struct sii9022_i2c_addr_data regset0[] = {
43 { 0x60, 0x04 },
44 { 0x63, 0x00 },
45 { 0x1E, 0x00 },
46};
47
48static u8 video_infoframe[] = {
49 0x0C,
50 0xF0, 0x00, 0x68, 0x00, 0x04, 0x00, 0x19, 0x00,
51 0xE9, 0x02, 0x04, 0x01, 0x04, 0x06,
52};
53
54/* configure audio */
55static struct sii9022_i2c_addr_data regset1[] = {
56 { 0x26, 0x90 },
57 { 0x20, 0x90 },
58 { 0x1F, 0x80 },
59 { 0x26, 0x80 },
60 { 0x24, 0x02 },
61 { 0x25, 0x0B },
62 { 0xBC, 0x02 },
63 { 0xBD, 0x24 },
64 { 0xBE, 0x02 },
65};
66
67/* enable audio */
68static u8 misc_infoframe[] = {
69 0xBF,
70 0xC2, 0x84, 0x01, 0x0A, 0x6F, 0x02, 0x00, 0x00,
71 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72};
73
74/* set HDMI, active */
75static struct sii9022_i2c_addr_data regset2[] = {
76 { 0x1A, 0x01 },
77 { 0x3D, 0x00 },
78};
79
80static int send_i2c_data(struct i2c_client *client,
81 struct sii9022_i2c_addr_data *regset,
82 int size)
83{
84 int i;
85 int rc = 0;
86
87 for (i = 0; i < size; i++) {
88 rc = i2c_smbus_write_byte_data(
89 client,
90 regset[i].addr, regset[i].data);
91 if (rc)
92 break;
93 }
94 return rc;
95}
96
97static int hdmi_sii_enable(struct i2c_client *client)
98{
99 int rc;
100 int retries = 10;
101 int count;
102
103 rc = i2c_smbus_write_byte_data(client, 0xC7, 0x00);
104 if (rc)
105 goto enable_exit;
106
107 do {
108 msleep(1);
109 rc = i2c_smbus_read_byte_data(client, 0x1B);
110 } while ((rc != SII9022_DEVICE_ID) && retries--);
111
112 if (rc != SII9022_DEVICE_ID)
113 return -ENODEV;
114
115 rc = i2c_smbus_write_byte_data(client, 0x1A, 0x11);
116 if (rc)
117 goto enable_exit;
118
119 count = ARRAY_SIZE(video_mode_data);
120 rc = i2c_master_send(client, video_mode_data, count);
121 if (rc != count) {
122 rc = -EIO;
123 goto enable_exit;
124 }
125
126 rc = i2c_smbus_write_byte_data(client, 0x08, 0x20);
127 if (rc)
128 goto enable_exit;
129 count = ARRAY_SIZE(avi_io_format);
130 rc = i2c_master_send(client, avi_io_format, count);
131 if (rc != count) {
132 rc = -EIO;
133 goto enable_exit;
134 }
135
136 rc = send_i2c_data(client, regset0, ARRAY_SIZE(regset0));
137 if (rc)
138 goto enable_exit;
139
140 count = ARRAY_SIZE(video_infoframe);
141 rc = i2c_master_send(client, video_infoframe, count);
142 if (rc != count) {
143 rc = -EIO;
144 goto enable_exit;
145 }
146
147 rc = send_i2c_data(client, regset1, ARRAY_SIZE(regset1));
148 if (rc)
149 goto enable_exit;
150
151 count = ARRAY_SIZE(misc_infoframe);
152 rc = i2c_master_send(client, misc_infoframe, count);
153 if (rc != count) {
154 rc = -EIO;
155 goto enable_exit;
156 }
157
158 rc = send_i2c_data(client, regset2, ARRAY_SIZE(regset2));
159 if (rc)
160 goto enable_exit;
161
162 return 0;
163enable_exit:
164 printk(KERN_ERR "%s: exited rc=%d\n", __func__, rc);
165 return rc;
166}
167
168static const struct i2c_device_id hmdi_sii_id[] = {
169 { DEVICE_NAME, 0 },
170 { }
171};
172
173static int hdmi_sii_probe(struct i2c_client *client,
174 const struct i2c_device_id *id)
175{
176 int rc;
177
178 if (!i2c_check_functionality(client->adapter,
179 I2C_FUNC_SMBUS_BYTE | I2C_FUNC_I2C))
180 return -ENODEV;
181 rc = hdmi_sii_enable(client);
182 return rc;
183}
184
185
186static struct i2c_driver hdmi_sii_i2c_driver = {
187 .driver = {
188 .name = DEVICE_NAME,
189 .owner = THIS_MODULE,
190 },
191 .probe = hdmi_sii_probe,
192 .remove = __exit_p(hdmi_sii_remove),
193 .id_table = hmdi_sii_id,
194};
195
196static int __init lcdc_st15_init(void)
197{
198 int ret;
199 struct msm_panel_info pinfo;
200
201 if (msm_fb_detect_client("lcdc_st15"))
202 return 0;
203
204 pinfo.xres = 1366;
205 pinfo.yres = 768;
206 pinfo.type = LCDC_PANEL;
207 pinfo.pdest = DISPLAY_1;
208 pinfo.wait_cycle = 0;
209 pinfo.bpp = 24;
210 pinfo.fb_num = 2;
211 pinfo.clk_rate = 74250000;
212
213 pinfo.lcdc.h_back_porch = 120;
214 pinfo.lcdc.h_front_porch = 20;
215 pinfo.lcdc.h_pulse_width = 40;
216 pinfo.lcdc.v_back_porch = 25;
217 pinfo.lcdc.v_front_porch = 1;
218 pinfo.lcdc.v_pulse_width = 7;
219 pinfo.lcdc.border_clr = 0; /* blk */
220 pinfo.lcdc.underflow_clr = 0xff; /* blue */
221 pinfo.lcdc.hsync_skew = 0;
222
223 ret = lcdc_device_register(&pinfo);
224 if (ret) {
225 printk(KERN_ERR "%s: failed to register device!\n", __func__);
226 goto init_exit;
227 }
228
229 ret = i2c_add_driver(&hdmi_sii_i2c_driver);
230 if (ret)
231 printk(KERN_ERR "%s: failed to add i2c driver\n", __func__);
232
233init_exit:
234 return ret;
235}
236
237module_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
index 000000000000..73760019cf2e
--- /dev/null
+++ b/drivers/staging/msm/lcdc_st1_wxga.c
@@ -0,0 +1,54 @@
1/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include "msm_fb.h"
19
20static int __init lcdc_st1_wxga_init(void)
21{
22 int ret;
23 struct msm_panel_info pinfo;
24
25 if (msm_fb_detect_client("lcdc_st1_wxga"))
26 return 0;
27
28 pinfo.xres = 1280;
29 pinfo.yres = 720;
30 pinfo.type = LCDC_PANEL;
31 pinfo.pdest = DISPLAY_1;
32 pinfo.wait_cycle = 0;
33 pinfo.bpp = 18;
34 pinfo.fb_num = 2;
35 pinfo.clk_rate = 74250000;
36
37 pinfo.lcdc.h_back_porch = 124;
38 pinfo.lcdc.h_front_porch = 110;
39 pinfo.lcdc.h_pulse_width = 136;
40 pinfo.lcdc.v_back_porch = 19;
41 pinfo.lcdc.v_front_porch = 5;
42 pinfo.lcdc.v_pulse_width = 6;
43 pinfo.lcdc.border_clr = 0; /* blk */
44 pinfo.lcdc.underflow_clr = 0xff; /* blue */
45 pinfo.lcdc.hsync_skew = 0;
46
47 ret = lcdc_device_register(&pinfo);
48 if (ret)
49 printk(KERN_ERR "%s: failed to register device!\n", __func__);
50
51 return ret;
52}
53
54module_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
index 000000000000..864d7c18913d
--- /dev/null
+++ b/drivers/staging/msm/lcdc_toshiba_wvga_pt.c
@@ -0,0 +1,374 @@
1/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include <linux/delay.h>
19#include <linux/module.h>
20#include <mach/gpio.h>
21#include <mach/pmic.h>
22#include "msm_fb.h"
23
24#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
25#include "mddihosti.h"
26#endif
27
28static int spi_cs;
29static int spi_sclk;
30static int spi_mosi;
31static int spi_miso;
32
33struct toshiba_state_type{
34 boolean disp_initialized;
35 boolean display_on;
36 boolean disp_powered_up;
37};
38
39static struct toshiba_state_type toshiba_state = { 0 };
40static struct msm_panel_common_pdata *lcdc_toshiba_pdata;
41
42static void toshiba_spi_write_byte(char dc, uint8 data)
43{
44 uint32 bit;
45 int bnum;
46
47 gpio_set_value(spi_sclk, 0); /* clk low */
48 /* dc: 0 for command, 1 for parameter */
49 gpio_set_value(spi_mosi, dc);
50 udelay(1); /* at least 20 ns */
51 gpio_set_value(spi_sclk, 1); /* clk high */
52 udelay(1); /* at least 20 ns */
53 bnum = 8; /* 8 data bits */
54 bit = 0x80;
55 while (bnum) {
56 gpio_set_value(spi_sclk, 0); /* clk low */
57 if (data & bit)
58 gpio_set_value(spi_mosi, 1);
59 else
60 gpio_set_value(spi_mosi, 0);
61 udelay(1);
62 gpio_set_value(spi_sclk, 1); /* clk high */
63 udelay(1);
64 bit >>= 1;
65 bnum--;
66 }
67}
68
69static void toshiba_spi_write(char cmd, uint32 data, int num)
70{
71 char *bp;
72
73 gpio_set_value(spi_cs, 1); /* cs high */
74
75 /* command byte first */
76 toshiba_spi_write_byte(0, cmd);
77
78 /* followed by parameter bytes */
79 if (num) {
80 bp = (char *)&data;;
81 bp += (num - 1);
82 while (num) {
83 toshiba_spi_write_byte(1, *bp);
84 num--;
85 bp--;
86 }
87 }
88
89 gpio_set_value(spi_cs, 0); /* cs low */
90 udelay(1);
91}
92
93void toshiba_spi_read_bytes(char cmd, uint32 *data, int num)
94{
95 uint32 dbit, bits;
96 int bnum;
97
98 gpio_set_value(spi_cs, 1); /* cs high */
99
100 /* command byte first */
101 toshiba_spi_write_byte(0, cmd);
102
103 if (num > 1) {
104 /* extra dc bit */
105 gpio_set_value(spi_sclk, 0); /* clk low */
106 udelay(1);
107 dbit = gpio_get_value(spi_miso);/* dc bit */
108 udelay(1);
109 gpio_set_value(spi_sclk, 1); /* clk high */
110 }
111
112 /* followed by data bytes */
113 bnum = num * 8; /* number of bits */
114 bits = 0;
115 while (bnum) {
116 bits <<= 1;
117 gpio_set_value(spi_sclk, 0); /* clk low */
118 udelay(1);
119 dbit = gpio_get_value(spi_miso);
120 udelay(1);
121 gpio_set_value(spi_sclk, 1); /* clk high */
122 bits |= dbit;
123 bnum--;
124 }
125
126 *data = bits;
127
128 udelay(1);
129 gpio_set_value(spi_cs, 0); /* cs low */
130 udelay(1);
131}
132
133static void spi_pin_assign(void)
134{
135 /* Setting the Default GPIO's */
136 spi_sclk = *(lcdc_toshiba_pdata->gpio_num);
137 spi_cs = *(lcdc_toshiba_pdata->gpio_num + 1);
138 spi_mosi = *(lcdc_toshiba_pdata->gpio_num + 2);
139 spi_miso = *(lcdc_toshiba_pdata->gpio_num + 3);
140}
141
142static void toshiba_disp_powerup(void)
143{
144 if (!toshiba_state.disp_powered_up && !toshiba_state.display_on) {
145 /* Reset the hardware first */
146 /* Include DAC power up implementation here */
147 toshiba_state.disp_powered_up = TRUE;
148 }
149}
150
151static void toshiba_disp_on(void)
152{
153 uint32 data;
154
155 gpio_set_value(spi_cs, 0); /* low */
156 gpio_set_value(spi_sclk, 1); /* high */
157 gpio_set_value(spi_mosi, 0);
158 gpio_set_value(spi_miso, 0);
159
160 if (toshiba_state.disp_powered_up && !toshiba_state.display_on) {
161 toshiba_spi_write(0, 0, 0);
162 mdelay(7);
163 toshiba_spi_write(0, 0, 0);
164 mdelay(7);
165 toshiba_spi_write(0, 0, 0);
166 mdelay(7);
167 toshiba_spi_write(0xba, 0x11, 1);
168 toshiba_spi_write(0x36, 0x00, 1);
169 mdelay(1);
170 toshiba_spi_write(0x3a, 0x60, 1);
171 toshiba_spi_write(0xb1, 0x5d, 1);
172 mdelay(1);
173 toshiba_spi_write(0xb2, 0x33, 1);
174 toshiba_spi_write(0xb3, 0x22, 1);
175 mdelay(1);
176 toshiba_spi_write(0xb4, 0x02, 1);
177 toshiba_spi_write(0xb5, 0x1e, 1); /* vcs -- adjust brightness */
178 mdelay(1);
179 toshiba_spi_write(0xb6, 0x27, 1);
180 toshiba_spi_write(0xb7, 0x03, 1);
181 mdelay(1);
182 toshiba_spi_write(0xb9, 0x24, 1);
183 toshiba_spi_write(0xbd, 0xa1, 1);
184 mdelay(1);
185 toshiba_spi_write(0xbb, 0x00, 1);
186 toshiba_spi_write(0xbf, 0x01, 1);
187 mdelay(1);
188 toshiba_spi_write(0xbe, 0x00, 1);
189 toshiba_spi_write(0xc0, 0x11, 1);
190 mdelay(1);
191 toshiba_spi_write(0xc1, 0x11, 1);
192 toshiba_spi_write(0xc2, 0x11, 1);
193 mdelay(1);
194 toshiba_spi_write(0xc3, 0x3232, 2);
195 mdelay(1);
196 toshiba_spi_write(0xc4, 0x3232, 2);
197 mdelay(1);
198 toshiba_spi_write(0xc5, 0x3232, 2);
199 mdelay(1);
200 toshiba_spi_write(0xc6, 0x3232, 2);
201 mdelay(1);
202 toshiba_spi_write(0xc7, 0x6445, 2);
203 mdelay(1);
204 toshiba_spi_write(0xc8, 0x44, 1);
205 toshiba_spi_write(0xc9, 0x52, 1);
206 mdelay(1);
207 toshiba_spi_write(0xca, 0x00, 1);
208 mdelay(1);
209 toshiba_spi_write(0xec, 0x02a4, 2); /* 0x02a4 */
210 mdelay(1);
211 toshiba_spi_write(0xcf, 0x01, 1);
212 mdelay(1);
213 toshiba_spi_write(0xd0, 0xc003, 2); /* c003 */
214 mdelay(1);
215 toshiba_spi_write(0xd1, 0x01, 1);
216 mdelay(1);
217 toshiba_spi_write(0xd2, 0x0028, 2);
218 mdelay(1);
219 toshiba_spi_write(0xd3, 0x0028, 2);
220 mdelay(1);
221 toshiba_spi_write(0xd4, 0x26a4, 2);
222 mdelay(1);
223 toshiba_spi_write(0xd5, 0x20, 1);
224 mdelay(1);
225 toshiba_spi_write(0xef, 0x3200, 2);
226 mdelay(32);
227 toshiba_spi_write(0xbc, 0x80, 1); /* wvga pass through */
228 toshiba_spi_write(0x3b, 0x00, 1);
229 mdelay(1);
230 toshiba_spi_write(0xb0, 0x16, 1);
231 mdelay(1);
232 toshiba_spi_write(0xb8, 0xfff5, 2);
233 mdelay(1);
234 toshiba_spi_write(0x11, 0, 0);
235 mdelay(5);
236 toshiba_spi_write(0x29, 0, 0);
237 mdelay(5);
238 toshiba_state.display_on = TRUE;
239 }
240
241 data = 0;
242 toshiba_spi_read_bytes(0x04, &data, 3);
243 printk(KERN_INFO "toshiba_disp_on: id=%x\n", data);
244
245}
246
247static int lcdc_toshiba_panel_on(struct platform_device *pdev)
248{
249 if (!toshiba_state.disp_initialized) {
250 /* Configure reset GPIO that drives DAC */
251 if (lcdc_toshiba_pdata->panel_config_gpio)
252 lcdc_toshiba_pdata->panel_config_gpio(1);
253 toshiba_disp_powerup();
254 toshiba_disp_on();
255 toshiba_state.disp_initialized = TRUE;
256 }
257 return 0;
258}
259
260static int lcdc_toshiba_panel_off(struct platform_device *pdev)
261{
262 if (toshiba_state.disp_powered_up && toshiba_state.display_on) {
263 /* Main panel power off (Deep standby in) */
264
265 toshiba_spi_write(0x28, 0, 0); /* display off */
266 mdelay(1);
267 toshiba_spi_write(0xb8, 0x8002, 2); /* output control */
268 mdelay(1);
269 toshiba_spi_write(0x10, 0x00, 1); /* sleep mode in */
270 mdelay(85); /* wait 85 msec */
271 toshiba_spi_write(0xb0, 0x00, 1); /* deep standby in */
272 mdelay(1);
273 if (lcdc_toshiba_pdata->panel_config_gpio)
274 lcdc_toshiba_pdata->panel_config_gpio(0);
275 toshiba_state.display_on = FALSE;
276 toshiba_state.disp_initialized = FALSE;
277 }
278 return 0;
279}
280
281static void lcdc_toshiba_set_backlight(struct msm_fb_data_type *mfd)
282{
283 int bl_level;
284 int ret = -EPERM;
285
286 bl_level = mfd->bl_level;
287 ret = pmic_set_led_intensity(LED_LCD, bl_level);
288
289 if (ret)
290 printk(KERN_WARNING "%s: can't set lcd backlight!\n",
291 __func__);
292}
293
294static int __init toshiba_probe(struct platform_device *pdev)
295{
296 if (pdev->id == 0) {
297 lcdc_toshiba_pdata = pdev->dev.platform_data;
298 spi_pin_assign();
299 return 0;
300 }
301 msm_fb_add_device(pdev);
302 return 0;
303}
304
305static struct platform_driver this_driver = {
306 .probe = toshiba_probe,
307 .driver = {
308 .name = "lcdc_toshiba_wvga",
309 },
310};
311
312static struct msm_fb_panel_data toshiba_panel_data = {
313 .on = lcdc_toshiba_panel_on,
314 .off = lcdc_toshiba_panel_off,
315 .set_backlight = lcdc_toshiba_set_backlight,
316};
317
318static struct platform_device this_device = {
319 .name = "lcdc_toshiba_wvga",
320 .id = 1,
321 .dev = {
322 .platform_data = &toshiba_panel_data,
323 }
324};
325
326static int __init lcdc_toshiba_panel_init(void)
327{
328 int ret;
329 struct msm_panel_info *pinfo;
330#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
331 if (mddi_get_client_id() != 0)
332 return 0;
333
334 ret = msm_fb_detect_client("lcdc_toshiba_wvga_pt");
335 if (ret)
336 return 0;
337
338#endif
339
340 ret = platform_driver_register(&this_driver);
341 if (ret)
342 return ret;
343
344 pinfo = &toshiba_panel_data.panel_info;
345 pinfo->xres = 480;
346 pinfo->yres = 800;
347 pinfo->type = LCDC_PANEL;
348 pinfo->pdest = DISPLAY_1;
349 pinfo->wait_cycle = 0;
350 pinfo->bpp = 18;
351 pinfo->fb_num = 2;
352 /* 30Mhz mdp_lcdc_pclk and mdp_lcdc_pad_pcl */
353 pinfo->clk_rate = 27648000;
354 pinfo->bl_max = 15;
355 pinfo->bl_min = 1;
356
357 pinfo->lcdc.h_back_porch = 184; /* hsw = 8 + hbp=184 */
358 pinfo->lcdc.h_front_porch = 4;
359 pinfo->lcdc.h_pulse_width = 8;
360 pinfo->lcdc.v_back_porch = 2; /* vsw=1 + vbp = 2 */
361 pinfo->lcdc.v_front_porch = 3;
362 pinfo->lcdc.v_pulse_width = 1;
363 pinfo->lcdc.border_clr = 0; /* blk */
364 pinfo->lcdc.underflow_clr = 0xff; /* blue */
365 pinfo->lcdc.hsync_skew = 0;
366
367 ret = platform_device_register(&this_device);
368 if (ret)
369 platform_driver_unregister(&this_driver);
370
371 return ret;
372}
373
374device_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
index 000000000000..202c92c0ef54
--- /dev/null
+++ b/drivers/staging/msm/lcdc_wxga.c
@@ -0,0 +1,56 @@
1/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include "msm_fb.h"
19
20static int __init lcdc_wxga_init(void)
21{
22 int ret;
23 struct msm_panel_info pinfo;
24
25#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
26 if (msm_fb_detect_client("lcdc_wxga"))
27 return 0;
28#endif
29
30 pinfo.xres = 1280;
31 pinfo.yres = 720;
32 pinfo.type = LCDC_PANEL;
33 pinfo.pdest = DISPLAY_1;
34 pinfo.wait_cycle = 0;
35 pinfo.bpp = 24;
36 pinfo.fb_num = 2;
37 pinfo.clk_rate = 74250000;
38
39 pinfo.lcdc.h_back_porch = 124;
40 pinfo.lcdc.h_front_porch = 110;
41 pinfo.lcdc.h_pulse_width = 136;
42 pinfo.lcdc.v_back_porch = 19;
43 pinfo.lcdc.v_front_porch = 5;
44 pinfo.lcdc.v_pulse_width = 6;
45 pinfo.lcdc.border_clr = 0; /* blk */
46 pinfo.lcdc.underflow_clr = 0xff; /* blue */
47 pinfo.lcdc.hsync_skew = 0;
48
49 ret = lcdc_device_register(&pinfo);
50 if (ret)
51 printk(KERN_ERR "%s: failed to register device!\n", __func__);
52
53 return ret;
54}
55
56module_init(lcdc_wxga_init);
diff --git a/drivers/staging/msm/logo.c b/drivers/staging/msm/logo.c
new file mode 100644
index 000000000000..7272765f48cd
--- /dev/null
+++ b/drivers/staging/msm/logo.c
@@ -0,0 +1,98 @@
1/* drivers/video/msm/logo.c
2 *
3 * Show Logo in RLE 565 format
4 *
5 * Copyright (C) 2008 Google Incorporated
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17#include <linux/module.h>
18#include <linux/types.h>
19#include <linux/fb.h>
20#include <linux/vt_kern.h>
21#include <linux/unistd.h>
22#include <linux/syscalls.h>
23
24#include <linux/irq.h>
25#include <asm/system.h>
26
27#define fb_width(fb) ((fb)->var.xres)
28#define fb_height(fb) ((fb)->var.yres)
29#define fb_size(fb) ((fb)->var.xres * (fb)->var.yres * 2)
30
31static void memset16(void *_ptr, unsigned short val, unsigned count)
32{
33 unsigned short *ptr = _ptr;
34 count >>= 1;
35 while (count--)
36 *ptr++ = val;
37}
38
39/* 565RLE image format: [count(2 bytes), rle(2 bytes)] */
40int load_565rle_image(char *filename)
41{
42 struct fb_info *info;
43 int fd, err = 0;
44 unsigned count, max;
45 unsigned short *data, *bits, *ptr;
46
47 info = registered_fb[0];
48 if (!info) {
49 printk(KERN_WARNING "%s: Can not access framebuffer\n",
50 __func__);
51 return -ENODEV;
52 }
53
54 fd = sys_open(filename, O_RDONLY, 0);
55 if (fd < 0) {
56 printk(KERN_WARNING "%s: Can not open %s\n",
57 __func__, filename);
58 return -ENOENT;
59 }
60 count = (unsigned)sys_lseek(fd, (off_t)0, 2);
61 if (count == 0) {
62 sys_close(fd);
63 err = -EIO;
64 goto err_logo_close_file;
65 }
66 sys_lseek(fd, (off_t)0, 0);
67 data = kmalloc(count, GFP_KERNEL);
68 if (!data) {
69 printk(KERN_WARNING "%s: Can not alloc data\n", __func__);
70 err = -ENOMEM;
71 goto err_logo_close_file;
72 }
73 if ((unsigned)sys_read(fd, (char *)data, count) != count) {
74 err = -EIO;
75 goto err_logo_free_data;
76 }
77
78 max = fb_width(info) * fb_height(info);
79 ptr = data;
80 bits = (unsigned short *)(info->screen_base);
81 while (count > 3) {
82 unsigned n = ptr[0];
83 if (n > max)
84 break;
85 memset16(bits, ptr[1], n << 1);
86 bits += n;
87 max -= n;
88 ptr += 2;
89 count -= 4;
90 }
91
92err_logo_free_data:
93 kfree(data);
94err_logo_close_file:
95 sys_close(fd);
96 return err;
97}
98EXPORT_SYMBOL(load_565rle_image);
diff --git a/drivers/staging/msm/mddi.c b/drivers/staging/msm/mddi.c
new file mode 100644
index 000000000000..132eb1adff16
--- /dev/null
+++ b/drivers/staging/msm/mddi.c
@@ -0,0 +1,375 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/sched.h>
21#include <linux/time.h>
22#include <linux/init.h>
23#include <linux/interrupt.h>
24#include <linux/spinlock.h>
25#include <linux/delay.h>
26#include <mach/hardware.h>
27#include <asm/io.h>
28
29#include <asm/system.h>
30#include <asm/mach-types.h>
31#include <linux/semaphore.h>
32#include <linux/uaccess.h>
33#include <linux/clk.h>
34#include <linux/platform_device.h>
35
36#include "msm_fb.h"
37#include "mddihosti.h"
38#include "mddihost.h"
39#include <mach/gpio.h>
40#include <mach/clk.h>
41
42static int mddi_probe(struct platform_device *pdev);
43static int mddi_remove(struct platform_device *pdev);
44
45static int mddi_off(struct platform_device *pdev);
46static int mddi_on(struct platform_device *pdev);
47
48static int mddi_suspend(struct platform_device *pdev, pm_message_t state);
49static int mddi_resume(struct platform_device *pdev);
50
51#ifdef CONFIG_HAS_EARLYSUSPEND
52static void mddi_early_suspend(struct early_suspend *h);
53static void mddi_early_resume(struct early_suspend *h);
54#endif
55
56static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
57static int pdev_list_cnt;
58static struct clk *mddi_clk;
59static struct clk *mddi_pclk;
60static struct mddi_platform_data *mddi_pdata;
61
62static struct platform_driver mddi_driver = {
63 .probe = mddi_probe,
64 .remove = mddi_remove,
65#ifndef CONFIG_HAS_EARLYSUSPEND
66#ifdef CONFIG_PM
67 .suspend = mddi_suspend,
68 .resume = mddi_resume,
69#endif
70#endif
71 .suspend_late = NULL,
72 .resume_early = NULL,
73 .shutdown = NULL,
74 .driver = {
75 .name = "mddi",
76 },
77};
78
79extern int int_mddi_pri_flag;
80
81static int mddi_off(struct platform_device *pdev)
82{
83 int ret = 0;
84
85 ret = panel_next_off(pdev);
86
87 if (mddi_pdata && mddi_pdata->mddi_power_save)
88 mddi_pdata->mddi_power_save(0);
89
90 return ret;
91}
92
93static int mddi_on(struct platform_device *pdev)
94{
95 int ret = 0;
96 u32 clk_rate;
97 struct msm_fb_data_type *mfd;
98
99 mfd = platform_get_drvdata(pdev);
100
101 if (mddi_pdata && mddi_pdata->mddi_power_save)
102 mddi_pdata->mddi_power_save(1);
103
104 clk_rate = mfd->fbi->var.pixclock;
105 clk_rate = min(clk_rate, mfd->panel_info.clk_max);
106
107 if (mddi_pdata &&
108 mddi_pdata->mddi_sel_clk &&
109 mddi_pdata->mddi_sel_clk(&clk_rate))
110 printk(KERN_ERR
111 "%s: can't select mddi io clk targate rate = %d\n",
112 __func__, clk_rate);
113
114 if (clk_set_min_rate(mddi_clk, clk_rate) < 0)
115 printk(KERN_ERR "%s: clk_set_min_rate failed\n",
116 __func__);
117
118 ret = panel_next_on(pdev);
119
120 return ret;
121}
122
123static int mddi_resource_initialized;
124
125static int mddi_probe(struct platform_device *pdev)
126{
127 struct msm_fb_data_type *mfd;
128 struct platform_device *mdp_dev = NULL;
129 struct msm_fb_panel_data *pdata = NULL;
130 int rc;
131 resource_size_t size ;
132 u32 clk_rate;
133
134 if ((pdev->id == 0) && (pdev->num_resources >= 0)) {
135 mddi_pdata = pdev->dev.platform_data;
136
137 size = resource_size(&pdev->resource[0]);
138 msm_pmdh_base = ioremap(pdev->resource[0].start, size);
139
140 MSM_FB_INFO("primary mddi base phy_addr = 0x%x virt = 0x%x\n",
141 pdev->resource[0].start, (int) msm_pmdh_base);
142
143 if (unlikely(!msm_pmdh_base))
144 return -ENOMEM;
145
146 if (mddi_pdata && mddi_pdata->mddi_power_save)
147 mddi_pdata->mddi_power_save(1);
148
149 mddi_resource_initialized = 1;
150 return 0;
151 }
152
153 if (!mddi_resource_initialized)
154 return -EPERM;
155
156 mfd = platform_get_drvdata(pdev);
157
158 if (!mfd)
159 return -ENODEV;
160
161 if (mfd->key != MFD_KEY)
162 return -EINVAL;
163
164 if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
165 return -ENOMEM;
166
167 mdp_dev = platform_device_alloc("mdp", pdev->id);
168 if (!mdp_dev)
169 return -ENOMEM;
170
171 /*
172 * link to the latest pdev
173 */
174 mfd->pdev = mdp_dev;
175 mfd->dest = DISPLAY_LCD;
176
177 /*
178 * alloc panel device data
179 */
180 if (platform_device_add_data
181 (mdp_dev, pdev->dev.platform_data,
182 sizeof(struct msm_fb_panel_data))) {
183 printk(KERN_ERR "mddi_probe: platform_device_add_data failed!\n");
184 platform_device_put(mdp_dev);
185 return -ENOMEM;
186 }
187 /*
188 * data chain
189 */
190 pdata = mdp_dev->dev.platform_data;
191 pdata->on = mddi_on;
192 pdata->off = mddi_off;
193 pdata->next = pdev;
194
195 /*
196 * get/set panel specific fb info
197 */
198 mfd->panel_info = pdata->panel_info;
199 mfd->fb_imgType = MDP_RGB_565;
200
201 clk_rate = mfd->panel_info.clk_max;
202 if (mddi_pdata &&
203 mddi_pdata->mddi_sel_clk &&
204 mddi_pdata->mddi_sel_clk(&clk_rate))
205 printk(KERN_ERR
206 "%s: can't select mddi io clk targate rate = %d\n",
207 __func__, clk_rate);
208
209 if (clk_set_max_rate(mddi_clk, clk_rate) < 0)
210 printk(KERN_ERR "%s: clk_set_max_rate failed\n", __func__);
211 mfd->panel_info.clk_rate = mfd->panel_info.clk_min;
212
213 /*
214 * set driver data
215 */
216 platform_set_drvdata(mdp_dev, mfd);
217
218 /*
219 * register in mdp driver
220 */
221 rc = platform_device_add(mdp_dev);
222 if (rc)
223 goto mddi_probe_err;
224
225 pdev_list[pdev_list_cnt++] = pdev;
226
227#ifdef CONFIG_HAS_EARLYSUSPEND
228 mfd->mddi_early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
229 mfd->mddi_early_suspend.suspend = mddi_early_suspend;
230 mfd->mddi_early_suspend.resume = mddi_early_resume;
231 register_early_suspend(&mfd->mddi_early_suspend);
232#endif
233
234 return 0;
235
236mddi_probe_err:
237 platform_device_put(mdp_dev);
238 return rc;
239}
240
241static int mddi_pad_ctrl;
242static int mddi_power_locked;
243static int mddi_is_in_suspend;
244
245void mddi_disable(int lock)
246{
247 mddi_host_type host_idx = MDDI_HOST_PRIM;
248
249 if (mddi_power_locked)
250 return;
251
252 if (lock)
253 mddi_power_locked = 1;
254
255 if (mddi_host_timer.function)
256 del_timer_sync(&mddi_host_timer);
257
258 mddi_pad_ctrl = mddi_host_reg_in(PAD_CTL);
259 mddi_host_reg_out(PAD_CTL, 0x0);
260
261 if (clk_set_min_rate(mddi_clk, 0) < 0)
262 printk(KERN_ERR "%s: clk_set_min_rate failed\n", __func__);
263
264 clk_disable(mddi_clk);
265 if (mddi_pclk)
266 clk_disable(mddi_pclk);
267 disable_irq(INT_MDDI_PRI);
268
269 if (mddi_pdata && mddi_pdata->mddi_power_save)
270 mddi_pdata->mddi_power_save(0);
271}
272
273static int mddi_suspend(struct platform_device *pdev, pm_message_t state)
274{
275 if (mddi_is_in_suspend)
276 return 0;
277
278 mddi_is_in_suspend = 1;
279 mddi_disable(0);
280 return 0;
281}
282
283static int mddi_resume(struct platform_device *pdev)
284{
285 mddi_host_type host_idx = MDDI_HOST_PRIM;
286
287 if (!mddi_is_in_suspend)
288 return 0;
289
290 mddi_is_in_suspend = 0;
291
292 if (mddi_power_locked)
293 return 0;
294
295 enable_irq(INT_MDDI_PRI);
296 clk_enable(mddi_clk);
297 if (mddi_pclk)
298 clk_enable(mddi_pclk);
299 mddi_host_reg_out(PAD_CTL, mddi_pad_ctrl);
300
301 if (mddi_host_timer.function)
302 mddi_host_timer_service(0);
303
304 return 0;
305}
306
307#ifdef CONFIG_HAS_EARLYSUSPEND
308static void mddi_early_suspend(struct early_suspend *h)
309{
310 pm_message_t state;
311 struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
312 mddi_early_suspend);
313
314 state.event = PM_EVENT_SUSPEND;
315 mddi_suspend(mfd->pdev, state);
316}
317
318static void mddi_early_resume(struct early_suspend *h)
319{
320 struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
321 mddi_early_suspend);
322 mddi_resume(mfd->pdev);
323}
324#endif
325
326static int mddi_remove(struct platform_device *pdev)
327{
328 if (mddi_host_timer.function)
329 del_timer_sync(&mddi_host_timer);
330
331 iounmap(msm_pmdh_base);
332
333 return 0;
334}
335
336static int mddi_register_driver(void)
337{
338 return platform_driver_register(&mddi_driver);
339}
340
341static int __init mddi_driver_init(void)
342{
343 int ret;
344
345 mddi_clk = clk_get(NULL, "mddi_clk");
346 if (IS_ERR(mddi_clk)) {
347 printk(KERN_ERR "can't find mddi_clk \n");
348 return PTR_ERR(mddi_clk);
349 }
350 clk_enable(mddi_clk);
351
352 mddi_pclk = clk_get(NULL, "mddi_pclk");
353 if (IS_ERR(mddi_pclk))
354 mddi_pclk = NULL;
355 else
356 clk_enable(mddi_pclk);
357
358 ret = mddi_register_driver();
359 if (ret) {
360 clk_disable(mddi_clk);
361 clk_put(mddi_clk);
362 if (mddi_pclk) {
363 clk_disable(mddi_pclk);
364 clk_put(mddi_pclk);
365 }
366 printk(KERN_ERR "mddi_register_driver() failed!\n");
367 return ret;
368 }
369
370 mddi_init();
371
372 return ret;
373}
374
375module_init(mddi_driver_init);
diff --git a/drivers/staging/msm/mddi_ext.c b/drivers/staging/msm/mddi_ext.c
new file mode 100644
index 000000000000..c0c168c7199d
--- /dev/null
+++ b/drivers/staging/msm/mddi_ext.c
@@ -0,0 +1,320 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/sched.h>
21#include <linux/time.h>
22#include <linux/init.h>
23#include <linux/interrupt.h>
24#include <linux/spinlock.h>
25#include <linux/delay.h>
26#include <mach/hardware.h>
27#include <asm/io.h>
28
29#include <asm/system.h>
30#include <asm/mach-types.h>
31#include <linux/semaphore.h>
32#include <linux/uaccess.h>
33#include <linux/clk.h>
34#include <mach/clk.h>
35#include <linux/platform_device.h>
36
37#include "msm_fb.h"
38#include "mddihosti.h"
39
40static int mddi_ext_probe(struct platform_device *pdev);
41static int mddi_ext_remove(struct platform_device *pdev);
42
43static int mddi_ext_off(struct platform_device *pdev);
44static int mddi_ext_on(struct platform_device *pdev);
45
46static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
47static int pdev_list_cnt;
48
49static int mddi_ext_suspend(struct platform_device *pdev, pm_message_t state);
50static int mddi_ext_resume(struct platform_device *pdev);
51
52#ifdef CONFIG_HAS_EARLYSUSPEND
53static void mddi_ext_early_suspend(struct early_suspend *h);
54static void mddi_ext_early_resume(struct early_suspend *h);
55#endif
56
57static struct platform_driver mddi_ext_driver = {
58 .probe = mddi_ext_probe,
59 .remove = mddi_ext_remove,
60#ifndef CONFIG_HAS_EARLYSUSPEND
61#ifdef CONFIG_PM
62 .suspend = mddi_ext_suspend,
63 .resume = mddi_ext_resume,
64#endif
65#endif
66 .resume_early = NULL,
67 .resume = NULL,
68 .shutdown = NULL,
69 .driver = {
70 .name = "mddi_ext",
71 },
72};
73
74static struct clk *mddi_ext_clk;
75static struct mddi_platform_data *mddi_ext_pdata;
76
77extern int int_mddi_ext_flag;
78
79static int mddi_ext_off(struct platform_device *pdev)
80{
81 int ret = 0;
82
83 ret = panel_next_off(pdev);
84 mddi_host_stop_ext_display();
85
86 return ret;
87}
88
89static int mddi_ext_on(struct platform_device *pdev)
90{
91 int ret = 0;
92 u32 clk_rate;
93 struct msm_fb_data_type *mfd;
94
95 mfd = platform_get_drvdata(pdev);
96
97 clk_rate = mfd->fbi->var.pixclock;
98 clk_rate = min(clk_rate, mfd->panel_info.clk_max);
99
100 if (mddi_ext_pdata &&
101 mddi_ext_pdata->mddi_sel_clk &&
102 mddi_ext_pdata->mddi_sel_clk(&clk_rate))
103 printk(KERN_ERR
104 "%s: can't select mddi io clk targate rate = %d\n",
105 __func__, clk_rate);
106
107 if (clk_set_min_rate(mddi_ext_clk, clk_rate) < 0)
108 printk(KERN_ERR "%s: clk_set_min_rate failed\n",
109 __func__);
110
111 mddi_host_start_ext_display();
112 ret = panel_next_on(pdev);
113
114 return ret;
115}
116
117static int mddi_ext_resource_initialized;
118
119static int mddi_ext_probe(struct platform_device *pdev)
120{
121 struct msm_fb_data_type *mfd;
122 struct platform_device *mdp_dev = NULL;
123 struct msm_fb_panel_data *pdata = NULL;
124 int rc;
125 resource_size_t size ;
126 u32 clk_rate;
127
128 if ((pdev->id == 0) && (pdev->num_resources >= 0)) {
129 mddi_ext_pdata = pdev->dev.platform_data;
130
131 size = resource_size(&pdev->resource[0]);
132 msm_emdh_base = ioremap(pdev->resource[0].start, size);
133
134 MSM_FB_INFO("external mddi base address = 0x%x\n",
135 pdev->resource[0].start);
136
137 if (unlikely(!msm_emdh_base))
138 return -ENOMEM;
139
140 mddi_ext_resource_initialized = 1;
141 return 0;
142 }
143
144 if (!mddi_ext_resource_initialized)
145 return -EPERM;
146
147 mfd = platform_get_drvdata(pdev);
148
149 if (!mfd)
150 return -ENODEV;
151
152 if (mfd->key != MFD_KEY)
153 return -EINVAL;
154
155 if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
156 return -ENOMEM;
157
158 mdp_dev = platform_device_alloc("mdp", pdev->id);
159 if (!mdp_dev)
160 return -ENOMEM;
161
162 /*
163 * link to the latest pdev
164 */
165 mfd->pdev = mdp_dev;
166 mfd->dest = DISPLAY_EXT_MDDI;
167
168 /*
169 * alloc panel device data
170 */
171 if (platform_device_add_data
172 (mdp_dev, pdev->dev.platform_data,
173 sizeof(struct msm_fb_panel_data))) {
174 printk(KERN_ERR "mddi_ext_probe: platform_device_add_data failed!\n");
175 platform_device_put(mdp_dev);
176 return -ENOMEM;
177 }
178 /*
179 * data chain
180 */
181 pdata = mdp_dev->dev.platform_data;
182 pdata->on = mddi_ext_on;
183 pdata->off = mddi_ext_off;
184 pdata->next = pdev;
185
186 /*
187 * get/set panel specific fb info
188 */
189 mfd->panel_info = pdata->panel_info;
190 mfd->fb_imgType = MDP_RGB_565;
191
192 clk_rate = mfd->panel_info.clk_max;
193 if (mddi_ext_pdata &&
194 mddi_ext_pdata->mddi_sel_clk &&
195 mddi_ext_pdata->mddi_sel_clk(&clk_rate))
196 printk(KERN_ERR
197 "%s: can't select mddi io clk targate rate = %d\n",
198 __func__, clk_rate);
199
200 if (clk_set_max_rate(mddi_ext_clk, clk_rate) < 0)
201 printk(KERN_ERR "%s: clk_set_max_rate failed\n", __func__);
202 mfd->panel_info.clk_rate = mfd->panel_info.clk_min;
203
204 /*
205 * set driver data
206 */
207 platform_set_drvdata(mdp_dev, mfd);
208
209 /*
210 * register in mdp driver
211 */
212 rc = platform_device_add(mdp_dev);
213 if (rc)
214 goto mddi_ext_probe_err;
215
216 pdev_list[pdev_list_cnt++] = pdev;
217
218#ifdef CONFIG_HAS_EARLYSUSPEND
219 mfd->mddi_ext_early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
220 mfd->mddi_ext_early_suspend.suspend = mddi_ext_early_suspend;
221 mfd->mddi_ext_early_suspend.resume = mddi_ext_early_resume;
222 register_early_suspend(&mfd->mddi_ext_early_suspend);
223#endif
224
225 return 0;
226
227mddi_ext_probe_err:
228 platform_device_put(mdp_dev);
229 return rc;
230}
231
232static int mddi_ext_is_in_suspend;
233
234static int mddi_ext_suspend(struct platform_device *pdev, pm_message_t state)
235{
236 if (mddi_ext_is_in_suspend)
237 return 0;
238
239 mddi_ext_is_in_suspend = 1;
240
241 if (clk_set_min_rate(mddi_ext_clk, 0) < 0)
242 printk(KERN_ERR "%s: clk_set_min_rate failed\n", __func__);
243
244 clk_disable(mddi_ext_clk);
245 disable_irq(INT_MDDI_EXT);
246
247 return 0;
248}
249
250static int mddi_ext_resume(struct platform_device *pdev)
251{
252 struct msm_fb_data_type *mfd;
253
254 mfd = platform_get_drvdata(pdev);
255
256 if (!mddi_ext_is_in_suspend)
257 return 0;
258
259 mddi_ext_is_in_suspend = 0;
260 enable_irq(INT_MDDI_EXT);
261
262 clk_enable(mddi_ext_clk);
263
264 return 0;
265}
266
267#ifdef CONFIG_HAS_EARLYSUSPEND
268static void mddi_ext_early_suspend(struct early_suspend *h)
269{
270 pm_message_t state;
271 struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
272 mddi_ext_early_suspend);
273
274 state.event = PM_EVENT_SUSPEND;
275 mddi_ext_suspend(mfd->pdev, state);
276}
277
278static void mddi_ext_early_resume(struct early_suspend *h)
279{
280 struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
281 mddi_ext_early_suspend);
282 mddi_ext_resume(mfd->pdev);
283}
284#endif
285
286static int mddi_ext_remove(struct platform_device *pdev)
287{
288 iounmap(msm_emdh_base);
289 return 0;
290}
291
292static int mddi_ext_register_driver(void)
293{
294 return platform_driver_register(&mddi_ext_driver);
295}
296
297static int __init mddi_ext_driver_init(void)
298{
299 int ret;
300
301 mddi_ext_clk = clk_get(NULL, "emdh_clk");
302 if (IS_ERR(mddi_ext_clk)) {
303 printk(KERN_ERR "can't find emdh_clk\n");
304 return PTR_ERR(mddi_ext_clk);
305 }
306 clk_enable(mddi_ext_clk);
307
308 ret = mddi_ext_register_driver();
309 if (ret) {
310 clk_disable(mddi_ext_clk);
311 clk_put(mddi_ext_clk);
312 printk(KERN_ERR "mddi_ext_register_driver() failed!\n");
313 return ret;
314 }
315 mddi_init();
316
317 return ret;
318}
319
320module_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
index 000000000000..502e80d17ec7
--- /dev/null
+++ b/drivers/staging/msm/mddi_ext_lcd.c
@@ -0,0 +1,91 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include "msm_fb.h"
19#include "mddihost.h"
20#include "mddihosti.h"
21
22static int mddi_ext_lcd_on(struct platform_device *pdev);
23static int mddi_ext_lcd_off(struct platform_device *pdev);
24
25static int mddi_ext_lcd_on(struct platform_device *pdev)
26{
27 return 0;
28}
29
30static int mddi_ext_lcd_off(struct platform_device *pdev)
31{
32 return 0;
33}
34
35static int __init mddi_ext_lcd_probe(struct platform_device *pdev)
36{
37 msm_fb_add_device(pdev);
38
39 return 0;
40}
41
42static struct platform_driver this_driver = {
43 .probe = mddi_ext_lcd_probe,
44 .driver = {
45 .name = "extmddi_svga",
46 },
47};
48
49static struct msm_fb_panel_data mddi_ext_lcd_panel_data = {
50 .panel_info.xres = 800,
51 .panel_info.yres = 600,
52 .panel_info.type = EXT_MDDI_PANEL,
53 .panel_info.pdest = DISPLAY_1,
54 .panel_info.wait_cycle = 0,
55 .panel_info.bpp = 18,
56 .panel_info.fb_num = 2,
57 .panel_info.clk_rate = 122880000,
58 .panel_info.clk_min = 120000000,
59 .panel_info.clk_max = 125000000,
60 .on = mddi_ext_lcd_on,
61 .off = mddi_ext_lcd_off,
62};
63
64static struct platform_device this_device = {
65 .name = "extmddi_svga",
66 .id = 0,
67 .dev = {
68 .platform_data = &mddi_ext_lcd_panel_data,
69 }
70};
71
72static int __init mddi_ext_lcd_init(void)
73{
74 int ret;
75 struct msm_panel_info *pinfo;
76
77 ret = platform_driver_register(&this_driver);
78 if (!ret) {
79 pinfo = &mddi_ext_lcd_panel_data.panel_info;
80 pinfo->lcd.vsync_enable = FALSE;
81 pinfo->mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
82
83 ret = platform_device_register(&this_device);
84 if (ret)
85 platform_driver_unregister(&this_driver);
86 }
87
88 return ret;
89}
90
91module_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
index 000000000000..489d40405a5f
--- /dev/null
+++ b/drivers/staging/msm/mddi_prism.c
@@ -0,0 +1,114 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include "msm_fb.h"
19#include "mddihost.h"
20#include "mddihosti.h"
21
22static int prism_lcd_on(struct platform_device *pdev);
23static int prism_lcd_off(struct platform_device *pdev);
24
25static int prism_lcd_on(struct platform_device *pdev)
26{
27 /* Set the MDP pixel data attributes for Primary Display */
28 mddi_host_write_pix_attr_reg(0x00C3);
29
30 return 0;
31}
32
33static int prism_lcd_off(struct platform_device *pdev)
34{
35 return 0;
36}
37
38static int __init prism_probe(struct platform_device *pdev)
39{
40 msm_fb_add_device(pdev);
41
42 return 0;
43}
44
45static struct platform_driver this_driver = {
46 .probe = prism_probe,
47 .driver = {
48 .name = "mddi_prism_wvga",
49 },
50};
51
52static struct msm_fb_panel_data prism_panel_data = {
53 .on = prism_lcd_on,
54 .off = prism_lcd_off,
55};
56
57static struct platform_device this_device = {
58 .name = "mddi_prism_wvga",
59 .id = 0,
60 .dev = {
61 .platform_data = &prism_panel_data,
62 }
63};
64
65static int __init prism_init(void)
66{
67 int ret;
68 struct msm_panel_info *pinfo;
69
70#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
71 u32 id;
72
73 ret = msm_fb_detect_client("mddi_prism_wvga");
74 if (ret == -ENODEV)
75 return 0;
76
77 if (ret) {
78 id = mddi_get_client_id();
79
80 if (((id >> 16) != 0x4474) || ((id & 0xffff) == 0x8960))
81 return 0;
82 }
83#endif
84 ret = platform_driver_register(&this_driver);
85 if (!ret) {
86 pinfo = &prism_panel_data.panel_info;
87 pinfo->xres = 800;
88 pinfo->yres = 480;
89 pinfo->type = MDDI_PANEL;
90 pinfo->pdest = DISPLAY_1;
91 pinfo->mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
92 pinfo->wait_cycle = 0;
93 pinfo->bpp = 18;
94 pinfo->fb_num = 2;
95 pinfo->clk_rate = 153600000;
96 pinfo->clk_min = 150000000;
97 pinfo->clk_max = 160000000;
98 pinfo->lcd.vsync_enable = TRUE;
99 pinfo->lcd.refx100 = 6050;
100 pinfo->lcd.v_back_porch = 23;
101 pinfo->lcd.v_front_porch = 20;
102 pinfo->lcd.v_pulse_width = 105;
103 pinfo->lcd.hw_vsync_mode = TRUE;
104 pinfo->lcd.vsync_notifier_period = 0;
105
106 ret = platform_device_register(&this_device);
107 if (ret)
108 platform_driver_unregister(&this_driver);
109 }
110
111 return ret;
112}
113
114module_init(prism_init);
diff --git a/drivers/staging/msm/mddi_sharp.c b/drivers/staging/msm/mddi_sharp.c
new file mode 100644
index 000000000000..1da1be4052d0
--- /dev/null
+++ b/drivers/staging/msm/mddi_sharp.c
@@ -0,0 +1,892 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include "msm_fb.h"
19#include "mddihost.h"
20#include "mddihosti.h"
21
22#define SHARP_QVGA_PRIM 1
23#define SHARP_128X128_SECD 2
24
25extern uint32 mddi_host_core_version;
26static boolean mddi_debug_prim_wait = FALSE;
27static boolean mddi_sharp_vsync_wake = TRUE;
28static boolean mddi_sharp_monitor_refresh_value = TRUE;
29static boolean mddi_sharp_report_refresh_measurements = FALSE;
30static uint32 mddi_sharp_rows_per_second = 13830; /* 5200000/376 */
31static uint32 mddi_sharp_rows_per_refresh = 338;
32static uint32 mddi_sharp_usecs_per_refresh = 24440; /* (376+338)/5200000 */
33static boolean mddi_sharp_debug_60hz_refresh = FALSE;
34
35extern mddi_gpio_info_type mddi_gpio;
36extern boolean mddi_vsync_detect_enabled;
37static msm_fb_vsync_handler_type mddi_sharp_vsync_handler;
38static void *mddi_sharp_vsync_handler_arg;
39static uint16 mddi_sharp_vsync_attempts;
40
41static void mddi_sharp_prim_lcd_init(void);
42static void mddi_sharp_sub_lcd_init(void);
43static void mddi_sharp_lcd_set_backlight(struct msm_fb_data_type *mfd);
44static void mddi_sharp_vsync_set_handler(msm_fb_vsync_handler_type handler,
45 void *);
46static void mddi_sharp_lcd_vsync_detected(boolean detected);
47static struct msm_panel_common_pdata *mddi_sharp_pdata;
48
49#define REG_SYSCTL 0x0000
50#define REG_INTR 0x0006
51#define REG_CLKCNF 0x000C
52#define REG_CLKDIV1 0x000E
53#define REG_CLKDIV2 0x0010
54
55#define REG_GIOD 0x0040
56#define REG_GIOA 0x0042
57
58#define REG_AGM 0x010A
59#define REG_FLFT 0x0110
60#define REG_FRGT 0x0112
61#define REG_FTOP 0x0114
62#define REG_FBTM 0x0116
63#define REG_FSTRX 0x0118
64#define REG_FSTRY 0x011A
65#define REG_VRAM 0x0202
66#define REG_SSDCTL 0x0330
67#define REG_SSD0 0x0332
68#define REG_PSTCTL1 0x0400
69#define REG_PSTCTL2 0x0402
70#define REG_PTGCTL 0x042A
71#define REG_PTHP 0x042C
72#define REG_PTHB 0x042E
73#define REG_PTHW 0x0430
74#define REG_PTHF 0x0432
75#define REG_PTVP 0x0434
76#define REG_PTVB 0x0436
77#define REG_PTVW 0x0438
78#define REG_PTVF 0x043A
79#define REG_VBLKS 0x0458
80#define REG_VBLKE 0x045A
81#define REG_SUBCTL 0x0700
82#define REG_SUBTCMD 0x0702
83#define REG_SUBTCMDD 0x0704
84#define REG_REVBYTE 0x0A02
85#define REG_REVCNT 0x0A04
86#define REG_REVATTR 0x0A06
87#define REG_REVFMT 0x0A08
88
89#define SHARP_SUB_UNKNOWN 0xffffffff
90#define SHARP_SUB_HYNIX 1
91#define SHARP_SUB_ROHM 2
92
93static uint32 sharp_subpanel_type = SHARP_SUB_UNKNOWN;
94
95static void sub_through_write(int sub_rs, uint32 sub_data)
96{
97 mddi_queue_register_write(REG_SUBTCMDD, sub_data, FALSE, 0);
98
99 /* CS=1,RD=1,WE=1,RS=sub_rs */
100 mddi_queue_register_write(REG_SUBTCMD, 0x000e | sub_rs, FALSE, 0);
101
102 /* CS=0,RD=1,WE=1,RS=sub_rs */
103 mddi_queue_register_write(REG_SUBTCMD, 0x0006 | sub_rs, FALSE, 0);
104
105 /* CS=0,RD=1,WE=0,RS=sub_rs */
106 mddi_queue_register_write(REG_SUBTCMD, 0x0004 | sub_rs, FALSE, 0);
107
108 /* CS=0,RD=1,WE=1,RS=sub_rs */
109 mddi_queue_register_write(REG_SUBTCMD, 0x0006 | sub_rs, FALSE, 0);
110
111 /* CS=1,RD=1,WE=1,RS=sub_rs */
112 mddi_queue_register_write(REG_SUBTCMD, 0x000e | sub_rs, TRUE, 0);
113}
114
115static uint32 sub_through_read(int sub_rs)
116{
117 uint32 sub_data;
118
119 /* CS=1,RD=1,WE=1,RS=sub_rs */
120 mddi_queue_register_write(REG_SUBTCMD, 0x000e | sub_rs, FALSE, 0);
121
122 /* CS=0,RD=1,WE=1,RS=sub_rs */
123 mddi_queue_register_write(REG_SUBTCMD, 0x0006 | sub_rs, FALSE, 0);
124
125 /* CS=0,RD=1,WE=0,RS=sub_rs */
126 mddi_queue_register_write(REG_SUBTCMD, 0x0002 | sub_rs, TRUE, 0);
127
128 mddi_queue_register_read(REG_SUBTCMDD, &sub_data, TRUE, 0);
129
130 /* CS=0,RD=1,WE=1,RS=sub_rs */
131 mddi_queue_register_write(REG_SUBTCMD, 0x0006 | sub_rs, FALSE, 0);
132
133 /* CS=1,RD=1,WE=1,RS=sub_rs */
134 mddi_queue_register_write(REG_SUBTCMD, 0x000e | sub_rs, TRUE, 0);
135
136 return sub_data;
137}
138
139static void serigo(uint32 ssd)
140{
141 uint32 ssdctl;
142
143 mddi_queue_register_read(REG_SSDCTL, &ssdctl, TRUE, 0);
144 ssdctl = ((ssdctl & 0xE7) | 0x02);
145
146 mddi_queue_register_write(REG_SSD0, ssd, FALSE, 0);
147 mddi_queue_register_write(REG_SSDCTL, ssdctl, TRUE, 0);
148
149 do {
150 mddi_queue_register_read(REG_SSDCTL, &ssdctl, TRUE, 0);
151 } while ((ssdctl & 0x0002) != 0);
152
153 if (mddi_debug_prim_wait)
154 mddi_wait(2);
155}
156
157static void mddi_sharp_lcd_powerdown(void)
158{
159 serigo(0x0131);
160 serigo(0x0300);
161 mddi_wait(40);
162 serigo(0x0135);
163 mddi_wait(20);
164 serigo(0x2122);
165 mddi_wait(20);
166 serigo(0x0201);
167 mddi_wait(20);
168 serigo(0x2100);
169 mddi_wait(20);
170 serigo(0x2000);
171 mddi_wait(20);
172
173 mddi_queue_register_write(REG_PSTCTL1, 0x1, TRUE, 0);
174 mddi_wait(100);
175 mddi_queue_register_write(REG_PSTCTL1, 0x0, TRUE, 0);
176 mddi_wait(2);
177 mddi_queue_register_write(REG_SYSCTL, 0x1, TRUE, 0);
178 mddi_wait(2);
179 mddi_queue_register_write(REG_CLKDIV1, 0x3, TRUE, 0);
180 mddi_wait(2);
181 mddi_queue_register_write(REG_SSDCTL, 0x0000, TRUE, 0); /* SSDRESET */
182 mddi_queue_register_write(REG_SYSCTL, 0x0, TRUE, 0);
183 mddi_wait(2);
184}
185
186static void mddi_sharp_lcd_set_backlight(struct msm_fb_data_type *mfd)
187{
188 uint32 regdata;
189 int32 level;
190 int max = mfd->panel_info.bl_max;
191 int min = mfd->panel_info.bl_min;
192
193 if (mddi_sharp_pdata && mddi_sharp_pdata->backlight_level) {
194 level = mddi_sharp_pdata->backlight_level(mfd->bl_level,
195 max,
196 min);
197
198 if (level < 0)
199 return;
200
201 /* use Rodem GPIO(2:0) to give 8 levels of backlight (7-0) */
202 /* Set lower 3 GPIOs as Outputs (set to 0) */
203 mddi_queue_register_read(REG_GIOA, &regdata, TRUE, 0);
204 mddi_queue_register_write(REG_GIOA, regdata & 0xfff8, TRUE, 0);
205
206 /* Set lower 3 GPIOs as level */
207 mddi_queue_register_read(REG_GIOD, &regdata, TRUE, 0);
208 mddi_queue_register_write(REG_GIOD,
209 (regdata & 0xfff8) | (0x07 & level), TRUE, 0);
210 }
211}
212
213static void mddi_sharp_prim_lcd_init(void)
214{
215 mddi_queue_register_write(REG_SYSCTL, 0x4000, TRUE, 0);
216 mddi_wait(1);
217 mddi_queue_register_write(REG_SYSCTL, 0x0000, TRUE, 0);
218 mddi_wait(5);
219 mddi_queue_register_write(REG_SYSCTL, 0x0001, FALSE, 0);
220 mddi_queue_register_write(REG_CLKDIV1, 0x000b, FALSE, 0);
221
222 /* new reg write below */
223 if (mddi_sharp_debug_60hz_refresh)
224 mddi_queue_register_write(REG_CLKCNF, 0x070d, FALSE, 0);
225 else
226 mddi_queue_register_write(REG_CLKCNF, 0x0708, FALSE, 0);
227
228 mddi_queue_register_write(REG_SYSCTL, 0x0201, FALSE, 0);
229 mddi_queue_register_write(REG_PTGCTL, 0x0010, FALSE, 0);
230 mddi_queue_register_write(REG_PTHP, 4, FALSE, 0);
231 mddi_queue_register_write(REG_PTHB, 40, FALSE, 0);
232 mddi_queue_register_write(REG_PTHW, 240, FALSE, 0);
233 if (mddi_sharp_debug_60hz_refresh)
234 mddi_queue_register_write(REG_PTHF, 12, FALSE, 0);
235 else
236 mddi_queue_register_write(REG_PTHF, 92, FALSE, 0);
237
238 mddi_wait(1);
239
240 mddi_queue_register_write(REG_PTVP, 1, FALSE, 0);
241 mddi_queue_register_write(REG_PTVB, 2, FALSE, 0);
242 mddi_queue_register_write(REG_PTVW, 320, FALSE, 0);
243 mddi_queue_register_write(REG_PTVF, 15, FALSE, 0);
244
245 mddi_wait(1);
246
247 /* vram_color set REG_AGM???? */
248 mddi_queue_register_write(REG_AGM, 0x0000, TRUE, 0);
249
250 mddi_queue_register_write(REG_SSDCTL, 0x0000, FALSE, 0);
251 mddi_queue_register_write(REG_SSDCTL, 0x0001, TRUE, 0);
252 mddi_wait(1);
253 mddi_queue_register_write(REG_PSTCTL1, 0x0001, TRUE, 0);
254 mddi_wait(10);
255
256 serigo(0x0701);
257 /* software reset */
258 mddi_wait(1);
259 /* Wait over 50us */
260
261 serigo(0x0400);
262 /* DCLK~ACHSYNC~ACVSYNC polarity setting */
263 serigo(0x2900);
264 /* EEPROM start read address setting */
265 serigo(0x2606);
266 /* EEPROM start read register setting */
267 mddi_wait(20);
268 /* Wait over 20ms */
269
270 serigo(0x0503);
271 /* Horizontal timing setting */
272 serigo(0x062C);
273 /* Veritical timing setting */
274 serigo(0x2001);
275 /* power initialize setting(VDC2) */
276 mddi_wait(20);
277 /* Wait over 20ms */
278
279 serigo(0x2120);
280 /* Initialize power setting(CPS) */
281 mddi_wait(20);
282 /* Wait over 20ms */
283
284 serigo(0x2130);
285 /* Initialize power setting(CPS) */
286 mddi_wait(20);
287 /* Wait over 20ms */
288
289 serigo(0x2132);
290 /* Initialize power setting(CPS) */
291 mddi_wait(10);
292 /* Wait over 10ms */
293
294 serigo(0x2133);
295 /* Initialize power setting(CPS) */
296 mddi_wait(20);
297 /* Wait over 20ms */
298
299 serigo(0x0200);
300 /* Panel initialize release(INIT) */
301 mddi_wait(1);
302 /* Wait over 1ms */
303
304 serigo(0x0131);
305 /* Panel setting(CPS) */
306 mddi_wait(1);
307 /* Wait over 1ms */
308
309 mddi_queue_register_write(REG_PSTCTL1, 0x0003, TRUE, 0);
310
311 /* if (FFA LCD is upside down) -> serigo(0x0100); */
312 serigo(0x0130);
313
314 /* Black mask release(display ON) */
315 mddi_wait(1);
316 /* Wait over 1ms */
317
318 if (mddi_sharp_vsync_wake) {
319 mddi_queue_register_write(REG_VBLKS, 0x1001, TRUE, 0);
320 mddi_queue_register_write(REG_VBLKE, 0x1002, TRUE, 0);
321 }
322
323 /* Set the MDP pixel data attributes for Primary Display */
324 mddi_host_write_pix_attr_reg(0x00C3);
325 return;
326
327}
328
329void mddi_sharp_sub_lcd_init(void)
330{
331
332 mddi_queue_register_write(REG_SYSCTL, 0x4000, FALSE, 0);
333 mddi_queue_register_write(REG_SYSCTL, 0x0000, TRUE, 0);
334 mddi_wait(100);
335
336 mddi_queue_register_write(REG_SYSCTL, 0x0001, FALSE, 0);
337 mddi_queue_register_write(REG_CLKDIV1, 0x000b, FALSE, 0);
338 mddi_queue_register_write(REG_CLKCNF, 0x0708, FALSE, 0);
339 mddi_queue_register_write(REG_SYSCTL, 0x0201, FALSE, 0);
340 mddi_queue_register_write(REG_PTGCTL, 0x0010, FALSE, 0);
341 mddi_queue_register_write(REG_PTHP, 4, FALSE, 0);
342 mddi_queue_register_write(REG_PTHB, 40, FALSE, 0);
343 mddi_queue_register_write(REG_PTHW, 128, FALSE, 0);
344 mddi_queue_register_write(REG_PTHF, 92, FALSE, 0);
345 mddi_queue_register_write(REG_PTVP, 1, FALSE, 0);
346 mddi_queue_register_write(REG_PTVB, 2, FALSE, 0);
347 mddi_queue_register_write(REG_PTVW, 128, FALSE, 0);
348 mddi_queue_register_write(REG_PTVF, 15, FALSE, 0);
349
350 /* Now the sub display..... */
351 /* Reset High */
352 mddi_queue_register_write(REG_SUBCTL, 0x0200, FALSE, 0);
353 /* CS=1,RD=1,WE=1,RS=1 */
354 mddi_queue_register_write(REG_SUBTCMD, 0x000f, TRUE, 0);
355 mddi_wait(1);
356 /* Wait 5us */
357
358 if (sharp_subpanel_type == SHARP_SUB_UNKNOWN) {
359 uint32 data;
360
361 sub_through_write(1, 0x05);
362 sub_through_write(1, 0x6A);
363 sub_through_write(1, 0x1D);
364 sub_through_write(1, 0x05);
365 data = sub_through_read(1);
366 if (data == 0x6A) {
367 sharp_subpanel_type = SHARP_SUB_HYNIX;
368 } else {
369 sub_through_write(0, 0x36);
370 sub_through_write(1, 0xA8);
371 sub_through_write(0, 0x09);
372 data = sub_through_read(1);
373 data = sub_through_read(1);
374 if (data == 0x54) {
375 sub_through_write(0, 0x36);
376 sub_through_write(1, 0x00);
377 sharp_subpanel_type = SHARP_SUB_ROHM;
378 }
379 }
380 }
381
382 if (sharp_subpanel_type == SHARP_SUB_HYNIX) {
383 sub_through_write(1, 0x00); /* Display setting 1 */
384 sub_through_write(1, 0x04);
385 sub_through_write(1, 0x01);
386 sub_through_write(1, 0x05);
387 sub_through_write(1, 0x0280);
388 sub_through_write(1, 0x0301);
389 sub_through_write(1, 0x0402);
390 sub_through_write(1, 0x0500);
391 sub_through_write(1, 0x0681);
392 sub_through_write(1, 0x077F);
393 sub_through_write(1, 0x08C0);
394 sub_through_write(1, 0x0905);
395 sub_through_write(1, 0x0A02);
396 sub_through_write(1, 0x0B00);
397 sub_through_write(1, 0x0C00);
398 sub_through_write(1, 0x0D00);
399 sub_through_write(1, 0x0E00);
400 sub_through_write(1, 0x0F00);
401
402 sub_through_write(1, 0x100B); /* Display setting 2 */
403 sub_through_write(1, 0x1103);
404 sub_through_write(1, 0x1237);
405 sub_through_write(1, 0x1300);
406 sub_through_write(1, 0x1400);
407 sub_through_write(1, 0x1500);
408 sub_through_write(1, 0x1605);
409 sub_through_write(1, 0x1700);
410 sub_through_write(1, 0x1800);
411 sub_through_write(1, 0x192E);
412 sub_through_write(1, 0x1A00);
413 sub_through_write(1, 0x1B00);
414 sub_through_write(1, 0x1C00);
415
416 sub_through_write(1, 0x151A); /* Power setting */
417
418 sub_through_write(1, 0x2002); /* Gradation Palette setting */
419 sub_through_write(1, 0x2107);
420 sub_through_write(1, 0x220C);
421 sub_through_write(1, 0x2310);
422 sub_through_write(1, 0x2414);
423 sub_through_write(1, 0x2518);
424 sub_through_write(1, 0x261C);
425 sub_through_write(1, 0x2720);
426 sub_through_write(1, 0x2824);
427 sub_through_write(1, 0x2928);
428 sub_through_write(1, 0x2A2B);
429 sub_through_write(1, 0x2B2E);
430 sub_through_write(1, 0x2C31);
431 sub_through_write(1, 0x2D34);
432 sub_through_write(1, 0x2E37);
433 sub_through_write(1, 0x2F3A);
434 sub_through_write(1, 0x303C);
435 sub_through_write(1, 0x313E);
436 sub_through_write(1, 0x323F);
437 sub_through_write(1, 0x3340);
438 sub_through_write(1, 0x3441);
439 sub_through_write(1, 0x3543);
440 sub_through_write(1, 0x3646);
441 sub_through_write(1, 0x3749);
442 sub_through_write(1, 0x384C);
443 sub_through_write(1, 0x394F);
444 sub_through_write(1, 0x3A52);
445 sub_through_write(1, 0x3B59);
446 sub_through_write(1, 0x3C60);
447 sub_through_write(1, 0x3D67);
448 sub_through_write(1, 0x3E6E);
449 sub_through_write(1, 0x3F7F);
450 sub_through_write(1, 0x4001);
451 sub_through_write(1, 0x4107);
452 sub_through_write(1, 0x420C);
453 sub_through_write(1, 0x4310);
454 sub_through_write(1, 0x4414);
455 sub_through_write(1, 0x4518);
456 sub_through_write(1, 0x461C);
457 sub_through_write(1, 0x4720);
458 sub_through_write(1, 0x4824);
459 sub_through_write(1, 0x4928);
460 sub_through_write(1, 0x4A2B);
461 sub_through_write(1, 0x4B2E);
462 sub_through_write(1, 0x4C31);
463 sub_through_write(1, 0x4D34);
464 sub_through_write(1, 0x4E37);
465 sub_through_write(1, 0x4F3A);
466 sub_through_write(1, 0x503C);
467 sub_through_write(1, 0x513E);
468 sub_through_write(1, 0x523F);
469 sub_through_write(1, 0x5340);
470 sub_through_write(1, 0x5441);
471 sub_through_write(1, 0x5543);
472 sub_through_write(1, 0x5646);
473 sub_through_write(1, 0x5749);
474 sub_through_write(1, 0x584C);
475 sub_through_write(1, 0x594F);
476 sub_through_write(1, 0x5A52);
477 sub_through_write(1, 0x5B59);
478 sub_through_write(1, 0x5C60);
479 sub_through_write(1, 0x5D67);
480 sub_through_write(1, 0x5E6E);
481 sub_through_write(1, 0x5F7E);
482 sub_through_write(1, 0x6000);
483 sub_through_write(1, 0x6107);
484 sub_through_write(1, 0x620C);
485 sub_through_write(1, 0x6310);
486 sub_through_write(1, 0x6414);
487 sub_through_write(1, 0x6518);
488 sub_through_write(1, 0x661C);
489 sub_through_write(1, 0x6720);
490 sub_through_write(1, 0x6824);
491 sub_through_write(1, 0x6928);
492 sub_through_write(1, 0x6A2B);
493 sub_through_write(1, 0x6B2E);
494 sub_through_write(1, 0x6C31);
495 sub_through_write(1, 0x6D34);
496 sub_through_write(1, 0x6E37);
497 sub_through_write(1, 0x6F3A);
498 sub_through_write(1, 0x703C);
499 sub_through_write(1, 0x713E);
500 sub_through_write(1, 0x723F);
501 sub_through_write(1, 0x7340);
502 sub_through_write(1, 0x7441);
503 sub_through_write(1, 0x7543);
504 sub_through_write(1, 0x7646);
505 sub_through_write(1, 0x7749);
506 sub_through_write(1, 0x784C);
507 sub_through_write(1, 0x794F);
508 sub_through_write(1, 0x7A52);
509 sub_through_write(1, 0x7B59);
510 sub_through_write(1, 0x7C60);
511 sub_through_write(1, 0x7D67);
512 sub_through_write(1, 0x7E6E);
513 sub_through_write(1, 0x7F7D);
514
515 sub_through_write(1, 0x1851); /* Display on */
516
517 mddi_queue_register_write(REG_AGM, 0x0000, TRUE, 0);
518
519 /* 1 pixel / 1 post clock */
520 mddi_queue_register_write(REG_CLKDIV2, 0x3b00, FALSE, 0);
521
522 /* SUB LCD select */
523 mddi_queue_register_write(REG_PSTCTL2, 0x0080, FALSE, 0);
524
525 /* RS=0,command initiate number=0,select master mode */
526 mddi_queue_register_write(REG_SUBCTL, 0x0202, FALSE, 0);
527
528 /* Sub LCD Data transform start */
529 mddi_queue_register_write(REG_PSTCTL1, 0x0003, FALSE, 0);
530
531 } else if (sharp_subpanel_type == SHARP_SUB_ROHM) {
532
533 sub_through_write(0, 0x01); /* Display setting */
534 sub_through_write(1, 0x00);
535
536 mddi_wait(1);
537 /* Wait 100us <----- ******* Update 2005/01/24 */
538
539 sub_through_write(0, 0xB6);
540 sub_through_write(1, 0x0C);
541 sub_through_write(1, 0x4A);
542 sub_through_write(1, 0x20);
543 sub_through_write(0, 0x3A);
544 sub_through_write(1, 0x05);
545 sub_through_write(0, 0xB7);
546 sub_through_write(1, 0x01);
547 sub_through_write(0, 0xBA);
548 sub_through_write(1, 0x20);
549 sub_through_write(1, 0x02);
550 sub_through_write(0, 0x25);
551 sub_through_write(1, 0x4F);
552 sub_through_write(0, 0xBB);
553 sub_through_write(1, 0x00);
554 sub_through_write(0, 0x36);
555 sub_through_write(1, 0x00);
556 sub_through_write(0, 0xB1);
557 sub_through_write(1, 0x05);
558 sub_through_write(0, 0xBE);
559 sub_through_write(1, 0x80);
560 sub_through_write(0, 0x26);
561 sub_through_write(1, 0x01);
562 sub_through_write(0, 0x2A);
563 sub_through_write(1, 0x02);
564 sub_through_write(1, 0x81);
565 sub_through_write(0, 0x2B);
566 sub_through_write(1, 0x00);
567 sub_through_write(1, 0x7F);
568
569 sub_through_write(0, 0x2C);
570 sub_through_write(0, 0x11); /* Sleep mode off */
571
572 mddi_wait(1);
573 /* Wait 100 ms <----- ******* Update 2005/01/24 */
574
575 sub_through_write(0, 0x29); /* Display on */
576 sub_through_write(0, 0xB3);
577 sub_through_write(1, 0x20);
578 sub_through_write(1, 0xAA);
579 sub_through_write(1, 0xA0);
580 sub_through_write(1, 0x20);
581 sub_through_write(1, 0x30);
582 sub_through_write(1, 0xA6);
583 sub_through_write(1, 0xFF);
584 sub_through_write(1, 0x9A);
585 sub_through_write(1, 0x9F);
586 sub_through_write(1, 0xAF);
587 sub_through_write(1, 0xBC);
588 sub_through_write(1, 0xCF);
589 sub_through_write(1, 0xDF);
590 sub_through_write(1, 0x20);
591 sub_through_write(1, 0x9C);
592 sub_through_write(1, 0x8A);
593
594 sub_through_write(0, 0x002C); /* Display on */
595
596 /* 1 pixel / 2 post clock */
597 mddi_queue_register_write(REG_CLKDIV2, 0x7b00, FALSE, 0);
598
599 /* SUB LCD select */
600 mddi_queue_register_write(REG_PSTCTL2, 0x0080, FALSE, 0);
601
602 /* RS=1,command initiate number=0,select master mode */
603 mddi_queue_register_write(REG_SUBCTL, 0x0242, FALSE, 0);
604
605 /* Sub LCD Data transform start */
606 mddi_queue_register_write(REG_PSTCTL1, 0x0003, FALSE, 0);
607
608 }
609
610 /* Set the MDP pixel data attributes for Sub Display */
611 mddi_host_write_pix_attr_reg(0x00C0);
612}
613
614void mddi_sharp_lcd_vsync_detected(boolean detected)
615{
616 /* static timetick_type start_time = 0; */
617 static struct timeval start_time;
618 static boolean first_time = TRUE;
619 /* uint32 mdp_cnt_val = 0; */
620 /* timetick_type elapsed_us; */
621 struct timeval now;
622 uint32 elapsed_us;
623 uint32 num_vsyncs;
624
625 if ((detected) || (mddi_sharp_vsync_attempts > 5)) {
626 if ((detected) && (mddi_sharp_monitor_refresh_value)) {
627 /* if (start_time != 0) */
628 if (!first_time) {
629 jiffies_to_timeval(jiffies, &now);
630 elapsed_us =
631 (now.tv_sec - start_time.tv_sec) * 1000000 +
632 now.tv_usec - start_time.tv_usec;
633 /*
634 * LCD is configured for a refresh every usecs,
635 * so to determine the number of vsyncs that
636 * have occurred since the last measurement add
637 * half that to the time difference and divide
638 * by the refresh rate.
639 */
640 num_vsyncs = (elapsed_us +
641 (mddi_sharp_usecs_per_refresh >>
642 1)) /
643 mddi_sharp_usecs_per_refresh;
644 /*
645 * LCD is configured for * hsyncs (rows) per
646 * refresh cycle. Calculate new rows_per_second
647 * value based upon these new measurements.
648 * MDP can update with this new value.
649 */
650 mddi_sharp_rows_per_second =
651 (mddi_sharp_rows_per_refresh * 1000 *
652 num_vsyncs) / (elapsed_us / 1000);
653 }
654 /* start_time = timetick_get(); */
655 first_time = FALSE;
656 jiffies_to_timeval(jiffies, &start_time);
657 if (mddi_sharp_report_refresh_measurements) {
658 /* mdp_cnt_val = MDP_LINE_COUNT; */
659 }
660 }
661 /* if detected = TRUE, client initiated wakeup was detected */
662 if (mddi_sharp_vsync_handler != NULL) {
663 (*mddi_sharp_vsync_handler)
664 (mddi_sharp_vsync_handler_arg);
665 mddi_sharp_vsync_handler = NULL;
666 }
667 mddi_vsync_detect_enabled = FALSE;
668 mddi_sharp_vsync_attempts = 0;
669 /* need to clear this vsync wakeup */
670 if (!mddi_queue_register_write_int(REG_INTR, 0x0000)) {
671 MDDI_MSG_ERR("Vsync interrupt clear failed!\n");
672 }
673 if (!detected) {
674 /* give up after 5 failed attempts but show error */
675 MDDI_MSG_NOTICE("Vsync detection failed!\n");
676 } else if ((mddi_sharp_monitor_refresh_value) &&
677 (mddi_sharp_report_refresh_measurements)) {
678 MDDI_MSG_NOTICE(" Lines Per Second=%d!\n",
679 mddi_sharp_rows_per_second);
680 }
681 } else
682 /* if detected = FALSE, we woke up from hibernation, but did not
683 * detect client initiated wakeup.
684 */
685 mddi_sharp_vsync_attempts++;
686}
687
688/* ISR to be executed */
689void mddi_sharp_vsync_set_handler(msm_fb_vsync_handler_type handler, void *arg)
690{
691 boolean error = FALSE;
692 unsigned long flags;
693
694 /* Disable interrupts */
695 spin_lock_irqsave(&mddi_host_spin_lock, flags);
696 /* INTLOCK(); */
697
698 if (mddi_sharp_vsync_handler != NULL)
699 error = TRUE;
700
701 /* Register the handler for this particular GROUP interrupt source */
702 mddi_sharp_vsync_handler = handler;
703 mddi_sharp_vsync_handler_arg = arg;
704
705 /* Restore interrupts */
706 spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
707 /* INTFREE(); */
708
709 if (error)
710 MDDI_MSG_ERR("MDDI: Previous Vsync handler never called\n");
711
712 /* Enable the vsync wakeup */
713 mddi_queue_register_write(REG_INTR, 0x8100, FALSE, 0);
714
715 mddi_sharp_vsync_attempts = 1;
716 mddi_vsync_detect_enabled = TRUE;
717} /* mddi_sharp_vsync_set_handler */
718
719static int mddi_sharp_lcd_on(struct platform_device *pdev)
720{
721 struct msm_fb_data_type *mfd;
722
723 mfd = platform_get_drvdata(pdev);
724
725 if (!mfd)
726 return -ENODEV;
727
728 if (mfd->key != MFD_KEY)
729 return -EINVAL;
730
731 if (mfd->panel.id == SHARP_QVGA_PRIM)
732 mddi_sharp_prim_lcd_init();
733 else
734 mddi_sharp_sub_lcd_init();
735
736 return 0;
737}
738
739static int mddi_sharp_lcd_off(struct platform_device *pdev)
740{
741 mddi_sharp_lcd_powerdown();
742 return 0;
743}
744
745static int __init mddi_sharp_probe(struct platform_device *pdev)
746{
747 if (pdev->id == 0) {
748 mddi_sharp_pdata = pdev->dev.platform_data;
749 return 0;
750 }
751
752 msm_fb_add_device(pdev);
753
754 return 0;
755}
756
757static struct platform_driver this_driver = {
758 .probe = mddi_sharp_probe,
759 .driver = {
760 .name = "mddi_sharp_qvga",
761 },
762};
763
764static struct msm_fb_panel_data mddi_sharp_panel_data0 = {
765 .on = mddi_sharp_lcd_on,
766 .off = mddi_sharp_lcd_off,
767 .set_backlight = mddi_sharp_lcd_set_backlight,
768 .set_vsync_notifier = mddi_sharp_vsync_set_handler,
769};
770
771static struct platform_device this_device_0 = {
772 .name = "mddi_sharp_qvga",
773 .id = SHARP_QVGA_PRIM,
774 .dev = {
775 .platform_data = &mddi_sharp_panel_data0,
776 }
777};
778
779static struct msm_fb_panel_data mddi_sharp_panel_data1 = {
780 .on = mddi_sharp_lcd_on,
781 .off = mddi_sharp_lcd_off,
782};
783
784static struct platform_device this_device_1 = {
785 .name = "mddi_sharp_qvga",
786 .id = SHARP_128X128_SECD,
787 .dev = {
788 .platform_data = &mddi_sharp_panel_data1,
789 }
790};
791
792static int __init mddi_sharp_init(void)
793{
794 int ret;
795 struct msm_panel_info *pinfo;
796
797#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
798 u32 id;
799
800 ret = msm_fb_detect_client("mddi_sharp_qvga");
801 if (ret == -ENODEV)
802 return 0;
803
804 if (ret) {
805 id = mddi_get_client_id();
806
807 if (((id >> 16) != 0x0) || ((id & 0xffff) != 0x8835))
808 return 0;
809 }
810#endif
811 if (mddi_host_core_version > 8) {
812 /* can use faster refresh with newer hw revisions */
813 mddi_sharp_debug_60hz_refresh = TRUE;
814
815 /* Timing variables for tracking vsync */
816 /* dot_clock = 6.00MHz
817 * horizontal count = 296
818 * vertical count = 338
819 * refresh rate = 6000000/(296+338) = 60Hz
820 */
821 mddi_sharp_rows_per_second = 20270; /* 6000000/296 */
822 mddi_sharp_rows_per_refresh = 338;
823 mddi_sharp_usecs_per_refresh = 16674; /* (296+338)/6000000 */
824 } else {
825 /* Timing variables for tracking vsync */
826 /* dot_clock = 5.20MHz
827 * horizontal count = 376
828 * vertical count = 338
829 * refresh rate = 5200000/(376+338) = 41Hz
830 */
831 mddi_sharp_rows_per_second = 13830; /* 5200000/376 */
832 mddi_sharp_rows_per_refresh = 338;
833 mddi_sharp_usecs_per_refresh = 24440; /* (376+338)/5200000 */
834 }
835
836 ret = platform_driver_register(&this_driver);
837 if (!ret) {
838 pinfo = &mddi_sharp_panel_data0.panel_info;
839 pinfo->xres = 240;
840 pinfo->yres = 320;
841 pinfo->type = MDDI_PANEL;
842 pinfo->pdest = DISPLAY_1;
843 pinfo->mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
844 pinfo->wait_cycle = 0;
845 pinfo->bpp = 18;
846 pinfo->fb_num = 2;
847 pinfo->clk_rate = 122880000;
848 pinfo->clk_min = 120000000;
849 pinfo->clk_max = 125000000;
850 pinfo->lcd.vsync_enable = TRUE;
851 pinfo->lcd.refx100 =
852 (mddi_sharp_rows_per_second * 100) /
853 mddi_sharp_rows_per_refresh;
854 pinfo->lcd.v_back_porch = 12;
855 pinfo->lcd.v_front_porch = 6;
856 pinfo->lcd.v_pulse_width = 0;
857 pinfo->lcd.hw_vsync_mode = FALSE;
858 pinfo->lcd.vsync_notifier_period = (1 * HZ);
859 pinfo->bl_max = 7;
860 pinfo->bl_min = 1;
861
862 ret = platform_device_register(&this_device_0);
863 if (ret)
864 platform_driver_unregister(&this_driver);
865
866 pinfo = &mddi_sharp_panel_data1.panel_info;
867 pinfo->xres = 128;
868 pinfo->yres = 128;
869 pinfo->type = MDDI_PANEL;
870 pinfo->pdest = DISPLAY_2;
871 pinfo->mddi.vdopkt = 0x400;
872 pinfo->wait_cycle = 0;
873 pinfo->bpp = 18;
874 pinfo->clk_rate = 122880000;
875 pinfo->clk_min = 120000000;
876 pinfo->clk_max = 125000000;
877 pinfo->fb_num = 2;
878
879 ret = platform_device_register(&this_device_1);
880 if (ret) {
881 platform_device_unregister(&this_device_0);
882 platform_driver_unregister(&this_driver);
883 }
884 }
885
886 if (!ret)
887 mddi_lcd.vsync_detected = mddi_sharp_lcd_vsync_detected;
888
889 return ret;
890}
891
892module_init(mddi_sharp_init);
diff --git a/drivers/staging/msm/mddi_toshiba.c b/drivers/staging/msm/mddi_toshiba.c
new file mode 100644
index 000000000000..e96342d477a2
--- /dev/null
+++ b/drivers/staging/msm/mddi_toshiba.c
@@ -0,0 +1,1741 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include "msm_fb.h"
19#include "mddihost.h"
20#include "mddihosti.h"
21#include "mddi_toshiba.h"
22
23#define TM_GET_DID(id) ((id) & 0xff)
24#define TM_GET_PID(id) (((id) & 0xff00)>>8)
25
26#define MDDI_CLIENT_CORE_BASE 0x108000
27#define LCD_CONTROL_BLOCK_BASE 0x110000
28#define SPI_BLOCK_BASE 0x120000
29#define PWM_BLOCK_BASE 0x140000
30#define SYSTEM_BLOCK1_BASE 0x160000
31
32#define TTBUSSEL (MDDI_CLIENT_CORE_BASE|0x18)
33#define DPSET0 (MDDI_CLIENT_CORE_BASE|0x1C)
34#define DPSET1 (MDDI_CLIENT_CORE_BASE|0x20)
35#define DPSUS (MDDI_CLIENT_CORE_BASE|0x24)
36#define DPRUN (MDDI_CLIENT_CORE_BASE|0x28)
37#define SYSCKENA (MDDI_CLIENT_CORE_BASE|0x2C)
38
39#define BITMAP0 (MDDI_CLIENT_CORE_BASE|0x44)
40#define BITMAP1 (MDDI_CLIENT_CORE_BASE|0x48)
41#define BITMAP2 (MDDI_CLIENT_CORE_BASE|0x4C)
42#define BITMAP3 (MDDI_CLIENT_CORE_BASE|0x50)
43#define BITMAP4 (MDDI_CLIENT_CORE_BASE|0x54)
44
45#define SRST (LCD_CONTROL_BLOCK_BASE|0x00)
46#define PORT_ENB (LCD_CONTROL_BLOCK_BASE|0x04)
47#define START (LCD_CONTROL_BLOCK_BASE|0x08)
48#define PORT (LCD_CONTROL_BLOCK_BASE|0x0C)
49
50#define INTFLG (LCD_CONTROL_BLOCK_BASE|0x18)
51#define INTMSK (LCD_CONTROL_BLOCK_BASE|0x1C)
52#define MPLFBUF (LCD_CONTROL_BLOCK_BASE|0x20)
53
54#define PXL (LCD_CONTROL_BLOCK_BASE|0x30)
55#define HCYCLE (LCD_CONTROL_BLOCK_BASE|0x34)
56#define HSW (LCD_CONTROL_BLOCK_BASE|0x38)
57#define HDE_START (LCD_CONTROL_BLOCK_BASE|0x3C)
58#define HDE_SIZE (LCD_CONTROL_BLOCK_BASE|0x40)
59#define VCYCLE (LCD_CONTROL_BLOCK_BASE|0x44)
60#define VSW (LCD_CONTROL_BLOCK_BASE|0x48)
61#define VDE_START (LCD_CONTROL_BLOCK_BASE|0x4C)
62#define VDE_SIZE (LCD_CONTROL_BLOCK_BASE|0x50)
63#define WAKEUP (LCD_CONTROL_BLOCK_BASE|0x54)
64#define REGENB (LCD_CONTROL_BLOCK_BASE|0x5C)
65#define VSYNIF (LCD_CONTROL_BLOCK_BASE|0x60)
66#define WRSTB (LCD_CONTROL_BLOCK_BASE|0x64)
67#define RDSTB (LCD_CONTROL_BLOCK_BASE|0x68)
68#define ASY_DATA (LCD_CONTROL_BLOCK_BASE|0x6C)
69#define ASY_DATB (LCD_CONTROL_BLOCK_BASE|0x70)
70#define ASY_DATC (LCD_CONTROL_BLOCK_BASE|0x74)
71#define ASY_DATD (LCD_CONTROL_BLOCK_BASE|0x78)
72#define ASY_DATE (LCD_CONTROL_BLOCK_BASE|0x7C)
73#define ASY_DATF (LCD_CONTROL_BLOCK_BASE|0x80)
74#define ASY_DATG (LCD_CONTROL_BLOCK_BASE|0x84)
75#define ASY_DATH (LCD_CONTROL_BLOCK_BASE|0x88)
76#define ASY_CMDSET (LCD_CONTROL_BLOCK_BASE|0x8C)
77#define MONI (LCD_CONTROL_BLOCK_BASE|0xB0)
78#define VPOS (LCD_CONTROL_BLOCK_BASE|0xC0)
79
80#define SSICTL (SPI_BLOCK_BASE|0x00)
81#define SSITIME (SPI_BLOCK_BASE|0x04)
82#define SSITX (SPI_BLOCK_BASE|0x08)
83#define SSIINTS (SPI_BLOCK_BASE|0x14)
84
85#define TIMER0LOAD (PWM_BLOCK_BASE|0x00)
86#define TIMER0CTRL (PWM_BLOCK_BASE|0x08)
87#define PWM0OFF (PWM_BLOCK_BASE|0x1C)
88#define TIMER1LOAD (PWM_BLOCK_BASE|0x20)
89#define TIMER1CTRL (PWM_BLOCK_BASE|0x28)
90#define PWM1OFF (PWM_BLOCK_BASE|0x3C)
91#define TIMER2LOAD (PWM_BLOCK_BASE|0x40)
92#define TIMER2CTRL (PWM_BLOCK_BASE|0x48)
93#define PWM2OFF (PWM_BLOCK_BASE|0x5C)
94#define PWMCR (PWM_BLOCK_BASE|0x68)
95
96#define GPIOIS (GPIO_BLOCK_BASE|0x08)
97#define GPIOIEV (GPIO_BLOCK_BASE|0x10)
98#define GPIOIC (GPIO_BLOCK_BASE|0x20)
99
100#define WKREQ (SYSTEM_BLOCK1_BASE|0x00)
101#define CLKENB (SYSTEM_BLOCK1_BASE|0x04)
102#define DRAMPWR (SYSTEM_BLOCK1_BASE|0x08)
103#define INTMASK (SYSTEM_BLOCK1_BASE|0x0C)
104#define CNT_DIS (SYSTEM_BLOCK1_BASE|0x10)
105
106typedef enum {
107 TOSHIBA_STATE_OFF,
108 TOSHIBA_STATE_PRIM_SEC_STANDBY,
109 TOSHIBA_STATE_PRIM_SEC_READY,
110 TOSHIBA_STATE_PRIM_NORMAL_MODE,
111 TOSHIBA_STATE_SEC_NORMAL_MODE
112} mddi_toshiba_state_t;
113
114static uint32 mddi_toshiba_curr_vpos;
115static boolean mddi_toshiba_monitor_refresh_value = FALSE;
116static boolean mddi_toshiba_report_refresh_measurements = FALSE;
117
118boolean mddi_toshiba_61Hz_refresh = TRUE;
119
120/* Modifications to timing to increase refresh rate to > 60Hz.
121 * 20MHz dot clock.
122 * 646 total rows.
123 * 506 total columns.
124 * refresh rate = 61.19Hz
125 */
126static uint32 mddi_toshiba_rows_per_second = 39526;
127static uint32 mddi_toshiba_usecs_per_refresh = 16344;
128static uint32 mddi_toshiba_rows_per_refresh = 646;
129extern boolean mddi_vsync_detect_enabled;
130
131static msm_fb_vsync_handler_type mddi_toshiba_vsync_handler;
132static void *mddi_toshiba_vsync_handler_arg;
133static uint16 mddi_toshiba_vsync_attempts;
134
135static mddi_toshiba_state_t toshiba_state = TOSHIBA_STATE_OFF;
136
137static struct msm_panel_common_pdata *mddi_toshiba_pdata;
138
139static int mddi_toshiba_lcd_on(struct platform_device *pdev);
140static int mddi_toshiba_lcd_off(struct platform_device *pdev);
141
142static void mddi_toshiba_state_transition(mddi_toshiba_state_t a,
143 mddi_toshiba_state_t b)
144{
145 if (toshiba_state != a) {
146 MDDI_MSG_ERR("toshiba state trans. (%d->%d) found %d\n", a, b,
147 toshiba_state);
148 }
149 toshiba_state = b;
150}
151
152#define GORDON_REG_IMGCTL1 0x10 /* Image interface control 1 */
153#define GORDON_REG_IMGCTL2 0x11 /* Image interface control 2 */
154#define GORDON_REG_IMGSET1 0x12 /* Image interface settings 1 */
155#define GORDON_REG_IMGSET2 0x13 /* Image interface settings 2 */
156#define GORDON_REG_IVBP1 0x14 /* DM0: Vert back porch */
157#define GORDON_REG_IHBP1 0x15 /* DM0: Horiz back porch */
158#define GORDON_REG_IVNUM1 0x16 /* DM0: Num of vert lines */
159#define GORDON_REG_IHNUM1 0x17 /* DM0: Num of pixels per line */
160#define GORDON_REG_IVBP2 0x18 /* DM1: Vert back porch */
161#define GORDON_REG_IHBP2 0x19 /* DM1: Horiz back porch */
162#define GORDON_REG_IVNUM2 0x1A /* DM1: Num of vert lines */
163#define GORDON_REG_IHNUM2 0x1B /* DM1: Num of pixels per line */
164#define GORDON_REG_LCDIFCTL1 0x30 /* LCD interface control 1 */
165#define GORDON_REG_VALTRAN 0x31 /* LCD IF ctl: VALTRAN sync flag */
166#define GORDON_REG_AVCTL 0x33
167#define GORDON_REG_LCDIFCTL2 0x34 /* LCD interface control 2 */
168#define GORDON_REG_LCDIFCTL3 0x35 /* LCD interface control 3 */
169#define GORDON_REG_LCDIFSET1 0x36 /* LCD interface settings 1 */
170#define GORDON_REG_PCCTL 0x3C
171#define GORDON_REG_TPARAM1 0x40
172#define GORDON_REG_TLCDIF1 0x41
173#define GORDON_REG_TSSPB_ST1 0x42
174#define GORDON_REG_TSSPB_ED1 0x43
175#define GORDON_REG_TSCK_ST1 0x44
176#define GORDON_REG_TSCK_WD1 0x45
177#define GORDON_REG_TGSPB_VST1 0x46
178#define GORDON_REG_TGSPB_VED1 0x47
179#define GORDON_REG_TGSPB_CH1 0x48
180#define GORDON_REG_TGCK_ST1 0x49
181#define GORDON_REG_TGCK_ED1 0x4A
182#define GORDON_REG_TPCTL_ST1 0x4B
183#define GORDON_REG_TPCTL_ED1 0x4C
184#define GORDON_REG_TPCHG_ED1 0x4D
185#define GORDON_REG_TCOM_CH1 0x4E
186#define GORDON_REG_THBP1 0x4F
187#define GORDON_REG_TPHCTL1 0x50
188#define GORDON_REG_EVPH1 0x51
189#define GORDON_REG_EVPL1 0x52
190#define GORDON_REG_EVNH1 0x53
191#define GORDON_REG_EVNL1 0x54
192#define GORDON_REG_TBIAS1 0x55
193#define GORDON_REG_TPARAM2 0x56
194#define GORDON_REG_TLCDIF2 0x57
195#define GORDON_REG_TSSPB_ST2 0x58
196#define GORDON_REG_TSSPB_ED2 0x59
197#define GORDON_REG_TSCK_ST2 0x5A
198#define GORDON_REG_TSCK_WD2 0x5B
199#define GORDON_REG_TGSPB_VST2 0x5C
200#define GORDON_REG_TGSPB_VED2 0x5D
201#define GORDON_REG_TGSPB_CH2 0x5E
202#define GORDON_REG_TGCK_ST2 0x5F
203#define GORDON_REG_TGCK_ED2 0x60
204#define GORDON_REG_TPCTL_ST2 0x61
205#define GORDON_REG_TPCTL_ED2 0x62
206#define GORDON_REG_TPCHG_ED2 0x63
207#define GORDON_REG_TCOM_CH2 0x64
208#define GORDON_REG_THBP2 0x65
209#define GORDON_REG_TPHCTL2 0x66
210#define GORDON_REG_EVPH2 0x67
211#define GORDON_REG_EVPL2 0x68
212#define GORDON_REG_EVNH2 0x69
213#define GORDON_REG_EVNL2 0x6A
214#define GORDON_REG_TBIAS2 0x6B
215#define GORDON_REG_POWCTL 0x80
216#define GORDON_REG_POWOSC1 0x81
217#define GORDON_REG_POWOSC2 0x82
218#define GORDON_REG_POWSET 0x83
219#define GORDON_REG_POWTRM1 0x85
220#define GORDON_REG_POWTRM2 0x86
221#define GORDON_REG_POWTRM3 0x87
222#define GORDON_REG_POWTRMSEL 0x88
223#define GORDON_REG_POWHIZ 0x89
224
225void serigo(uint16 reg, uint8 data)
226{
227 uint32 mddi_val = 0;
228 mddi_queue_register_read(SSIINTS, &mddi_val, TRUE, 0);
229 if (mddi_val & (1 << 8))
230 mddi_wait(1);
231 /* No De-assert of CS and send 2 bytes */
232 mddi_val = 0x90000 | ((0x00FF & reg) << 8) | data;
233 mddi_queue_register_write(SSITX, mddi_val, TRUE, 0);
234}
235
236void gordon_init(void)
237{
238 /* Image interface settings ***/
239 serigo(GORDON_REG_IMGCTL2, 0x00);
240 serigo(GORDON_REG_IMGSET1, 0x01);
241
242 /* Exchange the RGB signal for J510(Softbank mobile) */
243 serigo(GORDON_REG_IMGSET2, 0x12);
244 serigo(GORDON_REG_LCDIFSET1, 0x00);
245 mddi_wait(2);
246
247 /* Pre-charge settings */
248 serigo(GORDON_REG_PCCTL, 0x09);
249 serigo(GORDON_REG_LCDIFCTL2, 0x1B);
250 mddi_wait(1);
251}
252
253void gordon_disp_on(void)
254{
255 /*gordon_dispmode setting */
256 /*VGA settings */
257 serigo(GORDON_REG_TPARAM1, 0x30);
258 serigo(GORDON_REG_TLCDIF1, 0x00);
259 serigo(GORDON_REG_TSSPB_ST1, 0x8B);
260 serigo(GORDON_REG_TSSPB_ED1, 0x93);
261 mddi_wait(2);
262 serigo(GORDON_REG_TSCK_ST1, 0x88);
263 serigo(GORDON_REG_TSCK_WD1, 0x00);
264 serigo(GORDON_REG_TGSPB_VST1, 0x01);
265 serigo(GORDON_REG_TGSPB_VED1, 0x02);
266 mddi_wait(2);
267 serigo(GORDON_REG_TGSPB_CH1, 0x5E);
268 serigo(GORDON_REG_TGCK_ST1, 0x80);
269 serigo(GORDON_REG_TGCK_ED1, 0x3C);
270 serigo(GORDON_REG_TPCTL_ST1, 0x50);
271 mddi_wait(2);
272 serigo(GORDON_REG_TPCTL_ED1, 0x74);
273 serigo(GORDON_REG_TPCHG_ED1, 0x78);
274 serigo(GORDON_REG_TCOM_CH1, 0x50);
275 serigo(GORDON_REG_THBP1, 0x84);
276 mddi_wait(2);
277 serigo(GORDON_REG_TPHCTL1, 0x00);
278 serigo(GORDON_REG_EVPH1, 0x70);
279 serigo(GORDON_REG_EVPL1, 0x64);
280 serigo(GORDON_REG_EVNH1, 0x56);
281 mddi_wait(2);
282 serigo(GORDON_REG_EVNL1, 0x48);
283 serigo(GORDON_REG_TBIAS1, 0x88);
284 mddi_wait(2);
285 serigo(GORDON_REG_TPARAM2, 0x28);
286 serigo(GORDON_REG_TLCDIF2, 0x14);
287 serigo(GORDON_REG_TSSPB_ST2, 0x49);
288 serigo(GORDON_REG_TSSPB_ED2, 0x4B);
289 mddi_wait(2);
290 serigo(GORDON_REG_TSCK_ST2, 0x4A);
291 serigo(GORDON_REG_TSCK_WD2, 0x02);
292 serigo(GORDON_REG_TGSPB_VST2, 0x02);
293 serigo(GORDON_REG_TGSPB_VED2, 0x03);
294 mddi_wait(2);
295 serigo(GORDON_REG_TGSPB_CH2, 0x2F);
296 serigo(GORDON_REG_TGCK_ST2, 0x40);
297 serigo(GORDON_REG_TGCK_ED2, 0x1E);
298 serigo(GORDON_REG_TPCTL_ST2, 0x2C);
299 mddi_wait(2);
300 serigo(GORDON_REG_TPCTL_ED2, 0x3A);
301 serigo(GORDON_REG_TPCHG_ED2, 0x3C);
302 serigo(GORDON_REG_TCOM_CH2, 0x28);
303 serigo(GORDON_REG_THBP2, 0x4D);
304 mddi_wait(2);
305 serigo(GORDON_REG_TPHCTL2, 0x1A);
306 mddi_wait(2);
307 serigo(GORDON_REG_IVBP1, 0x02);
308 serigo(GORDON_REG_IHBP1, 0x90);
309 serigo(GORDON_REG_IVNUM1, 0xA0);
310 serigo(GORDON_REG_IHNUM1, 0x78);
311 mddi_wait(2);
312 serigo(GORDON_REG_IVBP2, 0x02);
313 serigo(GORDON_REG_IHBP2, 0x48);
314 serigo(GORDON_REG_IVNUM2, 0x50);
315 serigo(GORDON_REG_IHNUM2, 0x3C);
316 mddi_wait(2);
317 serigo(GORDON_REG_POWCTL, 0x03);
318 mddi_wait(15);
319 serigo(GORDON_REG_POWCTL, 0x07);
320 mddi_wait(15);
321 serigo(GORDON_REG_POWCTL, 0x0F);
322 mddi_wait(15);
323 serigo(GORDON_REG_AVCTL, 0x03);
324 mddi_wait(15);
325 serigo(GORDON_REG_POWCTL, 0x1F);
326 mddi_wait(15);
327 serigo(GORDON_REG_POWCTL, 0x5F);
328 mddi_wait(15);
329 serigo(GORDON_REG_POWCTL, 0x7F);
330 mddi_wait(15);
331 serigo(GORDON_REG_LCDIFCTL1, 0x02);
332 mddi_wait(15);
333 serigo(GORDON_REG_IMGCTL1, 0x00);
334 mddi_wait(15);
335 serigo(GORDON_REG_LCDIFCTL3, 0x00);
336 mddi_wait(15);
337 serigo(GORDON_REG_VALTRAN, 0x01);
338 mddi_wait(15);
339 serigo(GORDON_REG_LCDIFCTL1, 0x03);
340 serigo(GORDON_REG_LCDIFCTL1, 0x03);
341 mddi_wait(1);
342}
343
344void gordon_disp_off(void)
345{
346 serigo(GORDON_REG_LCDIFCTL2, 0x7B);
347 serigo(GORDON_REG_VALTRAN, 0x01);
348 serigo(GORDON_REG_LCDIFCTL1, 0x02);
349 serigo(GORDON_REG_LCDIFCTL3, 0x01);
350 mddi_wait(20);
351 serigo(GORDON_REG_VALTRAN, 0x01);
352 serigo(GORDON_REG_IMGCTL1, 0x01);
353 serigo(GORDON_REG_LCDIFCTL1, 0x00);
354 mddi_wait(20);
355 serigo(GORDON_REG_POWCTL, 0x1F);
356 mddi_wait(40);
357 serigo(GORDON_REG_POWCTL, 0x07);
358 mddi_wait(40);
359 serigo(GORDON_REG_POWCTL, 0x03);
360 mddi_wait(40);
361 serigo(GORDON_REG_POWCTL, 0x00);
362 mddi_wait(40);
363}
364
365void gordon_disp_init(void)
366{
367 gordon_init();
368 mddi_wait(20);
369 gordon_disp_on();
370}
371
372static void toshiba_common_initial_setup(struct msm_fb_data_type *mfd)
373{
374 if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT) {
375 write_client_reg(DPSET0 , 0x4bec0066, TRUE);
376 write_client_reg(DPSET1 , 0x00000113, TRUE);
377 write_client_reg(DPSUS , 0x00000000, TRUE);
378 write_client_reg(DPRUN , 0x00000001, TRUE);
379 mddi_wait(5);
380 write_client_reg(SYSCKENA , 0x00000001, TRUE);
381 write_client_reg(CLKENB , 0x0000a0e9, TRUE);
382
383 write_client_reg(GPIODATA , 0x03FF0000, TRUE);
384 write_client_reg(GPIODIR , 0x0000024D, TRUE);
385 write_client_reg(GPIOSEL , 0x00000173, TRUE);
386 write_client_reg(GPIOPC , 0x03C300C0, TRUE);
387 write_client_reg(WKREQ , 0x00000000, TRUE);
388 write_client_reg(GPIOIS , 0x00000000, TRUE);
389 write_client_reg(GPIOIEV , 0x00000001, TRUE);
390 write_client_reg(GPIOIC , 0x000003FF, TRUE);
391 write_client_reg(GPIODATA , 0x00040004, TRUE);
392
393 write_client_reg(GPIODATA , 0x00080008, TRUE);
394 write_client_reg(DRAMPWR , 0x00000001, TRUE);
395 write_client_reg(CLKENB , 0x0000a0eb, TRUE);
396 write_client_reg(PWMCR , 0x00000000, TRUE);
397 mddi_wait(1);
398
399 write_client_reg(SSICTL , 0x00060399, TRUE);
400 write_client_reg(SSITIME , 0x00000100, TRUE);
401 write_client_reg(CNT_DIS , 0x00000002, TRUE);
402 write_client_reg(SSICTL , 0x0006039b, TRUE);
403
404 write_client_reg(SSITX , 0x00000000, TRUE);
405 mddi_wait(7);
406 write_client_reg(SSITX , 0x00000000, TRUE);
407 mddi_wait(7);
408 write_client_reg(SSITX , 0x00000000, TRUE);
409 mddi_wait(7);
410
411 write_client_reg(SSITX , 0x000800BA, TRUE);
412 write_client_reg(SSITX , 0x00000111, TRUE);
413 write_client_reg(SSITX , 0x00080036, TRUE);
414 write_client_reg(SSITX , 0x00000100, TRUE);
415 mddi_wait(1);
416 write_client_reg(SSITX , 0x0008003A, TRUE);
417 write_client_reg(SSITX , 0x00000160, TRUE);
418 write_client_reg(SSITX , 0x000800B1, TRUE);
419 write_client_reg(SSITX , 0x0000015D, TRUE);
420 mddi_wait(1);
421 write_client_reg(SSITX , 0x000800B2, TRUE);
422 write_client_reg(SSITX , 0x00000133, TRUE);
423 write_client_reg(SSITX , 0x000800B3, TRUE);
424 write_client_reg(SSITX , 0x00000122, TRUE);
425 mddi_wait(1);
426 write_client_reg(SSITX , 0x000800B4, TRUE);
427 write_client_reg(SSITX , 0x00000102, TRUE);
428 write_client_reg(SSITX , 0x000800B5, TRUE);
429 write_client_reg(SSITX , 0x0000011E, TRUE);
430 mddi_wait(1);
431 write_client_reg(SSITX , 0x000800B6, TRUE);
432 write_client_reg(SSITX , 0x00000127, TRUE);
433 write_client_reg(SSITX , 0x000800B7, TRUE);
434 write_client_reg(SSITX , 0x00000103, TRUE);
435 mddi_wait(1);
436 write_client_reg(SSITX , 0x000800B9, TRUE);
437 write_client_reg(SSITX , 0x00000124, TRUE);
438 write_client_reg(SSITX , 0x000800BD, TRUE);
439 write_client_reg(SSITX , 0x000001A1, TRUE);
440 mddi_wait(1);
441 write_client_reg(SSITX , 0x000800BB, TRUE);
442 write_client_reg(SSITX , 0x00000100, TRUE);
443 write_client_reg(SSITX , 0x000800BF, TRUE);
444 write_client_reg(SSITX , 0x00000101, TRUE);
445 mddi_wait(1);
446 write_client_reg(SSITX , 0x000800BE, TRUE);
447 write_client_reg(SSITX , 0x00000100, TRUE);
448 write_client_reg(SSITX , 0x000800C0, TRUE);
449 write_client_reg(SSITX , 0x00000111, TRUE);
450 mddi_wait(1);
451 write_client_reg(SSITX , 0x000800C1, TRUE);
452 write_client_reg(SSITX , 0x00000111, TRUE);
453 write_client_reg(SSITX , 0x000800C2, TRUE);
454 write_client_reg(SSITX , 0x00000111, TRUE);
455 mddi_wait(1);
456 write_client_reg(SSITX , 0x000800C3, TRUE);
457 write_client_reg(SSITX , 0x00080132, TRUE);
458 write_client_reg(SSITX , 0x00000132, TRUE);
459 mddi_wait(1);
460 write_client_reg(SSITX , 0x000800C4, TRUE);
461 write_client_reg(SSITX , 0x00080132, TRUE);
462 write_client_reg(SSITX , 0x00000132, TRUE);
463 mddi_wait(1);
464 write_client_reg(SSITX , 0x000800C5, TRUE);
465 write_client_reg(SSITX , 0x00080132, TRUE);
466 write_client_reg(SSITX , 0x00000132, TRUE);
467 mddi_wait(1);
468 write_client_reg(SSITX , 0x000800C6, TRUE);
469 write_client_reg(SSITX , 0x00080132, TRUE);
470 write_client_reg(SSITX , 0x00000132, TRUE);
471 mddi_wait(1);
472 write_client_reg(SSITX , 0x000800C7, TRUE);
473 write_client_reg(SSITX , 0x00080164, TRUE);
474 write_client_reg(SSITX , 0x00000145, TRUE);
475 mddi_wait(1);
476 write_client_reg(SSITX , 0x000800C8, TRUE);
477 write_client_reg(SSITX , 0x00000144, TRUE);
478 write_client_reg(SSITX , 0x000800C9, TRUE);
479 write_client_reg(SSITX , 0x00000152, TRUE);
480 mddi_wait(1);
481 write_client_reg(SSITX , 0x000800CA, TRUE);
482 write_client_reg(SSITX , 0x00000100, TRUE);
483 mddi_wait(1);
484 write_client_reg(SSITX , 0x000800EC, TRUE);
485 write_client_reg(SSITX , 0x00080101, TRUE);
486 write_client_reg(SSITX , 0x000001FC, TRUE);
487 mddi_wait(1);
488 write_client_reg(SSITX , 0x000800CF, TRUE);
489 write_client_reg(SSITX , 0x00000101, TRUE);
490 mddi_wait(1);
491 write_client_reg(SSITX , 0x000800D0, TRUE);
492 write_client_reg(SSITX , 0x00080110, TRUE);
493 write_client_reg(SSITX , 0x00000104, TRUE);
494 mddi_wait(1);
495 write_client_reg(SSITX , 0x000800D1, TRUE);
496 write_client_reg(SSITX , 0x00000101, TRUE);
497 mddi_wait(1);
498 write_client_reg(SSITX , 0x000800D2, TRUE);
499 write_client_reg(SSITX , 0x00080100, TRUE);
500 write_client_reg(SSITX , 0x00000128, TRUE);
501 mddi_wait(1);
502 write_client_reg(SSITX , 0x000800D3, TRUE);
503 write_client_reg(SSITX , 0x00080100, TRUE);
504 write_client_reg(SSITX , 0x00000128, TRUE);
505 mddi_wait(1);
506 write_client_reg(SSITX , 0x000800D4, TRUE);
507 write_client_reg(SSITX , 0x00080126, TRUE);
508 write_client_reg(SSITX , 0x000001A4, TRUE);
509 mddi_wait(1);
510 write_client_reg(SSITX , 0x000800D5, TRUE);
511 write_client_reg(SSITX , 0x00000120, TRUE);
512 mddi_wait(1);
513 write_client_reg(SSITX , 0x000800EF, TRUE);
514 write_client_reg(SSITX , 0x00080132, TRUE);
515 write_client_reg(SSITX , 0x00000100, TRUE);
516 mddi_wait(1);
517
518 write_client_reg(BITMAP0 , 0x032001E0, TRUE);
519 write_client_reg(BITMAP1 , 0x032001E0, TRUE);
520 write_client_reg(BITMAP2 , 0x014000F0, TRUE);
521 write_client_reg(BITMAP3 , 0x014000F0, TRUE);
522 write_client_reg(BITMAP4 , 0x014000F0, TRUE);
523 write_client_reg(CLKENB , 0x0000A1EB, TRUE);
524 write_client_reg(PORT_ENB , 0x00000001, TRUE);
525 write_client_reg(PORT , 0x00000004, TRUE);
526 write_client_reg(PXL , 0x00000002, TRUE);
527 write_client_reg(MPLFBUF , 0x00000000, TRUE);
528 write_client_reg(HCYCLE , 0x000000FD, TRUE);
529 write_client_reg(HSW , 0x00000003, TRUE);
530 write_client_reg(HDE_START , 0x00000007, TRUE);
531 write_client_reg(HDE_SIZE , 0x000000EF, TRUE);
532 write_client_reg(VCYCLE , 0x00000325, TRUE);
533 write_client_reg(VSW , 0x00000001, TRUE);
534 write_client_reg(VDE_START , 0x00000003, TRUE);
535 write_client_reg(VDE_SIZE , 0x0000031F, TRUE);
536 write_client_reg(START , 0x00000001, TRUE);
537 mddi_wait(32);
538 write_client_reg(SSITX , 0x000800BC, TRUE);
539 write_client_reg(SSITX , 0x00000180, TRUE);
540 write_client_reg(SSITX , 0x0008003B, TRUE);
541 write_client_reg(SSITX , 0x00000100, TRUE);
542 mddi_wait(1);
543 write_client_reg(SSITX , 0x000800B0, TRUE);
544 write_client_reg(SSITX , 0x00000116, TRUE);
545 mddi_wait(1);
546 write_client_reg(SSITX , 0x000800B8, TRUE);
547 write_client_reg(SSITX , 0x000801FF, TRUE);
548 write_client_reg(SSITX , 0x000001F5, TRUE);
549 mddi_wait(1);
550 write_client_reg(SSITX , 0x00000011, TRUE);
551 mddi_wait(5);
552 write_client_reg(SSITX , 0x00000029, TRUE);
553 return;
554 }
555
556 if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA) {
557 write_client_reg(DPSET0, 0x4BEC0066, TRUE);
558 write_client_reg(DPSET1, 0x00000113, TRUE);
559 write_client_reg(DPSUS, 0x00000000, TRUE);
560 write_client_reg(DPRUN, 0x00000001, TRUE);
561 mddi_wait(14);
562 write_client_reg(SYSCKENA, 0x00000001, TRUE);
563 write_client_reg(CLKENB, 0x000000EF, TRUE);
564 write_client_reg(GPIO_BLOCK_BASE, 0x03FF0000, TRUE);
565 write_client_reg(GPIODIR, 0x0000024D, TRUE);
566 write_client_reg(SYSTEM_BLOCK2_BASE, 0x00000173, TRUE);
567 write_client_reg(GPIOPC, 0x03C300C0, TRUE);
568 write_client_reg(SYSTEM_BLOCK1_BASE, 0x00000000, TRUE);
569 write_client_reg(GPIOIS, 0x00000000, TRUE);
570 write_client_reg(GPIOIEV, 0x00000001, TRUE);
571 write_client_reg(GPIOIC, 0x000003FF, TRUE);
572 write_client_reg(GPIO_BLOCK_BASE, 0x00060006, TRUE);
573 write_client_reg(GPIO_BLOCK_BASE, 0x00080008, TRUE);
574 write_client_reg(GPIO_BLOCK_BASE, 0x02000200, TRUE);
575 write_client_reg(DRAMPWR, 0x00000001, TRUE);
576 write_client_reg(TIMER0CTRL, 0x00000060, TRUE);
577 write_client_reg(PWM_BLOCK_BASE, 0x00001388, TRUE);
578 write_client_reg(PWM0OFF, 0x00001387, TRUE);
579 write_client_reg(TIMER1CTRL, 0x00000060, TRUE);
580 write_client_reg(TIMER1LOAD, 0x00001388, TRUE);
581 write_client_reg(PWM1OFF, 0x00001387, TRUE);
582 write_client_reg(TIMER0CTRL, 0x000000E0, TRUE);
583 write_client_reg(TIMER1CTRL, 0x000000E0, TRUE);
584 write_client_reg(PWMCR, 0x00000003, TRUE);
585 mddi_wait(1);
586 write_client_reg(SPI_BLOCK_BASE, 0x00063111, TRUE);
587 write_client_reg(SSITIME, 0x00000100, TRUE);
588 write_client_reg(SPI_BLOCK_BASE, 0x00063113, TRUE);
589 mddi_wait(1);
590 write_client_reg(SSITX, 0x00000000, TRUE);
591 mddi_wait(1);
592 write_client_reg(SSITX, 0x00000000, TRUE);
593 mddi_wait(1);
594 write_client_reg(SSITX, 0x00000000, TRUE);
595 mddi_wait(1);
596 write_client_reg(CLKENB, 0x0000A1EF, TRUE);
597 write_client_reg(START, 0x00000000, TRUE);
598 write_client_reg(WRSTB, 0x0000003F, TRUE);
599 write_client_reg(RDSTB, 0x00000432, TRUE);
600 write_client_reg(PORT_ENB, 0x00000002, TRUE);
601 write_client_reg(VSYNIF, 0x00000000, TRUE);
602 write_client_reg(ASY_DATA, 0x80000000, TRUE);
603 write_client_reg(ASY_DATB, 0x00000001, TRUE);
604 write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
605 write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
606 mddi_wait(10);
607 write_client_reg(ASY_DATA, 0x80000000, TRUE);
608 write_client_reg(ASY_DATB, 0x80000000, TRUE);
609 write_client_reg(ASY_DATC, 0x80000000, TRUE);
610 write_client_reg(ASY_DATD, 0x80000000, TRUE);
611 write_client_reg(ASY_CMDSET, 0x00000009, TRUE);
612 write_client_reg(ASY_CMDSET, 0x00000008, TRUE);
613 write_client_reg(ASY_DATA, 0x80000007, TRUE);
614 write_client_reg(ASY_DATB, 0x00004005, TRUE);
615 write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
616 write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
617 mddi_wait(20);
618 write_client_reg(ASY_DATA, 0x80000059, TRUE);
619 write_client_reg(ASY_DATB, 0x00000000, TRUE);
620 write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
621 write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
622
623 write_client_reg(VSYNIF, 0x00000001, TRUE);
624 write_client_reg(PORT_ENB, 0x00000001, TRUE);
625 } else {
626 write_client_reg(DPSET0, 0x4BEC0066, TRUE);
627 write_client_reg(DPSET1, 0x00000113, TRUE);
628 write_client_reg(DPSUS, 0x00000000, TRUE);
629 write_client_reg(DPRUN, 0x00000001, TRUE);
630 mddi_wait(14);
631 write_client_reg(SYSCKENA, 0x00000001, TRUE);
632 write_client_reg(CLKENB, 0x000000EF, TRUE);
633 write_client_reg(GPIODATA, 0x03FF0000, TRUE);
634 write_client_reg(GPIODIR, 0x0000024D, TRUE);
635 write_client_reg(GPIOSEL, 0x00000173, TRUE);
636 write_client_reg(GPIOPC, 0x03C300C0, TRUE);
637 write_client_reg(WKREQ, 0x00000000, TRUE);
638 write_client_reg(GPIOIS, 0x00000000, TRUE);
639 write_client_reg(GPIOIEV, 0x00000001, TRUE);
640 write_client_reg(GPIOIC, 0x000003FF, TRUE);
641 write_client_reg(GPIODATA, 0x00060006, TRUE);
642 write_client_reg(GPIODATA, 0x00080008, TRUE);
643 write_client_reg(GPIODATA, 0x02000200, TRUE);
644
645 if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA) {
646 mddi_wait(400);
647 write_client_reg(DRAMPWR, 0x00000001, TRUE);
648
649 write_client_reg(CNT_DIS, 0x00000002, TRUE);
650 write_client_reg(BITMAP0, 0x01E00320, TRUE);
651 write_client_reg(PORT_ENB, 0x00000001, TRUE);
652 write_client_reg(PORT, 0x00000004, TRUE);
653 write_client_reg(PXL, 0x0000003A, TRUE);
654 write_client_reg(MPLFBUF, 0x00000000, TRUE);
655 write_client_reg(HCYCLE, 0x00000253, TRUE);
656 write_client_reg(HSW, 0x00000003, TRUE);
657 write_client_reg(HDE_START, 0x00000017, TRUE);
658 write_client_reg(HDE_SIZE, 0x0000018F, TRUE);
659 write_client_reg(VCYCLE, 0x000001FF, TRUE);
660 write_client_reg(VSW, 0x00000001, TRUE);
661 write_client_reg(VDE_START, 0x00000003, TRUE);
662 write_client_reg(VDE_SIZE, 0x000001DF, TRUE);
663 write_client_reg(START, 0x00000001, TRUE);
664 mddi_wait(1);
665 write_client_reg(TIMER0CTRL, 0x00000060, TRUE);
666 write_client_reg(TIMER0LOAD, 0x00001388, TRUE);
667 write_client_reg(TIMER1CTRL, 0x00000060, TRUE);
668 write_client_reg(TIMER1LOAD, 0x00001388, TRUE);
669 write_client_reg(PWM1OFF, 0x00000087, TRUE);
670 } else {
671 write_client_reg(DRAMPWR, 0x00000001, TRUE);
672 write_client_reg(TIMER0CTRL, 0x00000060, TRUE);
673 write_client_reg(TIMER0LOAD, 0x00001388, TRUE);
674 write_client_reg(TIMER1CTRL, 0x00000060, TRUE);
675 write_client_reg(TIMER1LOAD, 0x00001388, TRUE);
676 write_client_reg(PWM1OFF, 0x00001387, TRUE);
677 }
678
679 write_client_reg(TIMER0CTRL, 0x000000E0, TRUE);
680 write_client_reg(TIMER1CTRL, 0x000000E0, TRUE);
681 write_client_reg(PWMCR, 0x00000003, TRUE);
682 mddi_wait(1);
683 write_client_reg(SSICTL, 0x00000799, TRUE);
684 write_client_reg(SSITIME, 0x00000100, TRUE);
685 write_client_reg(SSICTL, 0x0000079b, TRUE);
686 write_client_reg(SSITX, 0x00000000, TRUE);
687 mddi_wait(1);
688 write_client_reg(SSITX, 0x00000000, TRUE);
689 mddi_wait(1);
690 write_client_reg(SSITX, 0x00000000, TRUE);
691 mddi_wait(1);
692 write_client_reg(SSITX, 0x000800BA, TRUE);
693 write_client_reg(SSITX, 0x00000111, TRUE);
694 write_client_reg(SSITX, 0x00080036, TRUE);
695 write_client_reg(SSITX, 0x00000100, TRUE);
696 mddi_wait(2);
697 write_client_reg(SSITX, 0x000800BB, TRUE);
698 write_client_reg(SSITX, 0x00000100, TRUE);
699 write_client_reg(SSITX, 0x0008003A, TRUE);
700 write_client_reg(SSITX, 0x00000160, TRUE);
701 mddi_wait(2);
702 write_client_reg(SSITX, 0x000800BF, TRUE);
703 write_client_reg(SSITX, 0x00000100, TRUE);
704 write_client_reg(SSITX, 0x000800B1, TRUE);
705 write_client_reg(SSITX, 0x0000015D, TRUE);
706 mddi_wait(2);
707 write_client_reg(SSITX, 0x000800B2, TRUE);
708 write_client_reg(SSITX, 0x00000133, TRUE);
709 write_client_reg(SSITX, 0x000800B3, TRUE);
710 write_client_reg(SSITX, 0x00000122, TRUE);
711 mddi_wait(2);
712 write_client_reg(SSITX, 0x000800B4, TRUE);
713 write_client_reg(SSITX, 0x00000102, TRUE);
714 write_client_reg(SSITX, 0x000800B5, TRUE);
715 write_client_reg(SSITX, 0x0000011F, TRUE);
716 mddi_wait(2);
717 write_client_reg(SSITX, 0x000800B6, TRUE);
718 write_client_reg(SSITX, 0x00000128, TRUE);
719 write_client_reg(SSITX, 0x000800B7, TRUE);
720 write_client_reg(SSITX, 0x00000103, TRUE);
721 mddi_wait(2);
722 write_client_reg(SSITX, 0x000800B9, TRUE);
723 write_client_reg(SSITX, 0x00000120, TRUE);
724 write_client_reg(SSITX, 0x000800BD, TRUE);
725 write_client_reg(SSITX, 0x00000102, TRUE);
726 mddi_wait(2);
727 write_client_reg(SSITX, 0x000800BE, TRUE);
728 write_client_reg(SSITX, 0x00000100, TRUE);
729 write_client_reg(SSITX, 0x000800C0, TRUE);
730 write_client_reg(SSITX, 0x00000111, TRUE);
731 mddi_wait(2);
732 write_client_reg(SSITX, 0x000800C1, TRUE);
733 write_client_reg(SSITX, 0x00000111, TRUE);
734 write_client_reg(SSITX, 0x000800C2, TRUE);
735 write_client_reg(SSITX, 0x00000111, TRUE);
736 mddi_wait(2);
737 write_client_reg(SSITX, 0x000800C3, TRUE);
738 write_client_reg(SSITX, 0x0008010A, TRUE);
739 write_client_reg(SSITX, 0x0000010A, TRUE);
740 mddi_wait(2);
741 write_client_reg(SSITX, 0x000800C4, TRUE);
742 write_client_reg(SSITX, 0x00080160, TRUE);
743 write_client_reg(SSITX, 0x00000160, TRUE);
744 mddi_wait(2);
745 write_client_reg(SSITX, 0x000800C5, TRUE);
746 write_client_reg(SSITX, 0x00080160, TRUE);
747 write_client_reg(SSITX, 0x00000160, TRUE);
748 mddi_wait(2);
749 write_client_reg(SSITX, 0x000800C6, TRUE);
750 write_client_reg(SSITX, 0x00080160, TRUE);
751 write_client_reg(SSITX, 0x00000160, TRUE);
752 mddi_wait(2);
753 write_client_reg(SSITX, 0x000800C7, TRUE);
754 write_client_reg(SSITX, 0x00080133, TRUE);
755 write_client_reg(SSITX, 0x00000143, TRUE);
756 mddi_wait(2);
757 write_client_reg(SSITX, 0x000800C8, TRUE);
758 write_client_reg(SSITX, 0x00000144, TRUE);
759 write_client_reg(SSITX, 0x000800C9, TRUE);
760 write_client_reg(SSITX, 0x00000133, TRUE);
761 mddi_wait(2);
762 write_client_reg(SSITX, 0x000800CA, TRUE);
763 write_client_reg(SSITX, 0x00000100, TRUE);
764 mddi_wait(2);
765 write_client_reg(SSITX, 0x000800EC, TRUE);
766 write_client_reg(SSITX, 0x00080102, TRUE);
767 write_client_reg(SSITX, 0x00000118, TRUE);
768 mddi_wait(2);
769 write_client_reg(SSITX, 0x000800CF, TRUE);
770 write_client_reg(SSITX, 0x00000101, TRUE);
771 mddi_wait(2);
772 write_client_reg(SSITX, 0x000800D0, TRUE);
773 write_client_reg(SSITX, 0x00080110, TRUE);
774 write_client_reg(SSITX, 0x00000104, TRUE);
775 mddi_wait(2);
776 write_client_reg(SSITX, 0x000800D1, TRUE);
777 write_client_reg(SSITX, 0x00000101, TRUE);
778 mddi_wait(2);
779 write_client_reg(SSITX, 0x000800D2, TRUE);
780 write_client_reg(SSITX, 0x00080100, TRUE);
781 write_client_reg(SSITX, 0x0000013A, TRUE);
782 mddi_wait(2);
783 write_client_reg(SSITX, 0x000800D3, TRUE);
784 write_client_reg(SSITX, 0x00080100, TRUE);
785 write_client_reg(SSITX, 0x0000013A, TRUE);
786 mddi_wait(2);
787 write_client_reg(SSITX, 0x000800D4, TRUE);
788 write_client_reg(SSITX, 0x00080124, TRUE);
789 write_client_reg(SSITX, 0x0000016E, TRUE);
790 mddi_wait(1);
791 write_client_reg(SSITX, 0x000800D5, TRUE);
792 write_client_reg(SSITX, 0x00000124, TRUE);
793 mddi_wait(2);
794 write_client_reg(SSITX, 0x000800ED, TRUE);
795 write_client_reg(SSITX, 0x00080101, TRUE);
796 write_client_reg(SSITX, 0x0000010A, TRUE);
797 mddi_wait(2);
798 write_client_reg(SSITX, 0x000800D6, TRUE);
799 write_client_reg(SSITX, 0x00000101, TRUE);
800 mddi_wait(2);
801 write_client_reg(SSITX, 0x000800D7, TRUE);
802 write_client_reg(SSITX, 0x00080110, TRUE);
803 write_client_reg(SSITX, 0x0000010A, TRUE);
804 mddi_wait(2);
805 write_client_reg(SSITX, 0x000800D8, TRUE);
806 write_client_reg(SSITX, 0x00000101, TRUE);
807 mddi_wait(2);
808 write_client_reg(SSITX, 0x000800D9, TRUE);
809 write_client_reg(SSITX, 0x00080100, TRUE);
810 write_client_reg(SSITX, 0x00000114, TRUE);
811 mddi_wait(2);
812 write_client_reg(SSITX, 0x000800DE, TRUE);
813 write_client_reg(SSITX, 0x00080100, TRUE);
814 write_client_reg(SSITX, 0x00000114, TRUE);
815 mddi_wait(2);
816 write_client_reg(SSITX, 0x000800DF, TRUE);
817 write_client_reg(SSITX, 0x00080112, TRUE);
818 write_client_reg(SSITX, 0x0000013F, TRUE);
819 mddi_wait(2);
820 write_client_reg(SSITX, 0x000800E0, TRUE);
821 write_client_reg(SSITX, 0x0000010B, TRUE);
822 write_client_reg(SSITX, 0x000800E2, TRUE);
823 write_client_reg(SSITX, 0x00000101, TRUE);
824 mddi_wait(2);
825 write_client_reg(SSITX, 0x000800E3, TRUE);
826 write_client_reg(SSITX, 0x00000136, TRUE);
827 mddi_wait(2);
828 write_client_reg(SSITX, 0x000800E4, TRUE);
829 write_client_reg(SSITX, 0x00080100, TRUE);
830 write_client_reg(SSITX, 0x00000103, TRUE);
831 mddi_wait(2);
832 write_client_reg(SSITX, 0x000800E5, TRUE);
833 write_client_reg(SSITX, 0x00080102, TRUE);
834 write_client_reg(SSITX, 0x00000104, TRUE);
835 mddi_wait(2);
836 write_client_reg(SSITX, 0x000800E6, TRUE);
837 write_client_reg(SSITX, 0x00000103, TRUE);
838 mddi_wait(2);
839 write_client_reg(SSITX, 0x000800E7, TRUE);
840 write_client_reg(SSITX, 0x00080104, TRUE);
841 write_client_reg(SSITX, 0x0000010A, TRUE);
842 mddi_wait(2);
843 write_client_reg(SSITX, 0x000800E8, TRUE);
844 write_client_reg(SSITX, 0x00000104, TRUE);
845 write_client_reg(CLKENB, 0x000001EF, TRUE);
846 write_client_reg(START, 0x00000000, TRUE);
847 write_client_reg(WRSTB, 0x0000003F, TRUE);
848 write_client_reg(RDSTB, 0x00000432, TRUE);
849 write_client_reg(PORT_ENB, 0x00000002, TRUE);
850 write_client_reg(VSYNIF, 0x00000000, TRUE);
851 write_client_reg(ASY_DATA, 0x80000000, TRUE);
852 write_client_reg(ASY_DATB, 0x00000001, TRUE);
853 write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
854 write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
855 mddi_wait(10);
856 write_client_reg(ASY_DATA, 0x80000000, TRUE);
857 write_client_reg(ASY_DATB, 0x80000000, TRUE);
858 write_client_reg(ASY_DATC, 0x80000000, TRUE);
859 write_client_reg(ASY_DATD, 0x80000000, TRUE);
860 write_client_reg(ASY_CMDSET, 0x00000009, TRUE);
861 write_client_reg(ASY_CMDSET, 0x00000008, TRUE);
862 write_client_reg(ASY_DATA, 0x80000007, TRUE);
863 write_client_reg(ASY_DATB, 0x00004005, TRUE);
864 write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
865 write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
866 mddi_wait(20);
867 write_client_reg(ASY_DATA, 0x80000059, TRUE);
868 write_client_reg(ASY_DATB, 0x00000000, TRUE);
869 write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
870 write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
871 write_client_reg(VSYNIF, 0x00000001, TRUE);
872 write_client_reg(PORT_ENB, 0x00000001, TRUE);
873 }
874
875 mddi_toshiba_state_transition(TOSHIBA_STATE_PRIM_SEC_STANDBY,
876 TOSHIBA_STATE_PRIM_SEC_READY);
877}
878
879static void toshiba_prim_start(struct msm_fb_data_type *mfd)
880{
881 if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
882 return;
883
884 if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA) {
885 write_client_reg(BITMAP1, 0x01E000F0, TRUE);
886 write_client_reg(BITMAP2, 0x01E000F0, TRUE);
887 write_client_reg(BITMAP3, 0x01E000F0, TRUE);
888 write_client_reg(BITMAP4, 0x00DC00B0, TRUE);
889 write_client_reg(CLKENB, 0x000001EF, TRUE);
890 write_client_reg(PORT_ENB, 0x00000001, TRUE);
891 write_client_reg(PORT, 0x00000016, TRUE);
892 write_client_reg(PXL, 0x00000002, TRUE);
893 write_client_reg(MPLFBUF, 0x00000000, TRUE);
894 write_client_reg(HCYCLE, 0x00000185, TRUE);
895 write_client_reg(HSW, 0x00000018, TRUE);
896 write_client_reg(HDE_START, 0x0000004A, TRUE);
897 write_client_reg(HDE_SIZE, 0x000000EF, TRUE);
898 write_client_reg(VCYCLE, 0x0000028E, TRUE);
899 write_client_reg(VSW, 0x00000004, TRUE);
900 write_client_reg(VDE_START, 0x00000009, TRUE);
901 write_client_reg(VDE_SIZE, 0x0000027F, TRUE);
902 write_client_reg(START, 0x00000001, TRUE);
903 write_client_reg(SYSTEM_BLOCK1_BASE, 0x00000002, TRUE);
904 } else{
905
906 write_client_reg(VSYNIF, 0x00000001, TRUE);
907 write_client_reg(PORT_ENB, 0x00000001, TRUE);
908 write_client_reg(BITMAP1, 0x01E000F0, TRUE);
909 write_client_reg(BITMAP2, 0x01E000F0, TRUE);
910 write_client_reg(BITMAP3, 0x01E000F0, TRUE);
911 write_client_reg(BITMAP4, 0x00DC00B0, TRUE);
912 write_client_reg(CLKENB, 0x000001EF, TRUE);
913 write_client_reg(PORT_ENB, 0x00000001, TRUE);
914 write_client_reg(PORT, 0x00000004, TRUE);
915 write_client_reg(PXL, 0x00000002, TRUE);
916 write_client_reg(MPLFBUF, 0x00000000, TRUE);
917
918 if (mddi_toshiba_61Hz_refresh) {
919 write_client_reg(HCYCLE, 0x000000FC, TRUE);
920 mddi_toshiba_rows_per_second = 39526;
921 mddi_toshiba_rows_per_refresh = 646;
922 mddi_toshiba_usecs_per_refresh = 16344;
923 } else {
924 write_client_reg(HCYCLE, 0x0000010b, TRUE);
925 mddi_toshiba_rows_per_second = 37313;
926 mddi_toshiba_rows_per_refresh = 646;
927 mddi_toshiba_usecs_per_refresh = 17313;
928 }
929
930 write_client_reg(HSW, 0x00000003, TRUE);
931 write_client_reg(HDE_START, 0x00000007, TRUE);
932 write_client_reg(HDE_SIZE, 0x000000EF, TRUE);
933 write_client_reg(VCYCLE, 0x00000285, TRUE);
934 write_client_reg(VSW, 0x00000001, TRUE);
935 write_client_reg(VDE_START, 0x00000003, TRUE);
936 write_client_reg(VDE_SIZE, 0x0000027F, TRUE);
937 write_client_reg(START, 0x00000001, TRUE);
938 mddi_wait(10);
939 write_client_reg(SSITX, 0x000800BC, TRUE);
940 write_client_reg(SSITX, 0x00000180, TRUE);
941 write_client_reg(SSITX, 0x0008003B, TRUE);
942 write_client_reg(SSITX, 0x00000100, TRUE);
943 mddi_wait(1);
944 write_client_reg(SSITX, 0x000800B0, TRUE);
945 write_client_reg(SSITX, 0x00000116, TRUE);
946 mddi_wait(1);
947 write_client_reg(SSITX, 0x000800B8, TRUE);
948 write_client_reg(SSITX, 0x000801FF, TRUE);
949 write_client_reg(SSITX, 0x000001F5, TRUE);
950 mddi_wait(1);
951 write_client_reg(SSITX, 0x00000011, TRUE);
952 write_client_reg(SSITX, 0x00000029, TRUE);
953 write_client_reg(WKREQ, 0x00000000, TRUE);
954 write_client_reg(WAKEUP, 0x00000000, TRUE);
955 write_client_reg(INTMSK, 0x00000001, TRUE);
956 }
957
958 mddi_toshiba_state_transition(TOSHIBA_STATE_PRIM_SEC_READY,
959 TOSHIBA_STATE_PRIM_NORMAL_MODE);
960}
961
962static void toshiba_sec_start(struct msm_fb_data_type *mfd)
963{
964 if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
965 return;
966
967 write_client_reg(VSYNIF, 0x00000000, TRUE);
968 write_client_reg(PORT_ENB, 0x00000002, TRUE);
969 write_client_reg(CLKENB, 0x000011EF, TRUE);
970 write_client_reg(BITMAP0, 0x028001E0, TRUE);
971 write_client_reg(BITMAP1, 0x00000000, TRUE);
972 write_client_reg(BITMAP2, 0x00000000, TRUE);
973 write_client_reg(BITMAP3, 0x00000000, TRUE);
974 write_client_reg(BITMAP4, 0x00DC00B0, TRUE);
975 write_client_reg(PORT, 0x00000000, TRUE);
976 write_client_reg(PXL, 0x00000000, TRUE);
977 write_client_reg(MPLFBUF, 0x00000004, TRUE);
978 write_client_reg(HCYCLE, 0x0000006B, TRUE);
979 write_client_reg(HSW, 0x00000003, TRUE);
980 write_client_reg(HDE_START, 0x00000007, TRUE);
981 write_client_reg(HDE_SIZE, 0x00000057, TRUE);
982 write_client_reg(VCYCLE, 0x000000E6, TRUE);
983 write_client_reg(VSW, 0x00000001, TRUE);
984 write_client_reg(VDE_START, 0x00000003, TRUE);
985 write_client_reg(VDE_SIZE, 0x000000DB, TRUE);
986 write_client_reg(ASY_DATA, 0x80000001, TRUE);
987 write_client_reg(ASY_DATB, 0x0000011B, TRUE);
988 write_client_reg(ASY_DATC, 0x80000002, TRUE);
989 write_client_reg(ASY_DATD, 0x00000700, TRUE);
990 write_client_reg(ASY_DATE, 0x80000003, TRUE);
991 write_client_reg(ASY_DATF, 0x00000230, TRUE);
992 write_client_reg(ASY_DATG, 0x80000008, TRUE);
993 write_client_reg(ASY_DATH, 0x00000402, TRUE);
994 write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
995 write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
996 write_client_reg(ASY_DATA, 0x80000009, TRUE);
997 write_client_reg(ASY_DATB, 0x00000000, TRUE);
998 write_client_reg(ASY_DATC, 0x8000000B, TRUE);
999 write_client_reg(ASY_DATD, 0x00000000, TRUE);
1000 write_client_reg(ASY_DATE, 0x8000000C, TRUE);
1001 write_client_reg(ASY_DATF, 0x00000000, TRUE);
1002 write_client_reg(ASY_DATG, 0x8000000D, TRUE);
1003 write_client_reg(ASY_DATH, 0x00000409, TRUE);
1004 write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
1005 write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
1006 write_client_reg(ASY_DATA, 0x8000000E, TRUE);
1007 write_client_reg(ASY_DATB, 0x00000409, TRUE);
1008 write_client_reg(ASY_DATC, 0x80000030, TRUE);
1009 write_client_reg(ASY_DATD, 0x00000000, TRUE);
1010 write_client_reg(ASY_DATE, 0x80000031, TRUE);
1011 write_client_reg(ASY_DATF, 0x00000100, TRUE);
1012 write_client_reg(ASY_DATG, 0x80000032, TRUE);
1013 write_client_reg(ASY_DATH, 0x00000104, TRUE);
1014 write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
1015 write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
1016 write_client_reg(ASY_DATA, 0x80000033, TRUE);
1017 write_client_reg(ASY_DATB, 0x00000400, TRUE);
1018 write_client_reg(ASY_DATC, 0x80000034, TRUE);
1019 write_client_reg(ASY_DATD, 0x00000306, TRUE);
1020 write_client_reg(ASY_DATE, 0x80000035, TRUE);
1021 write_client_reg(ASY_DATF, 0x00000706, TRUE);
1022 write_client_reg(ASY_DATG, 0x80000036, TRUE);
1023 write_client_reg(ASY_DATH, 0x00000707, TRUE);
1024 write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
1025 write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
1026 write_client_reg(ASY_DATA, 0x80000037, TRUE);
1027 write_client_reg(ASY_DATB, 0x00000004, TRUE);
1028 write_client_reg(ASY_DATC, 0x80000038, TRUE);
1029 write_client_reg(ASY_DATD, 0x00000000, TRUE);
1030 write_client_reg(ASY_DATE, 0x80000039, TRUE);
1031 write_client_reg(ASY_DATF, 0x00000000, TRUE);
1032 write_client_reg(ASY_DATG, 0x8000003A, TRUE);
1033 write_client_reg(ASY_DATH, 0x00000001, TRUE);
1034 write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
1035 write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
1036 write_client_reg(ASY_DATA, 0x80000044, TRUE);
1037 write_client_reg(ASY_DATB, 0x0000AF00, TRUE);
1038 write_client_reg(ASY_DATC, 0x80000045, TRUE);
1039 write_client_reg(ASY_DATD, 0x0000DB00, TRUE);
1040 write_client_reg(ASY_DATE, 0x08000042, TRUE);
1041 write_client_reg(ASY_DATF, 0x0000DB00, TRUE);
1042 write_client_reg(ASY_DATG, 0x80000021, TRUE);
1043 write_client_reg(ASY_DATH, 0x00000000, TRUE);
1044 write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
1045 write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
1046 write_client_reg(PXL, 0x0000000C, TRUE);
1047 write_client_reg(VSYNIF, 0x00000001, TRUE);
1048 write_client_reg(ASY_DATA, 0x80000022, TRUE);
1049 write_client_reg(ASY_CMDSET, 0x00000003, TRUE);
1050 write_client_reg(START, 0x00000001, TRUE);
1051 mddi_wait(60);
1052 write_client_reg(PXL, 0x00000000, TRUE);
1053 write_client_reg(VSYNIF, 0x00000000, TRUE);
1054 write_client_reg(START, 0x00000000, TRUE);
1055 write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
1056 write_client_reg(ASY_DATA, 0x80000050, TRUE);
1057 write_client_reg(ASY_DATB, 0x00000000, TRUE);
1058 write_client_reg(ASY_DATC, 0x80000051, TRUE);
1059 write_client_reg(ASY_DATD, 0x00000E00, TRUE);
1060 write_client_reg(ASY_DATE, 0x80000052, TRUE);
1061 write_client_reg(ASY_DATF, 0x00000D01, TRUE);
1062 write_client_reg(ASY_DATG, 0x80000053, TRUE);
1063 write_client_reg(ASY_DATH, 0x00000000, TRUE);
1064 write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
1065 write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
1066 write_client_reg(ASY_DATA, 0x80000058, TRUE);
1067 write_client_reg(ASY_DATB, 0x00000000, TRUE);
1068 write_client_reg(ASY_DATC, 0x8000005A, TRUE);
1069 write_client_reg(ASY_DATD, 0x00000E01, TRUE);
1070 write_client_reg(ASY_CMDSET, 0x00000009, TRUE);
1071 write_client_reg(ASY_CMDSET, 0x00000008, TRUE);
1072 write_client_reg(ASY_DATA, 0x80000011, TRUE);
1073 write_client_reg(ASY_DATB, 0x00000812, TRUE);
1074 write_client_reg(ASY_DATC, 0x80000012, TRUE);
1075 write_client_reg(ASY_DATD, 0x00000003, TRUE);
1076 write_client_reg(ASY_DATE, 0x80000013, TRUE);
1077 write_client_reg(ASY_DATF, 0x00000909, TRUE);
1078 write_client_reg(ASY_DATG, 0x80000010, TRUE);
1079 write_client_reg(ASY_DATH, 0x00000040, TRUE);
1080 write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
1081 write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
1082 mddi_wait(40);
1083 write_client_reg(ASY_DATA, 0x80000010, TRUE);
1084 write_client_reg(ASY_DATB, 0x00000340, TRUE);
1085 write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
1086 write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
1087 mddi_wait(60);
1088 write_client_reg(ASY_DATA, 0x80000010, TRUE);
1089 write_client_reg(ASY_DATB, 0x00003340, TRUE);
1090 write_client_reg(ASY_DATC, 0x80000007, TRUE);
1091 write_client_reg(ASY_DATD, 0x00004007, TRUE);
1092 write_client_reg(ASY_CMDSET, 0x00000009, TRUE);
1093 write_client_reg(ASY_CMDSET, 0x00000008, TRUE);
1094 mddi_wait(1);
1095 write_client_reg(ASY_DATA, 0x80000007, TRUE);
1096 write_client_reg(ASY_DATB, 0x00004017, TRUE);
1097 write_client_reg(ASY_DATC, 0x8000005B, TRUE);
1098 write_client_reg(ASY_DATD, 0x00000000, TRUE);
1099 write_client_reg(ASY_DATE, 0x80000059, TRUE);
1100 write_client_reg(ASY_DATF, 0x00000011, TRUE);
1101 write_client_reg(ASY_CMDSET, 0x0000000D, TRUE);
1102 write_client_reg(ASY_CMDSET, 0x0000000C, TRUE);
1103 mddi_wait(20);
1104 write_client_reg(ASY_DATA, 0x80000059, TRUE);
1105 /* LTPS I/F control */
1106 write_client_reg(ASY_DATB, 0x00000019, TRUE);
1107 /* Direct cmd transfer enable */
1108 write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
1109 /* Direct cmd transfer disable */
1110 write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
1111 mddi_wait(20);
1112 /* Index setting of SUB LCDD */
1113 write_client_reg(ASY_DATA, 0x80000059, TRUE);
1114 /* LTPS I/F control */
1115 write_client_reg(ASY_DATB, 0x00000079, TRUE);
1116 /* Direct cmd transfer enable */
1117 write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
1118 /* Direct cmd transfer disable */
1119 write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
1120 mddi_wait(20);
1121 /* Index setting of SUB LCDD */
1122 write_client_reg(ASY_DATA, 0x80000059, TRUE);
1123 /* LTPS I/F control */
1124 write_client_reg(ASY_DATB, 0x000003FD, TRUE);
1125 /* Direct cmd transfer enable */
1126 write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
1127 /* Direct cmd transfer disable */
1128 write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
1129 mddi_wait(20);
1130 mddi_toshiba_state_transition(TOSHIBA_STATE_PRIM_SEC_READY,
1131 TOSHIBA_STATE_SEC_NORMAL_MODE);
1132}
1133
1134static void toshiba_prim_lcd_off(struct msm_fb_data_type *mfd)
1135{
1136 if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA) {
1137 gordon_disp_off();
1138 } else{
1139
1140 /* Main panel power off (Deep standby in) */
1141 write_client_reg(SSITX, 0x000800BC, TRUE);
1142 write_client_reg(SSITX, 0x00000100, TRUE);
1143 write_client_reg(SSITX, 0x00000028, TRUE);
1144 mddi_wait(1);
1145 write_client_reg(SSITX, 0x000800B8, TRUE);
1146 write_client_reg(SSITX, 0x00000180, TRUE);
1147 write_client_reg(SSITX, 0x00000102, TRUE);
1148 write_client_reg(SSITX, 0x00000010, TRUE);
1149 }
1150 write_client_reg(PORT, 0x00000003, TRUE);
1151 write_client_reg(REGENB, 0x00000001, TRUE);
1152 mddi_wait(1);
1153 write_client_reg(PXL, 0x00000000, TRUE);
1154 write_client_reg(START, 0x00000000, TRUE);
1155 write_client_reg(REGENB, 0x00000001, TRUE);
1156 mddi_wait(3);
1157 if (TM_GET_PID(mfd->panel.id) != LCD_SHARP_2P4_VGA) {
1158 write_client_reg(SSITX, 0x000800B0, TRUE);
1159 write_client_reg(SSITX, 0x00000100, TRUE);
1160 }
1161 mddi_toshiba_state_transition(TOSHIBA_STATE_PRIM_NORMAL_MODE,
1162 TOSHIBA_STATE_PRIM_SEC_STANDBY);
1163}
1164
1165static void toshiba_sec_lcd_off(struct msm_fb_data_type *mfd)
1166{
1167 if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
1168 return;
1169
1170 write_client_reg(VSYNIF, 0x00000000, TRUE);
1171 write_client_reg(PORT_ENB, 0x00000002, TRUE);
1172 write_client_reg(ASY_DATA, 0x80000007, TRUE);
1173 write_client_reg(ASY_DATB, 0x00004016, TRUE);
1174 write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
1175 write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
1176 mddi_wait(2);
1177 write_client_reg(ASY_DATA, 0x80000059, TRUE);
1178 write_client_reg(ASY_DATB, 0x00000019, TRUE);
1179 write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
1180 write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
1181 mddi_wait(2);
1182 write_client_reg(ASY_DATA, 0x80000059, TRUE);
1183 write_client_reg(ASY_DATB, 0x0000000B, TRUE);
1184 write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
1185 write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
1186 mddi_wait(2);
1187 write_client_reg(ASY_DATA, 0x80000059, TRUE);
1188 write_client_reg(ASY_DATB, 0x00000002, TRUE);
1189 write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
1190 write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
1191 mddi_wait(4);
1192 write_client_reg(ASY_DATA, 0x80000010, TRUE);
1193 write_client_reg(ASY_DATB, 0x00000300, TRUE);
1194 write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
1195 write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
1196 mddi_wait(4);
1197 write_client_reg(ASY_DATA, 0x80000059, TRUE);
1198 write_client_reg(ASY_DATB, 0x00000000, TRUE);
1199 write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
1200 write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
1201 mddi_wait(2);
1202 write_client_reg(ASY_DATA, 0x80000007, TRUE);
1203 write_client_reg(ASY_DATB, 0x00004004, TRUE);
1204 write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
1205 write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
1206 mddi_wait(2);
1207 write_client_reg(PORT, 0x00000000, TRUE);
1208 write_client_reg(PXL, 0x00000000, TRUE);
1209 write_client_reg(START, 0x00000000, TRUE);
1210 write_client_reg(VSYNIF, 0x00000001, TRUE);
1211 write_client_reg(PORT_ENB, 0x00000001, TRUE);
1212 write_client_reg(REGENB, 0x00000001, TRUE);
1213 mddi_toshiba_state_transition(TOSHIBA_STATE_SEC_NORMAL_MODE,
1214 TOSHIBA_STATE_PRIM_SEC_STANDBY);
1215}
1216
1217static void toshiba_sec_cont_update_start(struct msm_fb_data_type *mfd)
1218{
1219
1220 if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
1221 return;
1222
1223 write_client_reg(VSYNIF, 0x00000000, TRUE);
1224 write_client_reg(PORT_ENB, 0x00000002, TRUE);
1225 write_client_reg(INTMASK, 0x00000001, TRUE);
1226 write_client_reg(TTBUSSEL, 0x0000000B, TRUE);
1227 write_client_reg(MONI, 0x00000008, TRUE);
1228 write_client_reg(CLKENB, 0x000000EF, TRUE);
1229 write_client_reg(CLKENB, 0x000010EF, TRUE);
1230 write_client_reg(CLKENB, 0x000011EF, TRUE);
1231 write_client_reg(BITMAP4, 0x00DC00B0, TRUE);
1232 write_client_reg(HCYCLE, 0x0000006B, TRUE);
1233 write_client_reg(HSW, 0x00000003, TRUE);
1234 write_client_reg(HDE_START, 0x00000002, TRUE);
1235 write_client_reg(HDE_SIZE, 0x00000057, TRUE);
1236 write_client_reg(VCYCLE, 0x000000E6, TRUE);
1237 write_client_reg(VSW, 0x00000001, TRUE);
1238 write_client_reg(VDE_START, 0x00000003, TRUE);
1239 write_client_reg(VDE_SIZE, 0x000000DB, TRUE);
1240 write_client_reg(WRSTB, 0x00000015, TRUE);
1241 write_client_reg(MPLFBUF, 0x00000004, TRUE);
1242 write_client_reg(ASY_DATA, 0x80000021, TRUE);
1243 write_client_reg(ASY_DATB, 0x00000000, TRUE);
1244 write_client_reg(ASY_DATC, 0x80000022, TRUE);
1245 write_client_reg(ASY_CMDSET, 0x00000007, TRUE);
1246 write_client_reg(PXL, 0x00000089, TRUE);
1247 write_client_reg(VSYNIF, 0x00000001, TRUE);
1248 mddi_wait(2);
1249}
1250
1251static void toshiba_sec_cont_update_stop(struct msm_fb_data_type *mfd)
1252{
1253 if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
1254 return;
1255
1256 write_client_reg(PXL, 0x00000000, TRUE);
1257 write_client_reg(VSYNIF, 0x00000000, TRUE);
1258 write_client_reg(START, 0x00000000, TRUE);
1259 write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
1260 mddi_wait(3);
1261 write_client_reg(SRST, 0x00000002, TRUE);
1262 mddi_wait(3);
1263 write_client_reg(SRST, 0x00000003, TRUE);
1264}
1265
1266static void toshiba_sec_backlight_on(struct msm_fb_data_type *mfd)
1267{
1268 if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
1269 return;
1270
1271 write_client_reg(TIMER0CTRL, 0x00000060, TRUE);
1272 write_client_reg(TIMER0LOAD, 0x00001388, TRUE);
1273 write_client_reg(PWM0OFF, 0x00000001, TRUE);
1274 write_client_reg(TIMER1CTRL, 0x00000060, TRUE);
1275 write_client_reg(TIMER1LOAD, 0x00001388, TRUE);
1276 write_client_reg(PWM1OFF, 0x00001387, TRUE);
1277 write_client_reg(TIMER0CTRL, 0x000000E0, TRUE);
1278 write_client_reg(TIMER1CTRL, 0x000000E0, TRUE);
1279 write_client_reg(PWMCR, 0x00000003, TRUE);
1280}
1281
1282static void toshiba_sec_sleep_in(struct msm_fb_data_type *mfd)
1283{
1284 if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
1285 return;
1286
1287 write_client_reg(VSYNIF, 0x00000000, TRUE);
1288 write_client_reg(PORT_ENB, 0x00000002, TRUE);
1289 write_client_reg(ASY_DATA, 0x80000007, TRUE);
1290 write_client_reg(ASY_DATB, 0x00004016, TRUE);
1291 write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
1292 write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
1293 mddi_wait(2);
1294 write_client_reg(ASY_DATA, 0x80000059, TRUE);
1295 write_client_reg(ASY_DATB, 0x00000019, TRUE);
1296 write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
1297 write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
1298 mddi_wait(2);
1299 write_client_reg(ASY_DATA, 0x80000059, TRUE);
1300 write_client_reg(ASY_DATB, 0x0000000B, TRUE);
1301 write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
1302 write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
1303 mddi_wait(2);
1304 write_client_reg(ASY_DATA, 0x80000059, TRUE);
1305 write_client_reg(ASY_DATB, 0x00000002, TRUE);
1306 write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
1307 write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
1308 mddi_wait(4);
1309 write_client_reg(ASY_DATA, 0x80000010, TRUE);
1310 write_client_reg(ASY_DATB, 0x00000300, TRUE);
1311 write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
1312 write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
1313 mddi_wait(4);
1314 write_client_reg(ASY_DATA, 0x80000059, TRUE);
1315 write_client_reg(ASY_DATB, 0x00000000, TRUE);
1316 write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
1317 write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
1318 mddi_wait(2);
1319 write_client_reg(ASY_DATA, 0x80000007, TRUE);
1320 write_client_reg(ASY_DATB, 0x00004004, TRUE);
1321 write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
1322 write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
1323 mddi_wait(2);
1324 write_client_reg(PORT, 0x00000000, TRUE);
1325 write_client_reg(PXL, 0x00000000, TRUE);
1326 write_client_reg(START, 0x00000000, TRUE);
1327 write_client_reg(REGENB, 0x00000001, TRUE);
1328 /* Sleep in sequence */
1329 write_client_reg(ASY_DATA, 0x80000010, TRUE);
1330 write_client_reg(ASY_DATB, 0x00000302, TRUE);
1331 write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
1332 write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
1333}
1334
1335static void toshiba_sec_sleep_out(struct msm_fb_data_type *mfd)
1336{
1337 if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
1338 return;
1339
1340 write_client_reg(VSYNIF, 0x00000000, TRUE);
1341 write_client_reg(PORT_ENB, 0x00000002, TRUE);
1342 write_client_reg(ASY_DATA, 0x80000010, TRUE);
1343 write_client_reg(ASY_DATB, 0x00000300, TRUE);
1344 write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
1345 write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
1346 /* Display ON sequence */
1347 write_client_reg(ASY_DATA, 0x80000011, TRUE);
1348 write_client_reg(ASY_DATB, 0x00000812, TRUE);
1349 write_client_reg(ASY_DATC, 0x80000012, TRUE);
1350 write_client_reg(ASY_DATD, 0x00000003, TRUE);
1351 write_client_reg(ASY_DATE, 0x80000013, TRUE);
1352 write_client_reg(ASY_DATF, 0x00000909, TRUE);
1353 write_client_reg(ASY_DATG, 0x80000010, TRUE);
1354 write_client_reg(ASY_DATH, 0x00000040, TRUE);
1355 write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
1356 write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
1357 mddi_wait(4);
1358 write_client_reg(ASY_DATA, 0x80000010, TRUE);
1359 write_client_reg(ASY_DATB, 0x00000340, TRUE);
1360 write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
1361 write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
1362 mddi_wait(6);
1363 write_client_reg(ASY_DATA, 0x80000010, TRUE);
1364 write_client_reg(ASY_DATB, 0x00003340, TRUE);
1365 write_client_reg(ASY_DATC, 0x80000007, TRUE);
1366 write_client_reg(ASY_DATD, 0x00004007, TRUE);
1367 write_client_reg(ASY_CMDSET, 0x00000009, TRUE);
1368 write_client_reg(ASY_CMDSET, 0x00000008, TRUE);
1369 mddi_wait(1);
1370 write_client_reg(ASY_DATA, 0x80000007, TRUE);
1371 write_client_reg(ASY_DATB, 0x00004017, TRUE);
1372 write_client_reg(ASY_DATC, 0x8000005B, TRUE);
1373 write_client_reg(ASY_DATD, 0x00000000, TRUE);
1374 write_client_reg(ASY_DATE, 0x80000059, TRUE);
1375 write_client_reg(ASY_DATF, 0x00000011, TRUE);
1376 write_client_reg(ASY_CMDSET, 0x0000000D, TRUE);
1377 write_client_reg(ASY_CMDSET, 0x0000000C, TRUE);
1378 mddi_wait(2);
1379 write_client_reg(ASY_DATA, 0x80000059, TRUE);
1380 write_client_reg(ASY_DATB, 0x00000019, TRUE);
1381 write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
1382 write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
1383 mddi_wait(2);
1384 write_client_reg(ASY_DATA, 0x80000059, TRUE);
1385 write_client_reg(ASY_DATB, 0x00000079, TRUE);
1386 write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
1387 write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
1388 mddi_wait(2);
1389 write_client_reg(ASY_DATA, 0x80000059, TRUE);
1390 write_client_reg(ASY_DATB, 0x000003FD, TRUE);
1391 write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
1392 write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
1393 mddi_wait(2);
1394}
1395
1396static void mddi_toshiba_lcd_set_backlight(struct msm_fb_data_type *mfd)
1397{
1398 int32 level;
1399 int ret = -EPERM;
1400 int max = mfd->panel_info.bl_max;
1401 int min = mfd->panel_info.bl_min;
1402
1403 if (mddi_toshiba_pdata && mddi_toshiba_pdata->pmic_backlight) {
1404 ret = mddi_toshiba_pdata->pmic_backlight(mfd->bl_level);
1405 if (!ret)
1406 return;
1407 }
1408
1409 if (ret && mddi_toshiba_pdata && mddi_toshiba_pdata->backlight_level) {
1410 level = mddi_toshiba_pdata->backlight_level(mfd->bl_level,
1411 max, min);
1412
1413 if (level < 0)
1414 return;
1415
1416 if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA)
1417 write_client_reg(TIMER0LOAD, 0x00001388, TRUE);
1418 } else {
1419 if (!max)
1420 level = 0;
1421 else
1422 level = (mfd->bl_level * 4999) / max;
1423 }
1424
1425 write_client_reg(PWM0OFF, level, TRUE);
1426}
1427
1428static void mddi_toshiba_vsync_set_handler(msm_fb_vsync_handler_type handler, /* ISR to be executed */
1429 void *arg)
1430{
1431 boolean error = FALSE;
1432 unsigned long flags;
1433
1434 /* Disable interrupts */
1435 spin_lock_irqsave(&mddi_host_spin_lock, flags);
1436 /* INTLOCK(); */
1437
1438 if (mddi_toshiba_vsync_handler != NULL) {
1439 error = TRUE;
1440 } else {
1441 /* Register the handler for this particular GROUP interrupt source */
1442 mddi_toshiba_vsync_handler = handler;
1443 mddi_toshiba_vsync_handler_arg = arg;
1444 }
1445
1446 /* Restore interrupts */
1447 spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
1448 /* MDDI_INTFREE(); */
1449 if (error) {
1450 MDDI_MSG_ERR("MDDI: Previous Vsync handler never called\n");
1451 } else {
1452 /* Enable the vsync wakeup */
1453 mddi_queue_register_write(INTMSK, 0x0000, FALSE, 0);
1454
1455 mddi_toshiba_vsync_attempts = 1;
1456 mddi_vsync_detect_enabled = TRUE;
1457 }
1458} /* mddi_toshiba_vsync_set_handler */
1459
1460static void mddi_toshiba_lcd_vsync_detected(boolean detected)
1461{
1462 /* static timetick_type start_time = 0; */
1463 static struct timeval start_time;
1464 static boolean first_time = TRUE;
1465 /* uint32 mdp_cnt_val = 0; */
1466 /* timetick_type elapsed_us; */
1467 struct timeval now;
1468 uint32 elapsed_us;
1469 uint32 num_vsyncs;
1470
1471 if ((detected) || (mddi_toshiba_vsync_attempts > 5)) {
1472 if ((detected) && (mddi_toshiba_monitor_refresh_value)) {
1473 /* if (start_time != 0) */
1474 if (!first_time) {
1475 jiffies_to_timeval(jiffies, &now);
1476 elapsed_us =
1477 (now.tv_sec - start_time.tv_sec) * 1000000 +
1478 now.tv_usec - start_time.tv_usec;
1479 /*
1480 * LCD is configured for a refresh every usecs,
1481 * so to determine the number of vsyncs that
1482 * have occurred since the last measurement
1483 * add half that to the time difference and
1484 * divide by the refresh rate.
1485 */
1486 num_vsyncs = (elapsed_us +
1487 (mddi_toshiba_usecs_per_refresh >>
1488 1)) /
1489 mddi_toshiba_usecs_per_refresh;
1490 /*
1491 * LCD is configured for * hsyncs (rows) per
1492 * refresh cycle. Calculate new rows_per_second
1493 * value based upon these new measurements.
1494 * MDP can update with this new value.
1495 */
1496 mddi_toshiba_rows_per_second =
1497 (mddi_toshiba_rows_per_refresh * 1000 *
1498 num_vsyncs) / (elapsed_us / 1000);
1499 }
1500 /* start_time = timetick_get(); */
1501 first_time = FALSE;
1502 jiffies_to_timeval(jiffies, &start_time);
1503 if (mddi_toshiba_report_refresh_measurements) {
1504 (void)mddi_queue_register_read_int(VPOS,
1505 &mddi_toshiba_curr_vpos);
1506 /* mdp_cnt_val = MDP_LINE_COUNT; */
1507 }
1508 }
1509 /* if detected = TRUE, client initiated wakeup was detected */
1510 if (mddi_toshiba_vsync_handler != NULL) {
1511 (*mddi_toshiba_vsync_handler)
1512 (mddi_toshiba_vsync_handler_arg);
1513 mddi_toshiba_vsync_handler = NULL;
1514 }
1515 mddi_vsync_detect_enabled = FALSE;
1516 mddi_toshiba_vsync_attempts = 0;
1517 /* need to disable the interrupt wakeup */
1518 if (!mddi_queue_register_write_int(INTMSK, 0x0001))
1519 MDDI_MSG_ERR("Vsync interrupt disable failed!\n");
1520 if (!detected) {
1521 /* give up after 5 failed attempts but show error */
1522 MDDI_MSG_NOTICE("Vsync detection failed!\n");
1523 } else if ((mddi_toshiba_monitor_refresh_value) &&
1524 (mddi_toshiba_report_refresh_measurements)) {
1525 MDDI_MSG_NOTICE(" Last Line Counter=%d!\n",
1526 mddi_toshiba_curr_vpos);
1527 /* MDDI_MSG_NOTICE(" MDP Line Counter=%d!\n",mdp_cnt_val); */
1528 MDDI_MSG_NOTICE(" Lines Per Second=%d!\n",
1529 mddi_toshiba_rows_per_second);
1530 }
1531 /* clear the interrupt */
1532 if (!mddi_queue_register_write_int(INTFLG, 0x0001))
1533 MDDI_MSG_ERR("Vsync interrupt clear failed!\n");
1534 } else {
1535 /* if detected = FALSE, we woke up from hibernation, but did not
1536 * detect client initiated wakeup.
1537 */
1538 mddi_toshiba_vsync_attempts++;
1539 }
1540}
1541
1542static void mddi_toshiba_prim_init(struct msm_fb_data_type *mfd)
1543{
1544
1545 switch (toshiba_state) {
1546 case TOSHIBA_STATE_PRIM_SEC_READY:
1547 break;
1548 case TOSHIBA_STATE_OFF:
1549 toshiba_state = TOSHIBA_STATE_PRIM_SEC_STANDBY;
1550 toshiba_common_initial_setup(mfd);
1551 break;
1552 case TOSHIBA_STATE_PRIM_SEC_STANDBY:
1553 toshiba_common_initial_setup(mfd);
1554 break;
1555 case TOSHIBA_STATE_SEC_NORMAL_MODE:
1556 toshiba_sec_cont_update_stop(mfd);
1557 toshiba_sec_sleep_in(mfd);
1558 toshiba_sec_sleep_out(mfd);
1559 toshiba_sec_lcd_off(mfd);
1560 toshiba_common_initial_setup(mfd);
1561 break;
1562 default:
1563 MDDI_MSG_ERR("mddi_toshiba_prim_init from state %d\n",
1564 toshiba_state);
1565 }
1566
1567 toshiba_prim_start(mfd);
1568 if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA)
1569 gordon_disp_init();
1570 mddi_host_write_pix_attr_reg(0x00C3);
1571}
1572
1573static void mddi_toshiba_sec_init(struct msm_fb_data_type *mfd)
1574{
1575
1576 switch (toshiba_state) {
1577 case TOSHIBA_STATE_PRIM_SEC_READY:
1578 break;
1579 case TOSHIBA_STATE_PRIM_SEC_STANDBY:
1580 toshiba_common_initial_setup(mfd);
1581 break;
1582 case TOSHIBA_STATE_PRIM_NORMAL_MODE:
1583 toshiba_prim_lcd_off(mfd);
1584 toshiba_common_initial_setup(mfd);
1585 break;
1586 default:
1587 MDDI_MSG_ERR("mddi_toshiba_sec_init from state %d\n",
1588 toshiba_state);
1589 }
1590
1591 toshiba_sec_start(mfd);
1592 toshiba_sec_backlight_on(mfd);
1593 toshiba_sec_cont_update_start(mfd);
1594 mddi_host_write_pix_attr_reg(0x0400);
1595}
1596
1597static void mddi_toshiba_lcd_powerdown(struct msm_fb_data_type *mfd)
1598{
1599 switch (toshiba_state) {
1600 case TOSHIBA_STATE_PRIM_SEC_READY:
1601 mddi_toshiba_prim_init(mfd);
1602 mddi_toshiba_lcd_powerdown(mfd);
1603 return;
1604 case TOSHIBA_STATE_PRIM_SEC_STANDBY:
1605 break;
1606 case TOSHIBA_STATE_PRIM_NORMAL_MODE:
1607 toshiba_prim_lcd_off(mfd);
1608 break;
1609 case TOSHIBA_STATE_SEC_NORMAL_MODE:
1610 toshiba_sec_cont_update_stop(mfd);
1611 toshiba_sec_sleep_in(mfd);
1612 toshiba_sec_sleep_out(mfd);
1613 toshiba_sec_lcd_off(mfd);
1614 break;
1615 default:
1616 MDDI_MSG_ERR("mddi_toshiba_lcd_powerdown from state %d\n",
1617 toshiba_state);
1618 }
1619}
1620
1621static int mddi_sharpgordon_firsttime = 1;
1622
1623static int mddi_toshiba_lcd_on(struct platform_device *pdev)
1624{
1625 struct msm_fb_data_type *mfd;
1626 mfd = platform_get_drvdata(pdev);
1627 if (!mfd)
1628 return -ENODEV;
1629 if (mfd->key != MFD_KEY)
1630 return -EINVAL;
1631
1632 if (TM_GET_DID(mfd->panel.id) == TOSHIBA_VGA_PRIM)
1633 mddi_toshiba_prim_init(mfd);
1634 else
1635 mddi_toshiba_sec_init(mfd);
1636 if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA) {
1637 if (mddi_sharpgordon_firsttime) {
1638 mddi_sharpgordon_firsttime = 0;
1639 write_client_reg(REGENB, 0x00000001, TRUE);
1640 }
1641 }
1642 return 0;
1643}
1644
1645static int mddi_toshiba_lcd_off(struct platform_device *pdev)
1646{
1647 mddi_toshiba_lcd_powerdown(platform_get_drvdata(pdev));
1648 return 0;
1649}
1650
1651static int __init mddi_toshiba_lcd_probe(struct platform_device *pdev)
1652{
1653 if (pdev->id == 0) {
1654 mddi_toshiba_pdata = pdev->dev.platform_data;
1655 return 0;
1656 }
1657
1658 msm_fb_add_device(pdev);
1659
1660 return 0;
1661}
1662
1663static struct platform_driver this_driver = {
1664 .probe = mddi_toshiba_lcd_probe,
1665 .driver = {
1666 .name = "mddi_toshiba",
1667 },
1668};
1669
1670static struct msm_fb_panel_data toshiba_panel_data = {
1671 .on = mddi_toshiba_lcd_on,
1672 .off = mddi_toshiba_lcd_off,
1673};
1674
1675static int ch_used[3];
1676
1677int mddi_toshiba_device_register(struct msm_panel_info *pinfo,
1678 u32 channel, u32 panel)
1679{
1680 struct platform_device *pdev = NULL;
1681 int ret;
1682
1683 if ((channel >= 3) || ch_used[channel])
1684 return -ENODEV;
1685
1686 if ((channel != TOSHIBA_VGA_PRIM) &&
1687 mddi_toshiba_pdata && mddi_toshiba_pdata->panel_num)
1688 if (mddi_toshiba_pdata->panel_num() < 2)
1689 return -ENODEV;
1690
1691 ch_used[channel] = TRUE;
1692
1693 pdev = platform_device_alloc("mddi_toshiba", (panel << 8)|channel);
1694 if (!pdev)
1695 return -ENOMEM;
1696
1697 if (channel == TOSHIBA_VGA_PRIM) {
1698 toshiba_panel_data.set_backlight =
1699 mddi_toshiba_lcd_set_backlight;
1700
1701 if (pinfo->lcd.vsync_enable) {
1702 toshiba_panel_data.set_vsync_notifier =
1703 mddi_toshiba_vsync_set_handler;
1704 mddi_lcd.vsync_detected =
1705 mddi_toshiba_lcd_vsync_detected;
1706 }
1707 } else {
1708 toshiba_panel_data.set_backlight = NULL;
1709 toshiba_panel_data.set_vsync_notifier = NULL;
1710 }
1711
1712 toshiba_panel_data.panel_info = *pinfo;
1713
1714 ret = platform_device_add_data(pdev, &toshiba_panel_data,
1715 sizeof(toshiba_panel_data));
1716 if (ret) {
1717 printk(KERN_ERR
1718 "%s: platform_device_add_data failed!\n", __func__);
1719 goto err_device_put;
1720 }
1721
1722 ret = platform_device_add(pdev);
1723 if (ret) {
1724 printk(KERN_ERR
1725 "%s: platform_device_register failed!\n", __func__);
1726 goto err_device_put;
1727 }
1728
1729 return 0;
1730
1731err_device_put:
1732 platform_device_put(pdev);
1733 return ret;
1734}
1735
1736static int __init mddi_toshiba_lcd_init(void)
1737{
1738 return platform_driver_register(&this_driver);
1739}
1740
1741module_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
index 000000000000..2d22b9a2c413
--- /dev/null
+++ b/drivers/staging/msm/mddi_toshiba.h
@@ -0,0 +1,52 @@
1/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are met:
5 * * Redistributions of source code must retain the above copyright
6 * notice, this list of conditions and the following disclaimer.
7 * * Redistributions in binary form must reproduce the above copyright
8 * notice, this list of conditions and the following disclaimer in the
9 * documentation and/or other materials provided with the distribution.
10 * * Neither the name of Code Aurora nor
11 * the names of its contributors may be used to endorse or promote
12 * products derived from this software without specific prior written
13 * permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 */
28
29#ifndef MDDI_TOSHIBA_H
30#define MDDI_TOSHIBA_H
31
32#define TOSHIBA_VGA_PRIM 1
33#define TOSHIBA_VGA_SECD 2
34
35#define LCD_TOSHIBA_2P4_VGA 0
36#define LCD_TOSHIBA_2P4_WVGA 1
37#define LCD_TOSHIBA_2P4_WVGA_PT 2
38#define LCD_SHARP_2P4_VGA 3
39
40#define GPIO_BLOCK_BASE 0x150000
41#define SYSTEM_BLOCK2_BASE 0x170000
42
43#define GPIODIR (GPIO_BLOCK_BASE|0x04)
44#define GPIOSEL (SYSTEM_BLOCK2_BASE|0x00)
45#define GPIOPC (GPIO_BLOCK_BASE|0x28)
46#define GPIODATA (GPIO_BLOCK_BASE|0x00)
47
48#define write_client_reg(__X, __Y, __Z) {\
49 mddi_queue_register_write(__X, __Y, TRUE, 0);\
50}
51
52#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
index 000000000000..7e61d3a5b8f1
--- /dev/null
+++ b/drivers/staging/msm/mddi_toshiba_vga.c
@@ -0,0 +1,136 @@
1/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include "msm_fb.h"
19#include "mddihost.h"
20#include "mddihosti.h"
21#include "mddi_toshiba.h"
22
23static uint32 read_client_reg(uint32 addr)
24{
25 uint32 val;
26 mddi_queue_register_read(addr, &val, TRUE, 0);
27 return val;
28}
29
30static uint32 toshiba_lcd_gpio_read(void)
31{
32 uint32 val;
33
34 write_client_reg(GPIODIR, 0x0000000C, TRUE);
35 write_client_reg(GPIOSEL, 0x00000000, TRUE);
36 write_client_reg(GPIOSEL, 0x00000000, TRUE);
37 write_client_reg(GPIOPC, 0x03CF00C0, TRUE);
38 val = read_client_reg(GPIODATA) & 0x2C0;
39
40 return val;
41}
42
43static u32 mddi_toshiba_panel_detect(void)
44{
45 mddi_host_type host_idx = MDDI_HOST_PRIM;
46 uint32 lcd_gpio;
47 u32 mddi_toshiba_lcd = LCD_TOSHIBA_2P4_VGA;
48
49 /* Toshiba display requires larger drive_lo value */
50 mddi_host_reg_out(DRIVE_LO, 0x0050);
51
52 lcd_gpio = toshiba_lcd_gpio_read();
53 switch (lcd_gpio) {
54 case 0x0080:
55 mddi_toshiba_lcd = LCD_SHARP_2P4_VGA;
56 break;
57
58 case 0x00C0:
59 default:
60 mddi_toshiba_lcd = LCD_TOSHIBA_2P4_VGA;
61 break;
62 }
63
64 return mddi_toshiba_lcd;
65}
66
67static int __init mddi_toshiba_vga_init(void)
68{
69 int ret;
70 struct msm_panel_info pinfo;
71 u32 panel;
72
73#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
74 u32 id;
75
76 ret = msm_fb_detect_client("mddi_toshiba_vga");
77 if (ret == -ENODEV)
78 return 0;
79
80 if (ret) {
81 id = mddi_get_client_id();
82 if ((id >> 16) != 0xD263)
83 return 0;
84 }
85#endif
86
87 panel = mddi_toshiba_panel_detect();
88
89 pinfo.xres = 480;
90 pinfo.yres = 640;
91 pinfo.type = MDDI_PANEL;
92 pinfo.pdest = DISPLAY_1;
93 pinfo.mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
94 pinfo.wait_cycle = 0;
95 pinfo.bpp = 18;
96 pinfo.lcd.vsync_enable = TRUE;
97 pinfo.lcd.refx100 = 6118;
98 pinfo.lcd.v_back_porch = 6;
99 pinfo.lcd.v_front_porch = 0;
100 pinfo.lcd.v_pulse_width = 0;
101 pinfo.lcd.hw_vsync_mode = FALSE;
102 pinfo.lcd.vsync_notifier_period = (1 * HZ);
103 pinfo.bl_max = 99;
104 pinfo.bl_min = 1;
105 pinfo.clk_rate = 122880000;
106 pinfo.clk_min = 120000000;
107 pinfo.clk_max = 200000000;
108 pinfo.fb_num = 2;
109
110 ret = mddi_toshiba_device_register(&pinfo, TOSHIBA_VGA_PRIM, panel);
111 if (ret) {
112 printk(KERN_ERR "%s: failed to register device!\n", __func__);
113 return ret;
114 }
115
116 pinfo.xres = 176;
117 pinfo.yres = 220;
118 pinfo.type = MDDI_PANEL;
119 pinfo.pdest = DISPLAY_2;
120 pinfo.mddi.vdopkt = 0x400;
121 pinfo.wait_cycle = 0;
122 pinfo.bpp = 18;
123 pinfo.clk_rate = 122880000;
124 pinfo.clk_min = 120000000;
125 pinfo.clk_max = 200000000;
126 pinfo.fb_num = 2;
127
128 ret = mddi_toshiba_device_register(&pinfo, TOSHIBA_VGA_SECD, panel);
129 if (ret)
130 printk(KERN_WARNING
131 "%s: failed to register device!\n", __func__);
132
133 return ret;
134}
135
136module_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
index 000000000000..557b0f08faf8
--- /dev/null
+++ b/drivers/staging/msm/mddi_toshiba_wvga.c
@@ -0,0 +1,63 @@
1/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include "msm_fb.h"
19#include "mddihost.h"
20#include "mddi_toshiba.h"
21
22static int __init mddi_toshiba_wvga_init(void)
23{
24 int ret;
25 struct msm_panel_info pinfo;
26
27#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
28 if (msm_fb_detect_client("mddi_toshiba_wvga"))
29 return 0;
30#endif
31
32 pinfo.xres = 800;
33 pinfo.yres = 480;
34 pinfo.pdest = DISPLAY_2;
35 pinfo.type = MDDI_PANEL;
36 pinfo.mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
37 pinfo.wait_cycle = 0;
38 pinfo.bpp = 18;
39 pinfo.lcd.vsync_enable = TRUE;
40 pinfo.lcd.refx100 = 6118;
41 pinfo.lcd.v_back_porch = 6;
42 pinfo.lcd.v_front_porch = 0;
43 pinfo.lcd.v_pulse_width = 0;
44 pinfo.lcd.hw_vsync_mode = FALSE;
45 pinfo.lcd.vsync_notifier_period = (1 * HZ);
46 pinfo.bl_max = 4;
47 pinfo.bl_min = 1;
48 pinfo.clk_rate = 192000000;
49 pinfo.clk_min = 190000000;
50 pinfo.clk_max = 200000000;
51 pinfo.fb_num = 2;
52
53 ret = mddi_toshiba_device_register(&pinfo, TOSHIBA_VGA_PRIM,
54 LCD_TOSHIBA_2P4_WVGA);
55 if (ret) {
56 printk(KERN_ERR "%s: failed to register device!\n", __func__);
57 return ret;
58 }
59
60 return ret;
61}
62
63module_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
index 000000000000..fc7d4e0d294f
--- /dev/null
+++ b/drivers/staging/msm/mddi_toshiba_wvga_pt.c
@@ -0,0 +1,64 @@
1/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include "msm_fb.h"
19#include "mddihost.h"
20#include "mddihosti.h"
21#include "mddi_toshiba.h"
22
23static int __init mddi_toshiba_wvga_pt_init(void)
24{
25 int ret;
26 struct msm_panel_info pinfo;
27#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
28 uint id;
29
30 ret = msm_fb_detect_client("mddi_toshiba_wvga_pt");
31 if (ret == -ENODEV)
32 return 0;
33
34 if (ret) {
35 id = mddi_get_client_id();
36 if (id != 0xd2638722)
37 return 0;
38 }
39#endif
40
41 pinfo.xres = 480;
42 pinfo.yres = 800;
43 pinfo.type = MDDI_PANEL;
44 pinfo.pdest = DISPLAY_1;
45 pinfo.mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
46 pinfo.wait_cycle = 0;
47 pinfo.bpp = 18;
48 pinfo.lcd.vsync_enable = FALSE;
49 pinfo.bl_max = 15;
50 pinfo.bl_min = 1;
51 pinfo.clk_rate = 192000000;
52 pinfo.clk_min = 190000000;
53 pinfo.clk_max = 200000000;
54 pinfo.fb_num = 2;
55
56 ret = mddi_toshiba_device_register(&pinfo, TOSHIBA_VGA_PRIM,
57 LCD_TOSHIBA_2P4_WVGA_PT);
58 if (ret)
59 printk(KERN_ERR "%s: failed to register device!\n", __func__);
60
61 return ret;
62}
63
64module_init(mddi_toshiba_wvga_pt_init);
diff --git a/drivers/staging/msm/mddihost.c b/drivers/staging/msm/mddihost.c
new file mode 100644
index 000000000000..c6c1ee4eda05
--- /dev/null
+++ b/drivers/staging/msm/mddihost.c
@@ -0,0 +1,377 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/slab.h>
21#include <linux/delay.h>
22#include <linux/mm.h>
23#include <linux/fb.h>
24#include <linux/init.h>
25#include <linux/ioport.h>
26#include <linux/device.h>
27#include <linux/dma-mapping.h>
28
29#include "msm_fb.h"
30#include "mddihost.h"
31#include "mddihosti.h"
32
33#include <linux/clk.h>
34#include <mach/clk.h>
35
36struct semaphore mddi_host_mutex;
37
38struct clk *mddi_io_clk;
39static boolean mddi_host_powered = FALSE;
40static boolean mddi_host_initialized = FALSE;
41extern uint32 *mddi_reg_read_value_ptr;
42
43mddi_lcd_func_type mddi_lcd;
44
45extern mddi_client_capability_type mddi_client_capability_pkt;
46
47#ifdef FEATURE_MDDI_HITACHI
48extern void mddi_hitachi_window_adjust(uint16 x1,
49 uint16 x2, uint16 y1, uint16 y2);
50#endif
51
52extern void mddi_toshiba_lcd_init(void);
53
54#ifdef FEATURE_MDDI_S6D0142
55extern void mddi_s6d0142_lcd_init(void);
56extern void mddi_s6d0142_window_adjust(uint16 x1,
57 uint16 x2,
58 uint16 y1,
59 uint16 y2,
60 mddi_llist_done_cb_type done_cb);
61#endif
62
63void mddi_init(void)
64{
65 if (mddi_host_initialized)
66 return;
67
68 mddi_host_initialized = TRUE;
69
70 init_MUTEX(&mddi_host_mutex);
71
72 if (!mddi_host_powered) {
73 down(&mddi_host_mutex);
74 mddi_host_init(MDDI_HOST_PRIM);
75 mddi_host_powered = TRUE;
76 up(&mddi_host_mutex);
77 mdelay(10);
78 }
79}
80
81int mddi_host_register_read(uint32 reg_addr,
82 uint32 *reg_value_ptr, boolean wait, mddi_host_type host) {
83 mddi_linked_list_type *curr_llist_ptr;
84 mddi_register_access_packet_type *regacc_pkt_ptr;
85 uint16 curr_llist_idx;
86 int ret = 0;
87
88 if (in_interrupt())
89 MDDI_MSG_CRIT("Called from ISR context\n");
90
91 if (!mddi_host_powered) {
92 MDDI_MSG_ERR("MDDI powered down!\n");
93 mddi_init();
94 }
95
96 down(&mddi_host_mutex);
97
98 mddi_reg_read_value_ptr = reg_value_ptr;
99 curr_llist_idx = mddi_get_reg_read_llist_item(host, TRUE);
100 if (curr_llist_idx == UNASSIGNED_INDEX) {
101 up(&mddi_host_mutex);
102
103 /* need to change this to some sort of wait */
104 MDDI_MSG_ERR("Attempting to queue up more than 1 reg read\n");
105 return -EINVAL;
106 }
107
108 curr_llist_ptr = &llist_extern[host][curr_llist_idx];
109 curr_llist_ptr->link_controller_flags = 0x11;
110 curr_llist_ptr->packet_header_count = 14;
111 curr_llist_ptr->packet_data_count = 0;
112
113 curr_llist_ptr->next_packet_pointer = NULL;
114 curr_llist_ptr->packet_data_pointer = NULL;
115 curr_llist_ptr->reserved = 0;
116
117 regacc_pkt_ptr = &curr_llist_ptr->packet_header.register_pkt;
118
119 regacc_pkt_ptr->packet_length = curr_llist_ptr->packet_header_count;
120 regacc_pkt_ptr->packet_type = 146; /* register access packet */
121 regacc_pkt_ptr->bClient_ID = 0;
122 regacc_pkt_ptr->read_write_info = 0x8001;
123 regacc_pkt_ptr->register_address = reg_addr;
124
125 /* now adjust pointers */
126 mddi_queue_forward_packets(curr_llist_idx, curr_llist_idx, wait,
127 NULL, host);
128 /* need to check if we can write the pointer or not */
129
130 up(&mddi_host_mutex);
131
132 if (wait) {
133 int wait_ret;
134
135 mddi_linked_list_notify_type *llist_notify_ptr;
136 llist_notify_ptr = &llist_extern_notify[host][curr_llist_idx];
137 wait_ret = wait_for_completion_timeout(
138 &(llist_notify_ptr->done_comp), 5 * HZ);
139
140 if (wait_ret <= 0)
141 ret = -EBUSY;
142
143 if (wait_ret < 0)
144 printk(KERN_ERR "%s: failed to wait for completion!\n",
145 __func__);
146 else if (!wait_ret)
147 printk(KERN_ERR "%s: Timed out waiting!\n", __func__);
148 }
149
150 MDDI_MSG_DEBUG("Reg Read value=0x%x\n", *reg_value_ptr);
151
152 return ret;
153} /* mddi_host_register_read */
154
155int mddi_host_register_write(uint32 reg_addr,
156 uint32 reg_val, enum mddi_data_packet_size_type packet_size,
157 boolean wait, mddi_llist_done_cb_type done_cb, mddi_host_type host) {
158 mddi_linked_list_type *curr_llist_ptr;
159 mddi_linked_list_type *curr_llist_dma_ptr;
160 mddi_register_access_packet_type *regacc_pkt_ptr;
161 uint16 curr_llist_idx;
162 int ret = 0;
163
164 if (in_interrupt())
165 MDDI_MSG_CRIT("Called from ISR context\n");
166
167 if (!mddi_host_powered) {
168 MDDI_MSG_ERR("MDDI powered down!\n");
169 mddi_init();
170 }
171
172 down(&mddi_host_mutex);
173
174 curr_llist_idx = mddi_get_next_free_llist_item(host, TRUE);
175 curr_llist_ptr = &llist_extern[host][curr_llist_idx];
176 curr_llist_dma_ptr = &llist_dma_extern[host][curr_llist_idx];
177
178 curr_llist_ptr->link_controller_flags = 1;
179 curr_llist_ptr->packet_header_count = 14;
180 curr_llist_ptr->packet_data_count = 4;
181
182 curr_llist_ptr->next_packet_pointer = NULL;
183 curr_llist_ptr->reserved = 0;
184
185 regacc_pkt_ptr = &curr_llist_ptr->packet_header.register_pkt;
186
187 regacc_pkt_ptr->packet_length = curr_llist_ptr->packet_header_count +
188 (uint16)packet_size;
189 regacc_pkt_ptr->packet_type = 146; /* register access packet */
190 regacc_pkt_ptr->bClient_ID = 0;
191 regacc_pkt_ptr->read_write_info = 0x0001;
192 regacc_pkt_ptr->register_address = reg_addr;
193 regacc_pkt_ptr->register_data_list = reg_val;
194
195 MDDI_MSG_DEBUG("Reg Access write reg=0x%x, value=0x%x\n",
196 regacc_pkt_ptr->register_address,
197 regacc_pkt_ptr->register_data_list);
198
199 regacc_pkt_ptr = &curr_llist_dma_ptr->packet_header.register_pkt;
200 curr_llist_ptr->packet_data_pointer =
201 (void *)(&regacc_pkt_ptr->register_data_list);
202
203 /* now adjust pointers */
204 mddi_queue_forward_packets(curr_llist_idx, curr_llist_idx, wait,
205 done_cb, host);
206
207 up(&mddi_host_mutex);
208
209 if (wait) {
210 int wait_ret;
211
212 mddi_linked_list_notify_type *llist_notify_ptr;
213 llist_notify_ptr = &llist_extern_notify[host][curr_llist_idx];
214 wait_ret = wait_for_completion_timeout(
215 &(llist_notify_ptr->done_comp), 5 * HZ);
216
217 if (wait_ret <= 0)
218 ret = -EBUSY;
219
220 if (wait_ret < 0)
221 printk(KERN_ERR "%s: failed to wait for completion!\n",
222 __func__);
223 else if (!wait_ret)
224 printk(KERN_ERR "%s: Timed out waiting!\n", __func__);
225 }
226
227 return ret;
228} /* mddi_host_register_write */
229
230boolean mddi_host_register_read_int
231 (uint32 reg_addr, uint32 *reg_value_ptr, mddi_host_type host) {
232 mddi_linked_list_type *curr_llist_ptr;
233 mddi_register_access_packet_type *regacc_pkt_ptr;
234 uint16 curr_llist_idx;
235
236 if (!in_interrupt())
237 MDDI_MSG_CRIT("Called from TASK context\n");
238
239 if (!mddi_host_powered) {
240 MDDI_MSG_ERR("MDDI powered down!\n");
241 return FALSE;
242 }
243
244 if (down_trylock(&mddi_host_mutex) != 0)
245 return FALSE;
246
247 mddi_reg_read_value_ptr = reg_value_ptr;
248 curr_llist_idx = mddi_get_reg_read_llist_item(host, FALSE);
249 if (curr_llist_idx == UNASSIGNED_INDEX) {
250 up(&mddi_host_mutex);
251 return FALSE;
252 }
253
254 curr_llist_ptr = &llist_extern[host][curr_llist_idx];
255 curr_llist_ptr->link_controller_flags = 0x11;
256 curr_llist_ptr->packet_header_count = 14;
257 curr_llist_ptr->packet_data_count = 0;
258
259 curr_llist_ptr->next_packet_pointer = NULL;
260 curr_llist_ptr->packet_data_pointer = NULL;
261 curr_llist_ptr->reserved = 0;
262
263 regacc_pkt_ptr = &curr_llist_ptr->packet_header.register_pkt;
264
265 regacc_pkt_ptr->packet_length = curr_llist_ptr->packet_header_count;
266 regacc_pkt_ptr->packet_type = 146; /* register access packet */
267 regacc_pkt_ptr->bClient_ID = 0;
268 regacc_pkt_ptr->read_write_info = 0x8001;
269 regacc_pkt_ptr->register_address = reg_addr;
270
271 /* now adjust pointers */
272 mddi_queue_forward_packets(curr_llist_idx, curr_llist_idx, FALSE,
273 NULL, host);
274 /* need to check if we can write the pointer or not */
275
276 up(&mddi_host_mutex);
277
278 return TRUE;
279
280} /* mddi_host_register_read */
281
282boolean mddi_host_register_write_int
283 (uint32 reg_addr,
284 uint32 reg_val, mddi_llist_done_cb_type done_cb, mddi_host_type host) {
285 mddi_linked_list_type *curr_llist_ptr;
286 mddi_linked_list_type *curr_llist_dma_ptr;
287 mddi_register_access_packet_type *regacc_pkt_ptr;
288 uint16 curr_llist_idx;
289
290 if (!in_interrupt())
291 MDDI_MSG_CRIT("Called from TASK context\n");
292
293 if (!mddi_host_powered) {
294 MDDI_MSG_ERR("MDDI powered down!\n");
295 return FALSE;
296 }
297
298 if (down_trylock(&mddi_host_mutex) != 0)
299 return FALSE;
300
301 curr_llist_idx = mddi_get_next_free_llist_item(host, FALSE);
302 if (curr_llist_idx == UNASSIGNED_INDEX) {
303 up(&mddi_host_mutex);
304 return FALSE;
305 }
306
307 curr_llist_ptr = &llist_extern[host][curr_llist_idx];
308 curr_llist_dma_ptr = &llist_dma_extern[host][curr_llist_idx];
309
310 curr_llist_ptr->link_controller_flags = 1;
311 curr_llist_ptr->packet_header_count = 14;
312 curr_llist_ptr->packet_data_count = 4;
313
314 curr_llist_ptr->next_packet_pointer = NULL;
315 curr_llist_ptr->reserved = 0;
316
317 regacc_pkt_ptr = &curr_llist_ptr->packet_header.register_pkt;
318
319 regacc_pkt_ptr->packet_length = curr_llist_ptr->packet_header_count + 4;
320 regacc_pkt_ptr->packet_type = 146; /* register access packet */
321 regacc_pkt_ptr->bClient_ID = 0;
322 regacc_pkt_ptr->read_write_info = 0x0001;
323 regacc_pkt_ptr->register_address = reg_addr;
324 regacc_pkt_ptr->register_data_list = reg_val;
325
326 regacc_pkt_ptr = &curr_llist_dma_ptr->packet_header.register_pkt;
327 curr_llist_ptr->packet_data_pointer =
328 (void *)(&(regacc_pkt_ptr->register_data_list));
329
330 /* now adjust pointers */
331 mddi_queue_forward_packets(curr_llist_idx, curr_llist_idx, FALSE,
332 done_cb, host);
333 up(&mddi_host_mutex);
334
335 return TRUE;
336
337} /* mddi_host_register_write */
338
339void mddi_wait(uint16 time_ms)
340{
341 mdelay(time_ms);
342}
343
344void mddi_client_lcd_vsync_detected(boolean detected)
345{
346 if (mddi_lcd.vsync_detected)
347 (*mddi_lcd.vsync_detected) (detected);
348}
349
350/* extended version of function includes done callback */
351void mddi_window_adjust_ext(struct msm_fb_data_type *mfd,
352 uint16 x1,
353 uint16 x2,
354 uint16 y1,
355 uint16 y2, mddi_llist_done_cb_type done_cb)
356{
357#ifdef FEATURE_MDDI_HITACHI
358 if (mfd->panel.id == HITACHI)
359 mddi_hitachi_window_adjust(x1, x2, y1, y2);
360#elif defined(FEATURE_MDDI_S6D0142)
361 if (mfd->panel.id == MDDI_LCD_S6D0142)
362 mddi_s6d0142_window_adjust(x1, x2, y1, y2, done_cb);
363#else
364 /* Do nothing then... except avoid lint/compiler warnings */
365 (void)x1;
366 (void)x2;
367 (void)y1;
368 (void)y2;
369 (void)done_cb;
370#endif
371}
372
373void mddi_window_adjust(struct msm_fb_data_type *mfd,
374 uint16 x1, uint16 x2, uint16 y1, uint16 y2)
375{
376 mddi_window_adjust_ext(mfd, x1, x2, y1, y2, NULL);
377}
diff --git a/drivers/staging/msm/mddihost.h b/drivers/staging/msm/mddihost.h
new file mode 100644
index 000000000000..20b817841c4a
--- /dev/null
+++ b/drivers/staging/msm/mddihost.h
@@ -0,0 +1,225 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are met:
5 * * Redistributions of source code must retain the above copyright
6 * notice, this list of conditions and the following disclaimer.
7 * * Redistributions in binary form must reproduce the above copyright
8 * notice, this list of conditions and the following disclaimer in the
9 * documentation and/or other materials provided with the distribution.
10 * * Neither the name of Code Aurora nor
11 * the names of its contributors may be used to endorse or promote
12 * products derived from this software without specific prior written
13 * permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 */
28
29#ifndef MDDIHOST_H
30#define MDDIHOST_H
31
32#include <linux/kernel.h>
33#include <linux/sched.h>
34#include <linux/time.h>
35#include <linux/init.h>
36#include <linux/interrupt.h>
37#include "linux/proc_fs.h"
38#include <linux/types.h>
39#include <linux/dma-mapping.h>
40#include <linux/clk.h>
41
42#include <mach/hardware.h>
43#include <linux/io.h>
44
45#include <asm/system.h>
46#include <asm/mach-types.h>
47#include <linux/types.h>
48#include <linux/dma-mapping.h>
49
50#include "msm_fb_panel.h"
51
52#undef FEATURE_MDDI_MC4
53#undef FEATURE_MDDI_S6D0142
54#undef FEATURE_MDDI_HITACHI
55#define FEATURE_MDDI_SHARP
56#define FEATURE_MDDI_TOSHIBA
57#undef FEATURE_MDDI_E751
58#define FEATURE_MDDI_CORONA
59#define FEATURE_MDDI_PRISM
60
61#define T_MSM7500
62
63typedef enum {
64 format_16bpp,
65 format_18bpp,
66 format_24bpp
67} mddi_video_format;
68
69typedef enum {
70 MDDI_LCD_NONE = 0,
71 MDDI_LCD_MC4,
72 MDDI_LCD_S6D0142,
73 MDDI_LCD_SHARP,
74 MDDI_LCD_E751,
75 MDDI_LCD_CORONA,
76 MDDI_LCD_HITACHI,
77 MDDI_LCD_TOSHIBA,
78 MDDI_LCD_PRISM,
79 MDDI_LCD_TP2,
80 MDDI_NUM_LCD_TYPES,
81 MDDI_LCD_DEFAULT = MDDI_LCD_TOSHIBA
82} mddi_lcd_type;
83
84typedef enum {
85 MDDI_HOST_PRIM = 0,
86 MDDI_HOST_EXT,
87 MDDI_NUM_HOST_CORES
88} mddi_host_type;
89
90typedef enum {
91 MDDI_DRIVER_RESET, /* host core registers have not been written. */
92 MDDI_DRIVER_DISABLED, /* registers written, interrupts disabled. */
93 MDDI_DRIVER_ENABLED /* registers written, interrupts enabled. */
94} mddi_host_driver_state_type;
95
96typedef enum {
97 MDDI_GPIO_INT_0 = 0,
98 MDDI_GPIO_INT_1,
99 MDDI_GPIO_INT_2,
100 MDDI_GPIO_INT_3,
101 MDDI_GPIO_INT_4,
102 MDDI_GPIO_INT_5,
103 MDDI_GPIO_INT_6,
104 MDDI_GPIO_INT_7,
105 MDDI_GPIO_INT_8,
106 MDDI_GPIO_INT_9,
107 MDDI_GPIO_INT_10,
108 MDDI_GPIO_INT_11,
109 MDDI_GPIO_INT_12,
110 MDDI_GPIO_INT_13,
111 MDDI_GPIO_INT_14,
112 MDDI_GPIO_INT_15,
113 MDDI_GPIO_NUM_INTS
114} mddi_gpio_int_type;
115
116enum mddi_data_packet_size_type {
117 MDDI_DATA_PACKET_4_BYTES = 4,
118 MDDI_DATA_PACKET_8_BYTES = 8,
119 MDDI_DATA_PACKET_12_BYTES = 12,
120 MDDI_DATA_PACKET_16_BYTES = 16,
121 MDDI_DATA_PACKET_24_BYTES = 24
122};
123
124typedef struct {
125 uint32 addr;
126 uint32 value;
127} mddi_reg_write_type;
128
129boolean mddi_vsync_set_handler(msm_fb_vsync_handler_type handler, void *arg);
130
131typedef void (*mddi_llist_done_cb_type) (void);
132
133typedef void (*mddi_rev_handler_type) (void *);
134
135boolean mddi_set_rev_handler(mddi_rev_handler_type handler, uint16 pkt_type);
136
137#define MDDI_DEFAULT_PRIM_PIX_ATTR 0xC3
138#define MDDI_DEFAULT_SECD_PIX_ATTR 0xC0
139
140typedef int gpio_int_polarity_type;
141typedef int gpio_int_handler_type;
142
143typedef struct {
144 void (*vsync_detected) (boolean);
145} mddi_lcd_func_type;
146
147extern mddi_lcd_func_type mddi_lcd;
148void mddi_init(void);
149
150void mddi_powerdown(void);
151
152void mddi_host_start_ext_display(void);
153void mddi_host_stop_ext_display(void);
154
155extern spinlock_t mddi_host_spin_lock;
156#ifdef T_MSM7500
157void mddi_reset(void);
158#ifdef FEATURE_DUAL_PROC_MODEM_DISPLAY
159void mddi_host_switch_proc_control(boolean on);
160#endif
161#endif
162void mddi_host_exit_power_collapse(void);
163
164void mddi_queue_splash_screen
165 (void *buf_ptr,
166 boolean clear_area,
167 int16 src_width,
168 int16 src_starting_row,
169 int16 src_starting_column,
170 int16 num_of_rows,
171 int16 num_of_columns, int16 dst_starting_row, int16 dst_starting_column);
172
173void mddi_queue_image
174 (void *buf_ptr,
175 uint8 stereo_video,
176 boolean clear_area,
177 int16 src_width,
178 int16 src_starting_row,
179 int16 src_starting_column,
180 int16 num_of_rows,
181 int16 num_of_columns, int16 dst_starting_row, int16 dst_starting_column);
182
183int mddi_host_register_read
184 (uint32 reg_addr,
185 uint32 *reg_value_ptr, boolean wait, mddi_host_type host_idx);
186int mddi_host_register_write
187 (uint32 reg_addr, uint32 reg_val,
188 enum mddi_data_packet_size_type packet_size,
189 boolean wait, mddi_llist_done_cb_type done_cb, mddi_host_type host);
190boolean mddi_host_register_write_int
191 (uint32 reg_addr,
192 uint32 reg_val, mddi_llist_done_cb_type done_cb, mddi_host_type host);
193boolean mddi_host_register_read_int
194 (uint32 reg_addr, uint32 *reg_value_ptr, mddi_host_type host_idx);
195void mddi_queue_register_write_static
196 (uint32 reg_addr,
197 uint32 reg_val, boolean wait, mddi_llist_done_cb_type done_cb);
198void mddi_queue_static_window_adjust
199 (const mddi_reg_write_type *reg_write,
200 uint16 num_writes, mddi_llist_done_cb_type done_cb);
201
202#define mddi_queue_register_read(reg, val_ptr, wait, sig) \
203 mddi_host_register_read(reg, val_ptr, wait, MDDI_HOST_PRIM)
204#define mddi_queue_register_write(reg, val, wait, sig) \
205 mddi_host_register_write(reg, val, MDDI_DATA_PACKET_4_BYTES,\
206 wait, NULL, MDDI_HOST_PRIM)
207#define mddi_queue_register_write_extn(reg, val, pkt_size, wait, sig) \
208 mddi_host_register_write(reg, val, pkt_size, \
209 wait, NULL, MDDI_HOST_PRIM)
210#define mddi_queue_register_write_int(reg, val) \
211 mddi_host_register_write_int(reg, val, NULL, MDDI_HOST_PRIM)
212#define mddi_queue_register_read_int(reg, val_ptr) \
213 mddi_host_register_read_int(reg, val_ptr, MDDI_HOST_PRIM)
214#define mddi_queue_register_writes(reg_ptr, val, wait, sig) \
215 mddi_host_register_writes(reg_ptr, val, wait, sig, MDDI_HOST_PRIM)
216
217void mddi_wait(uint16 time_ms);
218void mddi_assign_max_pkt_dimensions(uint16 image_cols,
219 uint16 image_rows,
220 uint16 bpp,
221 uint16 *max_cols, uint16 * max_rows);
222uint16 mddi_assign_pkt_height(uint16 pkt_width, uint16 pkt_height, uint16 bpp);
223void mddi_queue_reverse_encapsulation(boolean wait);
224void mddi_disable(int lock);
225#endif /* MDDIHOST_H */
diff --git a/drivers/staging/msm/mddihost_e.c b/drivers/staging/msm/mddihost_e.c
new file mode 100644
index 000000000000..7de5eda71ce3
--- /dev/null
+++ b/drivers/staging/msm/mddihost_e.c
@@ -0,0 +1,63 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/slab.h>
21#include <linux/delay.h>
22#include <linux/mm.h>
23#include <linux/fb.h>
24#include <linux/init.h>
25#include <linux/ioport.h>
26#include <linux/device.h>
27#include <linux/dma-mapping.h>
28
29#include "msm_fb.h"
30#include "mddihost.h"
31#include "mddihosti.h"
32
33#include <linux/clk.h>
34#include <mach/clk.h>
35
36extern struct semaphore mddi_host_mutex;
37static boolean mddi_host_ext_powered = FALSE;
38
39void mddi_host_start_ext_display(void)
40{
41 down(&mddi_host_mutex);
42
43 if (!mddi_host_ext_powered) {
44 mddi_host_init(MDDI_HOST_EXT);
45
46 mddi_host_ext_powered = TRUE;
47 }
48
49 up(&mddi_host_mutex);
50}
51
52void mddi_host_stop_ext_display(void)
53{
54 down(&mddi_host_mutex);
55
56 if (mddi_host_ext_powered) {
57 mddi_host_powerdown(MDDI_HOST_EXT);
58
59 mddi_host_ext_powered = FALSE;
60 }
61
62 up(&mddi_host_mutex);
63}
diff --git a/drivers/staging/msm/mddihosti.c b/drivers/staging/msm/mddihosti.c
new file mode 100644
index 000000000000..f9d6e91e8d5d
--- /dev/null
+++ b/drivers/staging/msm/mddihosti.c
@@ -0,0 +1,2239 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/slab.h>
21#include <linux/delay.h>
22#include <linux/mm.h>
23#include <linux/fb.h>
24#include <linux/init.h>
25#include <linux/ioport.h>
26#include <linux/device.h>
27#include <linux/dma-mapping.h>
28
29#include "msm_fb_panel.h"
30#include "mddihost.h"
31#include "mddihosti.h"
32
33#define FEATURE_MDDI_UNDERRUN_RECOVERY
34#ifndef FEATURE_MDDI_DISABLE_REVERSE
35static void mddi_read_rev_packet(byte *data_ptr);
36#endif
37
38struct timer_list mddi_host_timer;
39
40#define MDDI_DEFAULT_TIMER_LENGTH 5000 /* 5 seconds */
41uint32 mddi_rtd_frequency = 60000; /* send RTD every 60 seconds */
42uint32 mddi_client_status_frequency = 60000; /* get status pkt every 60 secs */
43
44boolean mddi_vsync_detect_enabled = FALSE;
45mddi_gpio_info_type mddi_gpio;
46
47uint32 mddi_host_core_version;
48boolean mddi_debug_log_statistics = FALSE;
49/* #define FEATURE_MDDI_HOST_ENABLE_EARLY_HIBERNATION */
50/* default to TRUE in case MDP does not vote */
51static boolean mddi_host_mdp_active_flag = TRUE;
52static uint32 mddi_log_stats_counter;
53uint32 mddi_log_stats_frequency = 4000;
54
55#define MDDI_DEFAULT_REV_PKT_SIZE 0x20
56
57#ifndef FEATURE_MDDI_DISABLE_REVERSE
58static boolean mddi_rev_ptr_workaround = TRUE;
59static uint32 mddi_reg_read_retry;
60static uint32 mddi_reg_read_retry_max = 20;
61static boolean mddi_enable_reg_read_retry = TRUE;
62static boolean mddi_enable_reg_read_retry_once = FALSE;
63
64#define MDDI_MAX_REV_PKT_SIZE 0x60
65
66#define MDDI_CLIENT_CAPABILITY_REV_PKT_SIZE 0x60
67
68#define MDDI_VIDEO_REV_PKT_SIZE 0x40
69#define MDDI_REV_BUFFER_SIZE MDDI_MAX_REV_PKT_SIZE
70static byte rev_packet_data[MDDI_MAX_REV_PKT_SIZE];
71#endif /* FEATURE_MDDI_DISABLE_REVERSE */
72/* leave these variables so graphics will compile */
73
74#define MDDI_MAX_REV_DATA_SIZE 128
75/*lint -d__align(x) */
76boolean mddi_debug_clear_rev_data = TRUE;
77
78uint32 *mddi_reg_read_value_ptr;
79
80mddi_client_capability_type mddi_client_capability_pkt;
81static boolean mddi_client_capability_request = FALSE;
82
83#ifndef FEATURE_MDDI_DISABLE_REVERSE
84
85#define MAX_MDDI_REV_HANDLERS 2
86#define INVALID_PKT_TYPE 0xFFFF
87
88typedef struct {
89 mddi_rev_handler_type handler; /* ISR to be executed */
90 uint16 pkt_type;
91} mddi_rev_pkt_handler_type;
92static mddi_rev_pkt_handler_type mddi_rev_pkt_handler[MAX_MDDI_REV_HANDLERS] =
93 { {NULL, INVALID_PKT_TYPE}, {NULL, INVALID_PKT_TYPE} };
94
95static boolean mddi_rev_encap_user_request = FALSE;
96static mddi_linked_list_notify_type mddi_rev_user;
97
98spinlock_t mddi_host_spin_lock;
99extern uint32 mdp_in_processing;
100#endif
101
102typedef enum {
103 MDDI_REV_IDLE
104#ifndef FEATURE_MDDI_DISABLE_REVERSE
105 , MDDI_REV_REG_READ_ISSUED,
106 MDDI_REV_REG_READ_SENT,
107 MDDI_REV_ENCAP_ISSUED,
108 MDDI_REV_STATUS_REQ_ISSUED,
109 MDDI_REV_CLIENT_CAP_ISSUED
110#endif
111} mddi_rev_link_state_type;
112
113typedef enum {
114 MDDI_LINK_DISABLED,
115 MDDI_LINK_HIBERNATING,
116 MDDI_LINK_ACTIVATING,
117 MDDI_LINK_ACTIVE
118} mddi_host_link_state_type;
119
120typedef struct {
121 uint32 count;
122 uint32 in_count;
123 uint32 disp_req_count;
124 uint32 state_change_count;
125 uint32 ll_done_count;
126 uint32 rev_avail_count;
127 uint32 error_count;
128 uint32 rev_encap_count;
129 uint32 llist_ptr_write_1;
130 uint32 llist_ptr_write_2;
131} mddi_host_int_type;
132
133typedef struct {
134 uint32 fwd_crc_count;
135 uint32 rev_crc_count;
136 uint32 pri_underflow;
137 uint32 sec_underflow;
138 uint32 rev_overflow;
139 uint32 pri_overwrite;
140 uint32 sec_overwrite;
141 uint32 rev_overwrite;
142 uint32 dma_failure;
143 uint32 rtd_failure;
144 uint32 reg_read_failure;
145#ifdef FEATURE_MDDI_UNDERRUN_RECOVERY
146 uint32 pri_underrun_detected;
147#endif
148} mddi_host_stat_type;
149
150typedef struct {
151 uint32 rtd_cnt;
152 uint32 rev_enc_cnt;
153 uint32 vid_cnt;
154 uint32 reg_acc_cnt;
155 uint32 cli_stat_cnt;
156 uint32 cli_cap_cnt;
157 uint32 reg_read_cnt;
158 uint32 link_active_cnt;
159 uint32 link_hibernate_cnt;
160 uint32 vsync_response_cnt;
161 uint32 fwd_crc_cnt;
162 uint32 rev_crc_cnt;
163} mddi_log_params_struct_type;
164
165typedef struct {
166 uint32 rtd_value;
167 uint32 rtd_counter;
168 uint32 client_status_cnt;
169 boolean rev_ptr_written;
170 uint8 *rev_ptr_start;
171 uint8 *rev_ptr_curr;
172 uint32 mddi_rev_ptr_write_val;
173 dma_addr_t rev_data_dma_addr;
174 uint16 rev_pkt_size;
175 mddi_rev_link_state_type rev_state;
176 mddi_host_link_state_type link_state;
177 mddi_host_driver_state_type driver_state;
178 boolean disable_hibernation;
179 uint32 saved_int_reg;
180 uint32 saved_int_en;
181 mddi_linked_list_type *llist_ptr;
182 dma_addr_t llist_dma_addr;
183 mddi_linked_list_type *llist_dma_ptr;
184 uint32 *rev_data_buf;
185 struct completion mddi_llist_avail_comp;
186 boolean mddi_waiting_for_llist_avail;
187 mddi_host_int_type int_type;
188 mddi_host_stat_type stats;
189 mddi_log_params_struct_type log_parms;
190 mddi_llist_info_type llist_info;
191 mddi_linked_list_notify_type llist_notify[MDDI_MAX_NUM_LLIST_ITEMS];
192} mddi_host_cntl_type;
193
194static mddi_host_type mddi_curr_host = MDDI_HOST_PRIM;
195static mddi_host_cntl_type mhctl[MDDI_NUM_HOST_CORES];
196mddi_linked_list_type *llist_extern[MDDI_NUM_HOST_CORES];
197mddi_linked_list_type *llist_dma_extern[MDDI_NUM_HOST_CORES];
198mddi_linked_list_notify_type *llist_extern_notify[MDDI_NUM_HOST_CORES];
199static mddi_log_params_struct_type prev_parms[MDDI_NUM_HOST_CORES];
200
201extern uint32 mdp_total_vdopkts;
202
203static boolean mddi_host_io_clock_on = FALSE;
204static boolean mddi_host_hclk_on = FALSE;
205
206int int_mddi_pri_flag = FALSE;
207int int_mddi_ext_flag = FALSE;
208
209static void mddi_report_errors(uint32 int_reg)
210{
211 mddi_host_type host_idx = mddi_curr_host;
212 mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
213
214 if (int_reg & MDDI_INT_PRI_UNDERFLOW) {
215 pmhctl->stats.pri_underflow++;
216 MDDI_MSG_ERR("!!! MDDI Primary Underflow !!!\n");
217 }
218 if (int_reg & MDDI_INT_SEC_UNDERFLOW) {
219 pmhctl->stats.sec_underflow++;
220 MDDI_MSG_ERR("!!! MDDI Secondary Underflow !!!\n");
221 }
222#ifndef FEATURE_MDDI_DISABLE_REVERSE
223 if (int_reg & MDDI_INT_REV_OVERFLOW) {
224 pmhctl->stats.rev_overflow++;
225 MDDI_MSG_ERR("!!! MDDI Reverse Overflow !!!\n");
226 pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
227 mddi_host_reg_out(REV_PTR, pmhctl->mddi_rev_ptr_write_val);
228
229 }
230 if (int_reg & MDDI_INT_CRC_ERROR)
231 MDDI_MSG_ERR("!!! MDDI Reverse CRC Error !!!\n");
232#endif
233 if (int_reg & MDDI_INT_PRI_OVERWRITE) {
234 pmhctl->stats.pri_overwrite++;
235 MDDI_MSG_ERR("!!! MDDI Primary Overwrite !!!\n");
236 }
237 if (int_reg & MDDI_INT_SEC_OVERWRITE) {
238 pmhctl->stats.sec_overwrite++;
239 MDDI_MSG_ERR("!!! MDDI Secondary Overwrite !!!\n");
240 }
241#ifndef FEATURE_MDDI_DISABLE_REVERSE
242 if (int_reg & MDDI_INT_REV_OVERWRITE) {
243 pmhctl->stats.rev_overwrite++;
244 /* This will show up normally and is not a problem */
245 MDDI_MSG_DEBUG("MDDI Reverse Overwrite!\n");
246 }
247 if (int_reg & MDDI_INT_RTD_FAILURE) {
248 mddi_host_reg_outm(INTEN, MDDI_INT_RTD_FAILURE, 0);
249 pmhctl->stats.rtd_failure++;
250 MDDI_MSG_ERR("!!! MDDI RTD Failure !!!\n");
251 }
252#endif
253 if (int_reg & MDDI_INT_DMA_FAILURE) {
254 pmhctl->stats.dma_failure++;
255 MDDI_MSG_ERR("!!! MDDI DMA Abort !!!\n");
256 }
257}
258
259static void mddi_host_enable_io_clock(void)
260{
261 if (!MDDI_HOST_IS_IO_CLOCK_ON)
262 MDDI_HOST_ENABLE_IO_CLOCK;
263}
264
265static void mddi_host_enable_hclk(void)
266{
267
268 if (!MDDI_HOST_IS_HCLK_ON)
269 MDDI_HOST_ENABLE_HCLK;
270}
271
272static void mddi_host_disable_io_clock(void)
273{
274#ifndef FEATURE_MDDI_HOST_IO_CLOCK_CONTROL_DISABLE
275 if (MDDI_HOST_IS_IO_CLOCK_ON)
276 MDDI_HOST_DISABLE_IO_CLOCK;
277#endif
278}
279
280static void mddi_host_disable_hclk(void)
281{
282#ifndef FEATURE_MDDI_HOST_HCLK_CONTROL_DISABLE
283 if (MDDI_HOST_IS_HCLK_ON)
284 MDDI_HOST_DISABLE_HCLK;
285#endif
286}
287
288static void mddi_vote_to_sleep(mddi_host_type host_idx, boolean sleep)
289{
290 uint16 vote_mask;
291
292 if (host_idx == MDDI_HOST_PRIM)
293 vote_mask = 0x01;
294 else
295 vote_mask = 0x02;
296}
297
298static void mddi_report_state_change(uint32 int_reg)
299{
300 mddi_host_type host_idx = mddi_curr_host;
301 mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
302
303 if ((pmhctl->saved_int_reg & MDDI_INT_IN_HIBERNATION) &&
304 (pmhctl->saved_int_reg & MDDI_INT_LINK_ACTIVE)) {
305 /* recover from condition where the io_clock was turned off by the
306 clock driver during a transition to hibernation. The io_clock
307 disable is to prevent MDP/MDDI underruns when changing ARM
308 clock speeds. In the process of halting the ARM, the hclk
309 divider needs to be set to 1. When it is set to 1, there is
310 a small time (usecs) when hclk is off or slow, and this can
311 cause an underrun. To prevent the underrun, clock driver turns
312 off the MDDI io_clock before making the change. */
313 mddi_host_reg_out(CMD, MDDI_CMD_POWERUP);
314 }
315
316 if (int_reg & MDDI_INT_LINK_ACTIVE) {
317 pmhctl->link_state = MDDI_LINK_ACTIVE;
318 pmhctl->log_parms.link_active_cnt++;
319 pmhctl->rtd_value = mddi_host_reg_in(RTD_VAL);
320 MDDI_MSG_DEBUG("!!! MDDI Active RTD:0x%x!!!\n",
321 pmhctl->rtd_value);
322 /* now interrupt on hibernation */
323 mddi_host_reg_outm(INTEN,
324 (MDDI_INT_IN_HIBERNATION |
325 MDDI_INT_LINK_ACTIVE),
326 MDDI_INT_IN_HIBERNATION);
327
328#ifdef DEBUG_MDDIHOSTI
329 /* if gpio interrupt is enabled, start polling at fastest
330 * registered rate
331 */
332 if (mddi_gpio.polling_enabled) {
333 timer_reg(&mddi_gpio_poll_timer,
334 mddi_gpio_poll_timer_cb, 0, mddi_gpio.polling_interval, 0);
335 }
336#endif
337#ifndef FEATURE_MDDI_DISABLE_REVERSE
338 if (mddi_rev_ptr_workaround) {
339 /* HW CR: need to reset reverse register stuff */
340 pmhctl->rev_ptr_written = FALSE;
341 pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
342 }
343#endif
344 /* vote on sleep */
345 mddi_vote_to_sleep(host_idx, FALSE);
346
347 if (host_idx == MDDI_HOST_PRIM) {
348 if (mddi_vsync_detect_enabled) {
349 /*
350 * Indicate to client specific code that vsync
351 * was enabled, but we did not detect a client
352 * intiated wakeup. The client specific
353 * handler can either reassert vsync detection,
354 * or treat this as a valid vsync.
355 */
356 mddi_client_lcd_vsync_detected(FALSE);
357 pmhctl->log_parms.vsync_response_cnt++;
358 }
359 }
360 }
361 if (int_reg & MDDI_INT_IN_HIBERNATION) {
362 pmhctl->link_state = MDDI_LINK_HIBERNATING;
363 pmhctl->log_parms.link_hibernate_cnt++;
364 MDDI_MSG_DEBUG("!!! MDDI Hibernating !!!\n");
365 /* now interrupt on link_active */
366#ifdef FEATURE_MDDI_DISABLE_REVERSE
367 mddi_host_reg_outm(INTEN,
368 (MDDI_INT_MDDI_IN |
369 MDDI_INT_IN_HIBERNATION |
370 MDDI_INT_LINK_ACTIVE),
371 MDDI_INT_LINK_ACTIVE);
372#else
373 mddi_host_reg_outm(INTEN,
374 (MDDI_INT_MDDI_IN |
375 MDDI_INT_IN_HIBERNATION |
376 MDDI_INT_LINK_ACTIVE),
377 (MDDI_INT_MDDI_IN | MDDI_INT_LINK_ACTIVE));
378
379 pmhctl->rtd_counter = mddi_rtd_frequency;
380
381 if (pmhctl->rev_state != MDDI_REV_IDLE) {
382 /* a rev_encap will not wake up the link, so we do that here */
383 pmhctl->link_state = MDDI_LINK_ACTIVATING;
384 mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE);
385 }
386#endif
387
388 if (pmhctl->disable_hibernation) {
389 mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE);
390 mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE);
391 pmhctl->link_state = MDDI_LINK_ACTIVATING;
392 }
393#ifdef FEATURE_MDDI_UNDERRUN_RECOVERY
394 if ((pmhctl->llist_info.transmitting_start_idx !=
395 UNASSIGNED_INDEX)
396 &&
397 ((pmhctl->
398 saved_int_reg & (MDDI_INT_PRI_LINK_LIST_DONE |
399 MDDI_INT_PRI_PTR_READ)) ==
400 MDDI_INT_PRI_PTR_READ)) {
401 mddi_linked_list_type *llist_dma;
402 llist_dma = pmhctl->llist_dma_ptr;
403 /*
404 * All indications are that we have not received a
405 * linked list done interrupt, due to an underrun
406 * condition. Recovery attempt is to send again.
407 */
408 dma_coherent_pre_ops();
409 /* Write to primary pointer register again */
410 mddi_host_reg_out(PRI_PTR,
411 &llist_dma[pmhctl->llist_info.
412 transmitting_start_idx]);
413 pmhctl->stats.pri_underrun_detected++;
414 }
415#endif
416
417 /* vote on sleep */
418 if (pmhctl->link_state == MDDI_LINK_HIBERNATING) {
419 mddi_vote_to_sleep(host_idx, TRUE);
420 }
421
422#ifdef DEBUG_MDDIHOSTI
423 /* need to stop polling timer */
424 if (mddi_gpio.polling_enabled) {
425 (void) timer_clr(&mddi_gpio_poll_timer, T_NONE);
426 }
427#endif
428 }
429}
430
431void mddi_host_timer_service(unsigned long data)
432{
433#ifndef FEATURE_MDDI_DISABLE_REVERSE
434 unsigned long flags;
435#endif
436 mddi_host_type host_idx;
437 mddi_host_cntl_type *pmhctl;
438
439 unsigned long time_ms = MDDI_DEFAULT_TIMER_LENGTH;
440 init_timer(&mddi_host_timer);
441 mddi_host_timer.function = mddi_host_timer_service;
442 mddi_host_timer.data = 0;
443
444 mddi_host_timer.expires = jiffies + ((time_ms * HZ) / 1000);
445 add_timer(&mddi_host_timer);
446
447 for (host_idx = MDDI_HOST_PRIM; host_idx < MDDI_NUM_HOST_CORES;
448 host_idx++) {
449 pmhctl = &(mhctl[host_idx]);
450 mddi_log_stats_counter += (uint32) time_ms;
451#ifndef FEATURE_MDDI_DISABLE_REVERSE
452 pmhctl->rtd_counter += (uint32) time_ms;
453 pmhctl->client_status_cnt += (uint32) time_ms;
454
455 if (host_idx == MDDI_HOST_PRIM) {
456 if (pmhctl->client_status_cnt >=
457 mddi_client_status_frequency) {
458 if ((pmhctl->link_state ==
459 MDDI_LINK_HIBERNATING)
460 && (pmhctl->client_status_cnt >
461 mddi_client_status_frequency)) {
462 /*
463 * special case where we are hibernating
464 * and mddi_host_isr is not firing, so
465 * kick the link so that the status can
466 * be retrieved
467 */
468
469 /* need to wake up link before issuing
470 * rev encap command
471 */
472 MDDI_MSG_INFO("wake up link!\n");
473 spin_lock_irqsave(&mddi_host_spin_lock,
474 flags);
475 mddi_host_enable_hclk();
476 mddi_host_enable_io_clock();
477 pmhctl->link_state =
478 MDDI_LINK_ACTIVATING;
479 mddi_host_reg_out(CMD,
480 MDDI_CMD_LINK_ACTIVE);
481 spin_unlock_irqrestore
482 (&mddi_host_spin_lock, flags);
483 } else
484 if ((pmhctl->link_state == MDDI_LINK_ACTIVE)
485 && pmhctl->disable_hibernation) {
486 /*
487 * special case where we have disabled
488 * hibernation and mddi_host_isr
489 * is not firing, so enable interrupt
490 * for no pkts pending, which will
491 * generate an interrupt
492 */
493 MDDI_MSG_INFO("kick isr!\n");
494 spin_lock_irqsave(&mddi_host_spin_lock,
495 flags);
496 mddi_host_enable_hclk();
497 mddi_host_reg_outm(INTEN,
498 MDDI_INT_NO_CMD_PKTS_PEND,
499 MDDI_INT_NO_CMD_PKTS_PEND);
500 spin_unlock_irqrestore
501 (&mddi_host_spin_lock, flags);
502 }
503 }
504 }
505#endif /* #ifndef FEATURE_MDDI_DISABLE_REVERSE */
506 }
507
508 /* Check if logging is turned on */
509 for (host_idx = MDDI_HOST_PRIM; host_idx < MDDI_NUM_HOST_CORES;
510 host_idx++) {
511 mddi_log_params_struct_type *prev_ptr = &(prev_parms[host_idx]);
512 pmhctl = &(mhctl[host_idx]);
513
514 if (mddi_debug_log_statistics) {
515
516 /* get video pkt count from MDP, since MDDI sw cannot know this */
517 pmhctl->log_parms.vid_cnt = mdp_total_vdopkts;
518
519 if (mddi_log_stats_counter >= mddi_log_stats_frequency) {
520 /* mddi_log_stats_counter = 0; */
521 if (mddi_debug_log_statistics) {
522 MDDI_MSG_NOTICE
523 ("MDDI Statistics since last report:\n");
524 MDDI_MSG_NOTICE(" Packets sent:\n");
525 MDDI_MSG_NOTICE
526 (" %d RTD packet(s)\n",
527 pmhctl->log_parms.rtd_cnt -
528 prev_ptr->rtd_cnt);
529 if (prev_ptr->rtd_cnt !=
530 pmhctl->log_parms.rtd_cnt) {
531 unsigned long flags;
532 spin_lock_irqsave
533 (&mddi_host_spin_lock,
534 flags);
535 mddi_host_enable_hclk();
536 pmhctl->rtd_value =
537 mddi_host_reg_in(RTD_VAL);
538 spin_unlock_irqrestore
539 (&mddi_host_spin_lock,
540 flags);
541 MDDI_MSG_NOTICE
542 (" RTD value=%d\n",
543 pmhctl->rtd_value);
544 }
545 MDDI_MSG_NOTICE
546 (" %d VIDEO packets\n",
547 pmhctl->log_parms.vid_cnt -
548 prev_ptr->vid_cnt);
549 MDDI_MSG_NOTICE
550 (" %d Register Access packets\n",
551 pmhctl->log_parms.reg_acc_cnt -
552 prev_ptr->reg_acc_cnt);
553 MDDI_MSG_NOTICE
554 (" %d Reverse Encapsulation packet(s)\n",
555 pmhctl->log_parms.rev_enc_cnt -
556 prev_ptr->rev_enc_cnt);
557 if (prev_ptr->rev_enc_cnt !=
558 pmhctl->log_parms.rev_enc_cnt) {
559 /* report # of reverse CRC errors */
560 MDDI_MSG_NOTICE
561 (" %d reverse CRC errors detected\n",
562 pmhctl->log_parms.
563 rev_crc_cnt -
564 prev_ptr->rev_crc_cnt);
565 }
566 MDDI_MSG_NOTICE
567 (" Packets received:\n");
568 MDDI_MSG_NOTICE
569 (" %d Client Status packets",
570 pmhctl->log_parms.cli_stat_cnt -
571 prev_ptr->cli_stat_cnt);
572 if (prev_ptr->cli_stat_cnt !=
573 pmhctl->log_parms.cli_stat_cnt) {
574 MDDI_MSG_NOTICE
575 (" %d forward CRC errors reported\n",
576 pmhctl->log_parms.
577 fwd_crc_cnt -
578 prev_ptr->fwd_crc_cnt);
579 }
580 MDDI_MSG_NOTICE
581 (" %d Register Access Read packets\n",
582 pmhctl->log_parms.reg_read_cnt -
583 prev_ptr->reg_read_cnt);
584
585 if (pmhctl->link_state ==
586 MDDI_LINK_ACTIVE) {
587 MDDI_MSG_NOTICE
588 (" Current Link Status: Active\n");
589 } else
590 if ((pmhctl->link_state ==
591 MDDI_LINK_HIBERNATING)
592 || (pmhctl->link_state ==
593 MDDI_LINK_ACTIVATING)) {
594 MDDI_MSG_NOTICE
595 (" Current Link Status: Hibernation\n");
596 } else {
597 MDDI_MSG_NOTICE
598 (" Current Link Status: Inactive\n");
599 }
600 MDDI_MSG_NOTICE
601 (" Active state entered %d times\n",
602 pmhctl->log_parms.link_active_cnt -
603 prev_ptr->link_active_cnt);
604 MDDI_MSG_NOTICE
605 (" Hibernation state entered %d times\n",
606 pmhctl->log_parms.
607 link_hibernate_cnt -
608 prev_ptr->link_hibernate_cnt);
609 }
610 }
611 prev_parms[host_idx] = pmhctl->log_parms;
612 }
613 }
614 if (mddi_log_stats_counter >= mddi_log_stats_frequency)
615 mddi_log_stats_counter = 0;
616
617 return;
618} /* mddi_host_timer_cb */
619
620static void mddi_process_link_list_done(void)
621{
622 mddi_host_type host_idx = mddi_curr_host;
623 mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
624
625 /* normal forward linked list packet(s) were sent */
626 if (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) {
627 MDDI_MSG_ERR("**** getting LL done, but no list ****\n");
628 } else {
629 uint16 idx;
630
631#ifndef FEATURE_MDDI_DISABLE_REVERSE
632 if (pmhctl->rev_state == MDDI_REV_REG_READ_ISSUED) {
633 /* special case where a register read packet was sent */
634 pmhctl->rev_state = MDDI_REV_REG_READ_SENT;
635 if (pmhctl->llist_info.reg_read_idx == UNASSIGNED_INDEX) {
636 MDDI_MSG_ERR
637 ("**** getting LL done, but no list ****\n");
638 }
639 }
640#endif
641 for (idx = pmhctl->llist_info.transmitting_start_idx;;) {
642 uint16 next_idx = pmhctl->llist_notify[idx].next_idx;
643 /* with reg read we don't release the waiting tcb until after
644 * the reverse encapsulation has completed.
645 */
646 if (idx != pmhctl->llist_info.reg_read_idx) {
647 /* notify task that may be waiting on this completion */
648 if (pmhctl->llist_notify[idx].waiting) {
649 complete(&
650 (pmhctl->llist_notify[idx].
651 done_comp));
652 }
653 if (pmhctl->llist_notify[idx].done_cb != NULL) {
654 (*(pmhctl->llist_notify[idx].done_cb))
655 ();
656 }
657
658 pmhctl->llist_notify[idx].in_use = FALSE;
659 pmhctl->llist_notify[idx].waiting = FALSE;
660 pmhctl->llist_notify[idx].done_cb = NULL;
661 if (idx < MDDI_NUM_DYNAMIC_LLIST_ITEMS) {
662 /* static LLIST items are configured only once */
663 pmhctl->llist_notify[idx].next_idx =
664 UNASSIGNED_INDEX;
665 }
666 /*
667 * currently, all linked list packets are
668 * register access, so we can increment the
669 * counter for that packet type here.
670 */
671 pmhctl->log_parms.reg_acc_cnt++;
672 }
673 if (idx == pmhctl->llist_info.transmitting_end_idx)
674 break;
675 idx = next_idx;
676 if (idx == UNASSIGNED_INDEX)
677 MDDI_MSG_CRIT("MDDI linked list corruption!\n");
678 }
679
680 pmhctl->llist_info.transmitting_start_idx = UNASSIGNED_INDEX;
681 pmhctl->llist_info.transmitting_end_idx = UNASSIGNED_INDEX;
682
683 if (pmhctl->mddi_waiting_for_llist_avail) {
684 if (!
685 (pmhctl->
686 llist_notify[pmhctl->llist_info.next_free_idx].
687 in_use)) {
688 pmhctl->mddi_waiting_for_llist_avail = FALSE;
689 complete(&(pmhctl->mddi_llist_avail_comp));
690 }
691 }
692 }
693
694 /* Turn off MDDI_INT_PRI_LINK_LIST_DONE interrupt */
695 mddi_host_reg_outm(INTEN, MDDI_INT_PRI_LINK_LIST_DONE, 0);
696
697}
698
699static void mddi_queue_forward_linked_list(void)
700{
701 uint16 first_pkt_index;
702 mddi_linked_list_type *llist_dma;
703 mddi_host_type host_idx = mddi_curr_host;
704 mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
705 llist_dma = pmhctl->llist_dma_ptr;
706
707 first_pkt_index = UNASSIGNED_INDEX;
708
709 if (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) {
710#ifndef FEATURE_MDDI_DISABLE_REVERSE
711 if (pmhctl->llist_info.reg_read_waiting) {
712 if (pmhctl->rev_state == MDDI_REV_IDLE) {
713 /*
714 * we have a register read to send and
715 * can send it now
716 */
717 pmhctl->rev_state = MDDI_REV_REG_READ_ISSUED;
718 mddi_reg_read_retry = 0;
719 first_pkt_index =
720 pmhctl->llist_info.waiting_start_idx;
721 pmhctl->llist_info.reg_read_waiting = FALSE;
722 }
723 } else
724#endif
725 {
726 /*
727 * not register read to worry about, go ahead and write
728 * anything that may be on the waiting list.
729 */
730 first_pkt_index = pmhctl->llist_info.waiting_start_idx;
731 }
732 }
733
734 if (first_pkt_index != UNASSIGNED_INDEX) {
735 pmhctl->llist_info.transmitting_start_idx =
736 pmhctl->llist_info.waiting_start_idx;
737 pmhctl->llist_info.transmitting_end_idx =
738 pmhctl->llist_info.waiting_end_idx;
739 pmhctl->llist_info.waiting_start_idx = UNASSIGNED_INDEX;
740 pmhctl->llist_info.waiting_end_idx = UNASSIGNED_INDEX;
741
742 /* write to the primary pointer register */
743 MDDI_MSG_DEBUG("MDDI writing primary ptr with idx=%d\n",
744 first_pkt_index);
745
746 pmhctl->int_type.llist_ptr_write_2++;
747
748 dma_coherent_pre_ops();
749 mddi_host_reg_out(PRI_PTR, &llist_dma[first_pkt_index]);
750
751 /* enable interrupt when complete */
752 mddi_host_reg_outm(INTEN, MDDI_INT_PRI_LINK_LIST_DONE,
753 MDDI_INT_PRI_LINK_LIST_DONE);
754
755 }
756
757}
758
759#ifndef FEATURE_MDDI_DISABLE_REVERSE
760static void mddi_read_rev_packet(byte *data_ptr)
761{
762 uint16 i, length;
763 mddi_host_type host_idx = mddi_curr_host;
764 mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
765
766 uint8 *rev_ptr_overflow =
767 (pmhctl->rev_ptr_start + MDDI_REV_BUFFER_SIZE);
768
769 /* first determine the length and handle invalid lengths */
770 length = *pmhctl->rev_ptr_curr++;
771 if (pmhctl->rev_ptr_curr >= rev_ptr_overflow)
772 pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
773 length |= ((*pmhctl->rev_ptr_curr++) << 8);
774 if (pmhctl->rev_ptr_curr >= rev_ptr_overflow)
775 pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
776 if (length > (pmhctl->rev_pkt_size - 2)) {
777 MDDI_MSG_ERR("Invalid rev pkt length %d\n", length);
778 /* rev_pkt_size should always be <= rev_ptr_size so limit to packet size */
779 length = pmhctl->rev_pkt_size - 2;
780 }
781
782 /* If the data pointer is NULL, just increment the pmhctl->rev_ptr_curr.
783 * Loop around if necessary. Don't bother reading the data.
784 */
785 if (data_ptr == NULL) {
786 pmhctl->rev_ptr_curr += length;
787 if (pmhctl->rev_ptr_curr >= rev_ptr_overflow)
788 pmhctl->rev_ptr_curr -= MDDI_REV_BUFFER_SIZE;
789 return;
790 }
791
792 data_ptr[0] = length & 0x0ff;
793 data_ptr[1] = length >> 8;
794 data_ptr += 2;
795 /* copy the data to data_ptr byte-at-a-time */
796 for (i = 0; (i < length) && (pmhctl->rev_ptr_curr < rev_ptr_overflow);
797 i++)
798 *data_ptr++ = *pmhctl->rev_ptr_curr++;
799 if (pmhctl->rev_ptr_curr >= rev_ptr_overflow)
800 pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
801 for (; (i < length) && (pmhctl->rev_ptr_curr < rev_ptr_overflow); i++)
802 *data_ptr++ = *pmhctl->rev_ptr_curr++;
803}
804
805static void mddi_process_rev_packets(void)
806{
807 uint32 rev_packet_count;
808 word i;
809 uint32 crc_errors;
810 boolean mddi_reg_read_successful = FALSE;
811 mddi_host_type host_idx = mddi_curr_host;
812 mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
813
814 pmhctl->log_parms.rev_enc_cnt++;
815 if ((pmhctl->rev_state != MDDI_REV_ENCAP_ISSUED) &&
816 (pmhctl->rev_state != MDDI_REV_STATUS_REQ_ISSUED) &&
817 (pmhctl->rev_state != MDDI_REV_CLIENT_CAP_ISSUED)) {
818 MDDI_MSG_ERR("Wrong state %d for reverse int\n",
819 pmhctl->rev_state);
820 }
821 /* Turn off MDDI_INT_REV_AVAIL interrupt */
822 mddi_host_reg_outm(INTEN, MDDI_INT_REV_DATA_AVAIL, 0);
823
824 /* Clear rev data avail int */
825 mddi_host_reg_out(INT, MDDI_INT_REV_DATA_AVAIL);
826
827 /* Get Number of packets */
828 rev_packet_count = mddi_host_reg_in(REV_PKT_CNT);
829
830#ifndef T_MSM7500
831 /* Clear out rev packet counter */
832 mddi_host_reg_out(REV_PKT_CNT, 0x0000);
833#endif
834
835#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40)
836 if ((pmhctl->rev_state == MDDI_REV_CLIENT_CAP_ISSUED) &&
837 (rev_packet_count > 0) &&
838 (mddi_host_core_version == 0x28 ||
839 mddi_host_core_version == 0x30)) {
840
841 uint32 int_reg;
842 uint32 max_count = 0;
843
844 mddi_host_reg_out(REV_PTR, pmhctl->mddi_rev_ptr_write_val);
845 int_reg = mddi_host_reg_in(INT);
846 while ((int_reg & 0x100000) == 0) {
847 udelay(3);
848 int_reg = mddi_host_reg_in(INT);
849 if (++max_count > 100)
850 break;
851 }
852 }
853#endif
854
855 /* Get CRC error count */
856 crc_errors = mddi_host_reg_in(REV_CRC_ERR);
857 if (crc_errors != 0) {
858 pmhctl->log_parms.rev_crc_cnt += crc_errors;
859 pmhctl->stats.rev_crc_count += crc_errors;
860 MDDI_MSG_ERR("!!! MDDI %d Reverse CRC Error(s) !!!\n",
861 crc_errors);
862#ifndef T_MSM7500
863 /* Clear CRC error count */
864 mddi_host_reg_out(REV_CRC_ERR, 0x0000);
865#endif
866 /* also issue an RTD to attempt recovery */
867 pmhctl->rtd_counter = mddi_rtd_frequency;
868 }
869
870 pmhctl->rtd_value = mddi_host_reg_in(RTD_VAL);
871
872 MDDI_MSG_DEBUG("MDDI rev pkt cnt=%d, ptr=0x%x, RTD:0x%x\n",
873 rev_packet_count,
874 pmhctl->rev_ptr_curr - pmhctl->rev_ptr_start,
875 pmhctl->rtd_value);
876
877 if (rev_packet_count >= 1) {
878 mddi_invalidate_cache_lines((uint32 *) pmhctl->rev_ptr_start,
879 MDDI_REV_BUFFER_SIZE);
880 }
881 /* order the reads */
882 dma_coherent_post_ops();
883 for (i = 0; i < rev_packet_count; i++) {
884 mddi_rev_packet_type *rev_pkt_ptr;
885
886 mddi_read_rev_packet(rev_packet_data);
887
888 rev_pkt_ptr = (mddi_rev_packet_type *) rev_packet_data;
889
890 if (rev_pkt_ptr->packet_length > pmhctl->rev_pkt_size) {
891 MDDI_MSG_ERR("!!!invalid packet size: %d\n",
892 rev_pkt_ptr->packet_length);
893 }
894
895 MDDI_MSG_DEBUG("MDDI rev pkt 0x%x size 0x%x\n",
896 rev_pkt_ptr->packet_type,
897 rev_pkt_ptr->packet_length);
898
899 /* Do whatever you want to do with the data based on the packet type */
900 switch (rev_pkt_ptr->packet_type) {
901 case 66: /* Client Capability */
902 {
903 mddi_client_capability_type
904 *client_capability_pkt_ptr;
905
906 client_capability_pkt_ptr =
907 (mddi_client_capability_type *)
908 rev_packet_data;
909 MDDI_MSG_NOTICE
910 ("Client Capability: Week=%d, Year=%d\n",
911 client_capability_pkt_ptr->
912 Week_of_Manufacture,
913 client_capability_pkt_ptr->
914 Year_of_Manufacture);
915 memcpy((void *)&mddi_client_capability_pkt,
916 (void *)rev_packet_data,
917 sizeof(mddi_client_capability_type));
918 pmhctl->log_parms.cli_cap_cnt++;
919 }
920 break;
921
922 case 70: /* Display Status */
923 {
924 mddi_client_status_type *client_status_pkt_ptr;
925
926 client_status_pkt_ptr =
927 (mddi_client_status_type *) rev_packet_data;
928 if ((client_status_pkt_ptr->crc_error_count !=
929 0)
930 || (client_status_pkt_ptr->
931 reverse_link_request != 0)) {
932 MDDI_MSG_ERR
933 ("Client Status: RevReq=%d, CrcErr=%d\n",
934 client_status_pkt_ptr->
935 reverse_link_request,
936 client_status_pkt_ptr->
937 crc_error_count);
938 } else {
939 MDDI_MSG_DEBUG
940 ("Client Status: RevReq=%d, CrcErr=%d\n",
941 client_status_pkt_ptr->
942 reverse_link_request,
943 client_status_pkt_ptr->
944 crc_error_count);
945 }
946 pmhctl->log_parms.fwd_crc_cnt +=
947 client_status_pkt_ptr->crc_error_count;
948 pmhctl->stats.fwd_crc_count +=
949 client_status_pkt_ptr->crc_error_count;
950 pmhctl->log_parms.cli_stat_cnt++;
951 }
952 break;
953
954 case 146: /* register access packet */
955 {
956 mddi_register_access_packet_type
957 * regacc_pkt_ptr;
958
959 regacc_pkt_ptr =
960 (mddi_register_access_packet_type *)
961 rev_packet_data;
962
963 MDDI_MSG_DEBUG
964 ("Reg Acc parse reg=0x%x, value=0x%x\n",
965 regacc_pkt_ptr->register_address,
966 regacc_pkt_ptr->register_data_list);
967
968 /* Copy register value to location passed in */
969 if (mddi_reg_read_value_ptr) {
970#if defined(T_MSM6280) && !defined(T_MSM7200)
971 /* only least significant 16 bits are valid with 6280 */
972 *mddi_reg_read_value_ptr =
973 regacc_pkt_ptr->
974 register_data_list & 0x0000ffff;
975#else
976 *mddi_reg_read_value_ptr =
977 regacc_pkt_ptr->register_data_list;
978#endif
979 mddi_reg_read_successful = TRUE;
980 mddi_reg_read_value_ptr = NULL;
981 }
982
983#ifdef DEBUG_MDDIHOSTI
984 if ((mddi_gpio.polling_enabled) &&
985 (regacc_pkt_ptr->register_address ==
986 mddi_gpio.polling_reg)) {
987 /*
988 * ToDo: need to call Linux GPIO call
989 * here...
990 */
991 mddi_client_lcd_gpio_poll(
992 regacc_pkt_ptr->register_data_list);
993 }
994#endif
995 pmhctl->log_parms.reg_read_cnt++;
996 }
997 break;
998
999 default: /* any other packet */
1000 {
1001 uint16 hdlr;
1002
1003 for (hdlr = 0; hdlr < MAX_MDDI_REV_HANDLERS;
1004 hdlr++) {
1005 if (mddi_rev_pkt_handler[hdlr].
1006 pkt_type ==
1007 rev_pkt_ptr->packet_type) {
1008 (*
1009 (mddi_rev_pkt_handler[hdlr].
1010 handler)) (rev_pkt_ptr);
1011 /* pmhctl->rev_state = MDDI_REV_IDLE; */
1012 break;
1013 }
1014 }
1015 if (hdlr >= MAX_MDDI_REV_HANDLERS)
1016 MDDI_MSG_ERR("MDDI unknown rev pkt\n");
1017 }
1018 break;
1019 }
1020 }
1021 if ((pmhctl->rev_ptr_curr + pmhctl->rev_pkt_size) >=
1022 (pmhctl->rev_ptr_start + MDDI_REV_BUFFER_SIZE)) {
1023 pmhctl->rev_ptr_written = FALSE;
1024 }
1025
1026 if (pmhctl->rev_state == MDDI_REV_ENCAP_ISSUED) {
1027 pmhctl->rev_state = MDDI_REV_IDLE;
1028 if (mddi_rev_user.waiting) {
1029 mddi_rev_user.waiting = FALSE;
1030 complete(&(mddi_rev_user.done_comp));
1031 } else if (pmhctl->llist_info.reg_read_idx == UNASSIGNED_INDEX) {
1032 MDDI_MSG_ERR
1033 ("Reverse Encap state, but no reg read in progress\n");
1034 } else {
1035 if ((!mddi_reg_read_successful) &&
1036 (mddi_reg_read_retry < mddi_reg_read_retry_max) &&
1037 (mddi_enable_reg_read_retry)) {
1038 /*
1039 * There is a race condition that can happen
1040 * where the reverse encapsulation message is
1041 * sent out by the MDDI host before the register
1042 * read packet is sent. As a work-around for
1043 * that problem we issue the reverse
1044 * encapsulation one more time before giving up.
1045 */
1046 if (mddi_enable_reg_read_retry_once)
1047 mddi_reg_read_retry =
1048 mddi_reg_read_retry_max;
1049 pmhctl->rev_state = MDDI_REV_REG_READ_SENT;
1050 pmhctl->stats.reg_read_failure++;
1051 } else {
1052 uint16 reg_read_idx =
1053 pmhctl->llist_info.reg_read_idx;
1054
1055 mddi_reg_read_retry = 0;
1056 if (pmhctl->llist_notify[reg_read_idx].waiting) {
1057 complete(&
1058 (pmhctl->
1059 llist_notify[reg_read_idx].
1060 done_comp));
1061 }
1062 pmhctl->llist_info.reg_read_idx =
1063 UNASSIGNED_INDEX;
1064 if (pmhctl->llist_notify[reg_read_idx].
1065 done_cb != NULL) {
1066 (*
1067 (pmhctl->llist_notify[reg_read_idx].
1068 done_cb)) ();
1069 }
1070 pmhctl->llist_notify[reg_read_idx].next_idx =
1071 UNASSIGNED_INDEX;
1072 pmhctl->llist_notify[reg_read_idx].in_use =
1073 FALSE;
1074 pmhctl->llist_notify[reg_read_idx].waiting =
1075 FALSE;
1076 pmhctl->llist_notify[reg_read_idx].done_cb =
1077 NULL;
1078 if (!mddi_reg_read_successful)
1079 pmhctl->stats.reg_read_failure++;
1080 }
1081 }
1082 } else if (pmhctl->rev_state == MDDI_REV_CLIENT_CAP_ISSUED) {
1083#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40)
1084 if (mddi_host_core_version == 0x28 ||
1085 mddi_host_core_version == 0x30) {
1086 mddi_host_reg_out(FIFO_ALLOC, 0x00);
1087 pmhctl->rev_ptr_written = TRUE;
1088 mddi_host_reg_out(REV_PTR,
1089 pmhctl->mddi_rev_ptr_write_val);
1090 pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
1091 mddi_host_reg_out(CMD, 0xC00);
1092 }
1093#endif
1094
1095 if (mddi_rev_user.waiting) {
1096 mddi_rev_user.waiting = FALSE;
1097 complete(&(mddi_rev_user.done_comp));
1098 }
1099 pmhctl->rev_state = MDDI_REV_IDLE;
1100 } else {
1101 pmhctl->rev_state = MDDI_REV_IDLE;
1102 }
1103
1104 /* pmhctl->rev_state = MDDI_REV_IDLE; */
1105
1106 /* Re-enable interrupt */
1107 mddi_host_reg_outm(INTEN, MDDI_INT_REV_DATA_AVAIL,
1108 MDDI_INT_REV_DATA_AVAIL);
1109
1110}
1111
1112static void mddi_issue_reverse_encapsulation(void)
1113{
1114 mddi_host_type host_idx = mddi_curr_host;
1115 mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
1116 /* Only issue a reverse encapsulation packet if:
1117 * 1) another reverse is not in progress (MDDI_REV_IDLE).
1118 * 2) a register read has been sent (MDDI_REV_REG_READ_SENT).
1119 * 3) forward is not in progress, because of a hw bug in client that
1120 * causes forward crc errors on packet immediately after rev encap.
1121 */
1122 if (((pmhctl->rev_state == MDDI_REV_IDLE) ||
1123 (pmhctl->rev_state == MDDI_REV_REG_READ_SENT)) &&
1124 (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) &&
1125 (!mdp_in_processing)) {
1126 uint32 mddi_command = MDDI_CMD_SEND_REV_ENCAP;
1127
1128 if ((pmhctl->rev_state == MDDI_REV_REG_READ_SENT) ||
1129 (mddi_rev_encap_user_request == TRUE)) {
1130 mddi_host_enable_io_clock();
1131 if (pmhctl->link_state == MDDI_LINK_HIBERNATING) {
1132 /* need to wake up link before issuing rev encap command */
1133 MDDI_MSG_DEBUG("wake up link!\n");
1134 pmhctl->link_state = MDDI_LINK_ACTIVATING;
1135 mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE);
1136 } else {
1137 if (pmhctl->rtd_counter >= mddi_rtd_frequency) {
1138 MDDI_MSG_DEBUG
1139 ("mddi sending RTD command!\n");
1140 mddi_host_reg_out(CMD,
1141 MDDI_CMD_SEND_RTD);
1142 pmhctl->rtd_counter = 0;
1143 pmhctl->log_parms.rtd_cnt++;
1144 }
1145 if (pmhctl->rev_state != MDDI_REV_REG_READ_SENT) {
1146 /* this is generic reverse request by user, so
1147 * reset the waiting flag. */
1148 mddi_rev_encap_user_request = FALSE;
1149 }
1150 /* link is active so send reverse encap to get register read results */
1151 pmhctl->rev_state = MDDI_REV_ENCAP_ISSUED;
1152 mddi_command = MDDI_CMD_SEND_REV_ENCAP;
1153 MDDI_MSG_DEBUG("sending rev encap!\n");
1154 }
1155 } else
1156 if ((pmhctl->client_status_cnt >=
1157 mddi_client_status_frequency)
1158 || mddi_client_capability_request) {
1159 mddi_host_enable_io_clock();
1160 if (pmhctl->link_state == MDDI_LINK_HIBERNATING) {
1161 /* only wake up the link if it client status is overdue */
1162 if ((pmhctl->client_status_cnt >=
1163 (mddi_client_status_frequency * 2))
1164 || mddi_client_capability_request) {
1165 /* need to wake up link before issuing rev encap command */
1166 MDDI_MSG_DEBUG("wake up link!\n");
1167 pmhctl->link_state =
1168 MDDI_LINK_ACTIVATING;
1169 mddi_host_reg_out(CMD,
1170 MDDI_CMD_LINK_ACTIVE);
1171 }
1172 } else {
1173 if (pmhctl->rtd_counter >= mddi_rtd_frequency) {
1174 MDDI_MSG_DEBUG
1175 ("mddi sending RTD command!\n");
1176 mddi_host_reg_out(CMD,
1177 MDDI_CMD_SEND_RTD);
1178 pmhctl->rtd_counter = 0;
1179 pmhctl->log_parms.rtd_cnt++;
1180 }
1181 /* periodically get client status */
1182 MDDI_MSG_DEBUG
1183 ("mddi sending rev enc! (get status)\n");
1184 if (mddi_client_capability_request) {
1185 pmhctl->rev_state =
1186 MDDI_REV_CLIENT_CAP_ISSUED;
1187 mddi_command = MDDI_CMD_GET_CLIENT_CAP;
1188 mddi_client_capability_request = FALSE;
1189 } else {
1190 pmhctl->rev_state =
1191 MDDI_REV_STATUS_REQ_ISSUED;
1192 pmhctl->client_status_cnt = 0;
1193 mddi_command =
1194 MDDI_CMD_GET_CLIENT_STATUS;
1195 }
1196 }
1197 }
1198 if ((pmhctl->rev_state == MDDI_REV_ENCAP_ISSUED) ||
1199 (pmhctl->rev_state == MDDI_REV_STATUS_REQ_ISSUED) ||
1200 (pmhctl->rev_state == MDDI_REV_CLIENT_CAP_ISSUED)) {
1201 pmhctl->int_type.rev_encap_count++;
1202#if defined(T_MSM6280) && !defined(T_MSM7200)
1203 mddi_rev_pointer_written = TRUE;
1204 mddi_host_reg_out(REV_PTR, mddi_rev_ptr_write_val);
1205 mddi_rev_ptr_curr = mddi_rev_ptr_start;
1206 /* force new rev ptr command */
1207 mddi_host_reg_out(CMD, 0xC00);
1208#else
1209 if (!pmhctl->rev_ptr_written) {
1210 MDDI_MSG_DEBUG("writing reverse pointer!\n");
1211 pmhctl->rev_ptr_written = TRUE;
1212#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40)
1213 if ((pmhctl->rev_state ==
1214 MDDI_REV_CLIENT_CAP_ISSUED) &&
1215 (mddi_host_core_version == 0x28 ||
1216 mddi_host_core_version == 0x30)) {
1217 pmhctl->rev_ptr_written = FALSE;
1218 mddi_host_reg_out(FIFO_ALLOC, 0x02);
1219 } else
1220 mddi_host_reg_out(REV_PTR,
1221 pmhctl->
1222 mddi_rev_ptr_write_val);
1223#else
1224 mddi_host_reg_out(REV_PTR,
1225 pmhctl->
1226 mddi_rev_ptr_write_val);
1227#endif
1228 }
1229#endif
1230 if (mddi_debug_clear_rev_data) {
1231 uint16 i;
1232 for (i = 0; i < MDDI_MAX_REV_DATA_SIZE / 4; i++)
1233 pmhctl->rev_data_buf[i] = 0xdddddddd;
1234 /* clean cache */
1235 mddi_flush_cache_lines(pmhctl->rev_data_buf,
1236 MDDI_MAX_REV_DATA_SIZE);
1237 }
1238
1239 /* send reverse encapsulation to get needed data */
1240 mddi_host_reg_out(CMD, mddi_command);
1241 }
1242 }
1243
1244}
1245
1246static void mddi_process_client_initiated_wakeup(void)
1247{
1248 mddi_host_type host_idx = mddi_curr_host;
1249 mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
1250
1251 /* Disable MDDI_INT Interrupt, we detect client initiated wakeup one
1252 * time for each entry into hibernation */
1253 mddi_host_reg_outm(INTEN, MDDI_INT_MDDI_IN, 0);
1254
1255 if (host_idx == MDDI_HOST_PRIM) {
1256 if (mddi_vsync_detect_enabled) {
1257 mddi_host_enable_io_clock();
1258#ifndef MDDI_HOST_DISP_LISTEN
1259 /* issue command to bring up link */
1260 /* need to do this to clear the vsync condition */
1261 if (pmhctl->link_state == MDDI_LINK_HIBERNATING) {
1262 pmhctl->link_state = MDDI_LINK_ACTIVATING;
1263 mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE);
1264 }
1265#endif
1266 /*
1267 * Indicate to client specific code that vsync was
1268 * enabled, and we did not detect a client initiated
1269 * wakeup. The client specific handler can clear the
1270 * condition if necessary to prevent subsequent
1271 * client initiated wakeups.
1272 */
1273 mddi_client_lcd_vsync_detected(TRUE);
1274 pmhctl->log_parms.vsync_response_cnt++;
1275 MDDI_MSG_NOTICE("MDDI_INT_IN condition\n");
1276
1277 }
1278 }
1279
1280 if (mddi_gpio.polling_enabled) {
1281 mddi_host_enable_io_clock();
1282 /* check interrupt status now */
1283 (void)mddi_queue_register_read_int(mddi_gpio.polling_reg,
1284 &mddi_gpio.polling_val);
1285 }
1286}
1287#endif /* FEATURE_MDDI_DISABLE_REVERSE */
1288
1289static void mddi_host_isr(void)
1290{
1291 uint32 int_reg, int_en;
1292#ifndef FEATURE_MDDI_DISABLE_REVERSE
1293 uint32 status_reg;
1294#endif
1295 mddi_host_type host_idx = mddi_curr_host;
1296 mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
1297
1298 if (!MDDI_HOST_IS_HCLK_ON) {
1299 MDDI_HOST_ENABLE_HCLK;
1300 MDDI_MSG_DEBUG("HCLK disabled, but isr is firing\n");
1301 }
1302 int_reg = mddi_host_reg_in(INT);
1303 int_en = mddi_host_reg_in(INTEN);
1304 pmhctl->saved_int_reg = int_reg;
1305 pmhctl->saved_int_en = int_en;
1306 int_reg = int_reg & int_en;
1307 pmhctl->int_type.count++;
1308
1309
1310#ifndef FEATURE_MDDI_DISABLE_REVERSE
1311 status_reg = mddi_host_reg_in(STAT);
1312
1313 if ((int_reg & MDDI_INT_MDDI_IN) ||
1314 ((int_en & MDDI_INT_MDDI_IN) &&
1315 ((int_reg == 0) || (status_reg & MDDI_STAT_CLIENT_WAKEUP_REQ)))) {
1316 /*
1317 * The MDDI_IN condition will clear itself, and so it is
1318 * possible that MDDI_IN was the reason for the isr firing,
1319 * even though the interrupt register does not have the
1320 * MDDI_IN bit set. To check if this was the case we need to
1321 * look at the status register bit that signifies a client
1322 * initiated wakeup. If the status register bit is set, as well
1323 * as the MDDI_IN interrupt enabled, then we treat this as a
1324 * client initiated wakeup.
1325 */
1326 if (int_reg & MDDI_INT_MDDI_IN)
1327 pmhctl->int_type.in_count++;
1328 mddi_process_client_initiated_wakeup();
1329 }
1330#endif
1331
1332 if (int_reg & MDDI_INT_LINK_STATE_CHANGES) {
1333 pmhctl->int_type.state_change_count++;
1334 mddi_report_state_change(int_reg);
1335 }
1336
1337 if (int_reg & MDDI_INT_PRI_LINK_LIST_DONE) {
1338 pmhctl->int_type.ll_done_count++;
1339 mddi_process_link_list_done();
1340 }
1341#ifndef FEATURE_MDDI_DISABLE_REVERSE
1342 if (int_reg & MDDI_INT_REV_DATA_AVAIL) {
1343 pmhctl->int_type.rev_avail_count++;
1344 mddi_process_rev_packets();
1345 }
1346#endif
1347
1348 if (int_reg & MDDI_INT_ERROR_CONDITIONS) {
1349 pmhctl->int_type.error_count++;
1350 mddi_report_errors(int_reg);
1351
1352 mddi_host_reg_out(INT, int_reg & MDDI_INT_ERROR_CONDITIONS);
1353 }
1354#ifndef FEATURE_MDDI_DISABLE_REVERSE
1355 mddi_issue_reverse_encapsulation();
1356
1357 if ((pmhctl->rev_state != MDDI_REV_ENCAP_ISSUED) &&
1358 (pmhctl->rev_state != MDDI_REV_STATUS_REQ_ISSUED))
1359#endif
1360 /* don't want simultaneous reverse and forward with Eagle */
1361 mddi_queue_forward_linked_list();
1362
1363 if (int_reg & MDDI_INT_NO_CMD_PKTS_PEND) {
1364 /* this interrupt is used to kick the isr when hibernation is disabled */
1365 mddi_host_reg_outm(INTEN, MDDI_INT_NO_CMD_PKTS_PEND, 0);
1366 }
1367
1368 if ((!mddi_host_mdp_active_flag) &&
1369 (!mddi_vsync_detect_enabled) &&
1370 (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) &&
1371 (pmhctl->llist_info.waiting_start_idx == UNASSIGNED_INDEX) &&
1372 (pmhctl->rev_state == MDDI_REV_IDLE)) {
1373 if (pmhctl->link_state == MDDI_LINK_HIBERNATING) {
1374 mddi_host_disable_io_clock();
1375 mddi_host_disable_hclk();
1376 }
1377#ifdef FEATURE_MDDI_HOST_ENABLE_EARLY_HIBERNATION
1378 else if ((pmhctl->link_state == MDDI_LINK_ACTIVE) &&
1379 (!pmhctl->disable_hibernation)) {
1380 mddi_host_reg_out(CMD, MDDI_CMD_POWERDOWN);
1381 }
1382#endif
1383 }
1384}
1385
1386static void mddi_host_isr_primary(void)
1387{
1388 mddi_curr_host = MDDI_HOST_PRIM;
1389 mddi_host_isr();
1390}
1391
1392irqreturn_t mddi_pmdh_isr_proxy(int irq, void *ptr)
1393{
1394 mddi_host_isr_primary();
1395 return IRQ_HANDLED;
1396}
1397
1398static void mddi_host_isr_external(void)
1399{
1400 mddi_curr_host = MDDI_HOST_EXT;
1401 mddi_host_isr();
1402 mddi_curr_host = MDDI_HOST_PRIM;
1403}
1404
1405irqreturn_t mddi_emdh_isr_proxy(int irq, void *ptr)
1406{
1407 mddi_host_isr_external();
1408 return IRQ_HANDLED;
1409}
1410
1411static void mddi_host_initialize_registers(mddi_host_type host_idx)
1412{
1413 uint32 pad_reg_val;
1414 mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
1415
1416 if (pmhctl->driver_state == MDDI_DRIVER_ENABLED)
1417 return;
1418
1419 /* turn on HCLK to MDDI host core */
1420 mddi_host_enable_hclk();
1421
1422 /* MDDI Reset command */
1423 mddi_host_reg_out(CMD, MDDI_CMD_RESET);
1424
1425 /* Version register (= 0x01) */
1426 mddi_host_reg_out(VERSION, 0x0001);
1427
1428 /* Bytes per subframe register */
1429 mddi_host_reg_out(BPS, MDDI_HOST_BYTES_PER_SUBFRAME);
1430
1431 /* Subframes per media frames register (= 0x03) */
1432 mddi_host_reg_out(SPM, 0x0003);
1433
1434 /* Turn Around 1 register (= 0x05) */
1435 mddi_host_reg_out(TA1_LEN, 0x0005);
1436
1437 /* Turn Around 2 register (= 0x0C) */
1438 mddi_host_reg_out(TA2_LEN, MDDI_HOST_TA2_LEN);
1439
1440 /* Drive hi register (= 0x96) */
1441 mddi_host_reg_out(DRIVE_HI, 0x0096);
1442
1443 /* Drive lo register (= 0x32) */
1444 mddi_host_reg_out(DRIVE_LO, 0x0032);
1445
1446 /* Display wakeup count register (= 0x3c) */
1447 mddi_host_reg_out(DISP_WAKE, 0x003c);
1448
1449 /* Reverse Rate Divisor register (= 0x2) */
1450 mddi_host_reg_out(REV_RATE_DIV, MDDI_HOST_REV_RATE_DIV);
1451
1452#ifndef FEATURE_MDDI_DISABLE_REVERSE
1453 /* Reverse Pointer Size */
1454 mddi_host_reg_out(REV_SIZE, MDDI_REV_BUFFER_SIZE);
1455
1456 /* Rev Encap Size */
1457 mddi_host_reg_out(REV_ENCAP_SZ, pmhctl->rev_pkt_size);
1458#endif
1459
1460 /* Periodic Rev Encap */
1461 /* don't send periodically */
1462 mddi_host_reg_out(CMD, MDDI_CMD_PERIODIC_REV_ENCAP);
1463
1464 pad_reg_val = mddi_host_reg_in(PAD_CTL);
1465 if (pad_reg_val == 0) {
1466 /* If we are turning on band gap, need to wait 5us before turning
1467 * on the rest of the PAD */
1468 mddi_host_reg_out(PAD_CTL, 0x08000);
1469 udelay(5);
1470 }
1471#ifdef T_MSM7200
1472 /* Recommendation from PAD hw team */
1473 mddi_host_reg_out(PAD_CTL, 0xa850a);
1474#else
1475 /* Recommendation from PAD hw team */
1476 mddi_host_reg_out(PAD_CTL, 0xa850f);
1477#endif
1478
1479#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40)
1480 mddi_host_reg_out(PAD_IO_CTL, 0x00320000);
1481 mddi_host_reg_out(PAD_CAL, 0x00220020);
1482#endif
1483
1484 mddi_host_core_version = mddi_host_reg_inm(CORE_VER, 0xffff);
1485
1486#ifndef FEATURE_MDDI_DISABLE_REVERSE
1487 if (mddi_host_core_version >= 8)
1488 mddi_rev_ptr_workaround = FALSE;
1489 pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
1490#endif
1491
1492 if ((mddi_host_core_version > 8) && (mddi_host_core_version < 0x19))
1493 mddi_host_reg_out(TEST, 0x2);
1494
1495 /* Need an even number for counts */
1496 mddi_host_reg_out(DRIVER_START_CNT, 0x60006);
1497
1498#ifndef T_MSM7500
1499 /* Setup defaults for MDP related register */
1500 mddi_host_reg_out(MDP_VID_FMT_DES, 0x5666);
1501 mddi_host_reg_out(MDP_VID_PIX_ATTR, 0x00C3);
1502 mddi_host_reg_out(MDP_VID_CLIENTID, 0);
1503#endif
1504
1505 /* automatically hibernate after 1 empty subframe */
1506 if (pmhctl->disable_hibernation)
1507 mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE);
1508 else
1509 mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE | 1);
1510
1511 /* Bring up link if display (client) requests it */
1512#ifdef MDDI_HOST_DISP_LISTEN
1513 mddi_host_reg_out(CMD, MDDI_CMD_DISP_LISTEN);
1514#else
1515 mddi_host_reg_out(CMD, MDDI_CMD_DISP_IGNORE);
1516#endif
1517
1518}
1519
1520void mddi_host_configure_interrupts(mddi_host_type host_idx, boolean enable)
1521{
1522 unsigned long flags;
1523 mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
1524
1525 spin_lock_irqsave(&mddi_host_spin_lock, flags);
1526
1527 /* turn on HCLK to MDDI host core if it has been disabled */
1528 mddi_host_enable_hclk();
1529 /* Clear MDDI Interrupt enable reg */
1530 mddi_host_reg_out(INTEN, 0);
1531
1532 spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
1533
1534 if (enable) {
1535 pmhctl->driver_state = MDDI_DRIVER_ENABLED;
1536
1537 if (host_idx == MDDI_HOST_PRIM) {
1538 if (request_irq
1539 (INT_MDDI_PRI, mddi_pmdh_isr_proxy, IRQF_DISABLED,
1540 "PMDH", 0) != 0)
1541 printk(KERN_ERR
1542 "a mddi: unable to request_irq\n");
1543 else
1544 int_mddi_pri_flag = TRUE;
1545 } else {
1546 if (request_irq
1547 (INT_MDDI_EXT, mddi_emdh_isr_proxy, IRQF_DISABLED,
1548 "EMDH", 0) != 0)
1549 printk(KERN_ERR
1550 "b mddi: unable to request_irq\n");
1551 else
1552 int_mddi_ext_flag = TRUE;
1553 }
1554
1555 /* Set MDDI Interrupt enable reg -- Enable Reverse data avail */
1556#ifdef FEATURE_MDDI_DISABLE_REVERSE
1557 mddi_host_reg_out(INTEN,
1558 MDDI_INT_ERROR_CONDITIONS |
1559 MDDI_INT_LINK_STATE_CHANGES);
1560#else
1561 /* Reverse Pointer register */
1562 pmhctl->rev_ptr_written = FALSE;
1563
1564 mddi_host_reg_out(INTEN,
1565 MDDI_INT_REV_DATA_AVAIL |
1566 MDDI_INT_ERROR_CONDITIONS |
1567 MDDI_INT_LINK_STATE_CHANGES);
1568 pmhctl->rtd_counter = mddi_rtd_frequency;
1569 pmhctl->client_status_cnt = 0;
1570#endif
1571 } else {
1572 if (pmhctl->driver_state == MDDI_DRIVER_ENABLED)
1573 pmhctl->driver_state = MDDI_DRIVER_DISABLED;
1574 }
1575
1576}
1577
1578static void mddi_host_powerup(mddi_host_type host_idx)
1579{
1580 mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
1581
1582 if (pmhctl->link_state != MDDI_LINK_DISABLED)
1583 return;
1584
1585 /* enable IO_CLK and hclk to MDDI host core */
1586 mddi_host_enable_io_clock();
1587
1588 mddi_host_initialize_registers(host_idx);
1589 mddi_host_configure_interrupts(host_idx, TRUE);
1590
1591 pmhctl->link_state = MDDI_LINK_ACTIVATING;
1592
1593 /* Link activate command */
1594 mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE);
1595
1596#ifdef CLKRGM_MDDI_IO_CLOCK_IN_MHZ
1597 MDDI_MSG_NOTICE("MDDI Host: Activating Link %d Mbps\n",
1598 CLKRGM_MDDI_IO_CLOCK_IN_MHZ * 2);
1599#else
1600 MDDI_MSG_NOTICE("MDDI Host: Activating Link\n");
1601#endif
1602
1603 /* Initialize the timer */
1604 if (host_idx == MDDI_HOST_PRIM)
1605 mddi_host_timer_service(0);
1606}
1607
1608void mddi_host_init(mddi_host_type host_idx)
1609/* Write out the MDDI configuration registers */
1610{
1611 static boolean initialized = FALSE;
1612 mddi_host_cntl_type *pmhctl;
1613
1614 if (host_idx >= MDDI_NUM_HOST_CORES) {
1615 MDDI_MSG_ERR("Invalid host core index\n");
1616 return;
1617 }
1618
1619 if (!initialized) {
1620 uint16 idx;
1621 mddi_host_type host;
1622 for (host = MDDI_HOST_PRIM; host < MDDI_NUM_HOST_CORES; host++) {
1623 pmhctl = &(mhctl[host]);
1624 initialized = TRUE;
1625
1626 pmhctl->llist_ptr =
1627 dma_alloc_coherent(NULL, MDDI_LLIST_POOL_SIZE,
1628 &(pmhctl->llist_dma_addr),
1629 GFP_KERNEL);
1630 pmhctl->llist_dma_ptr =
1631 (mddi_linked_list_type *) (void *)pmhctl->
1632 llist_dma_addr;
1633#ifdef FEATURE_MDDI_DISABLE_REVERSE
1634 pmhctl->rev_data_buf = NULL;
1635 if (pmhctl->llist_ptr == NULL)
1636#else
1637 mddi_rev_user.waiting = FALSE;
1638 init_completion(&(mddi_rev_user.done_comp));
1639 pmhctl->rev_data_buf =
1640 dma_alloc_coherent(NULL, MDDI_MAX_REV_DATA_SIZE,
1641 &(pmhctl->rev_data_dma_addr),
1642 GFP_KERNEL);
1643 if ((pmhctl->llist_ptr == NULL)
1644 || (pmhctl->rev_data_buf == NULL))
1645#endif
1646 {
1647 MDDI_MSG_CRIT
1648 ("unable to alloc non-cached memory\n");
1649 }
1650 llist_extern[host] = pmhctl->llist_ptr;
1651 llist_dma_extern[host] = pmhctl->llist_dma_ptr;
1652 llist_extern_notify[host] = pmhctl->llist_notify;
1653
1654 for (idx = 0; idx < UNASSIGNED_INDEX; idx++) {
1655 init_completion(&
1656 (pmhctl->llist_notify[idx].
1657 done_comp));
1658 }
1659 init_completion(&(pmhctl->mddi_llist_avail_comp));
1660 spin_lock_init(&mddi_host_spin_lock);
1661 pmhctl->mddi_waiting_for_llist_avail = FALSE;
1662 pmhctl->mddi_rev_ptr_write_val =
1663 (uint32) (void *)(pmhctl->rev_data_dma_addr);
1664 pmhctl->rev_ptr_start = (void *)pmhctl->rev_data_buf;
1665
1666 pmhctl->rev_pkt_size = MDDI_DEFAULT_REV_PKT_SIZE;
1667 pmhctl->rev_state = MDDI_REV_IDLE;
1668#ifdef IMAGE_MODEM_PROC
1669 /* assume hibernation state is last state from APPS proc, so that
1670 * we don't reinitialize the host core */
1671 pmhctl->link_state = MDDI_LINK_HIBERNATING;
1672#else
1673 pmhctl->link_state = MDDI_LINK_DISABLED;
1674#endif
1675 pmhctl->driver_state = MDDI_DRIVER_DISABLED;
1676 pmhctl->disable_hibernation = FALSE;
1677
1678 /* initialize llist variables */
1679 pmhctl->llist_info.transmitting_start_idx =
1680 UNASSIGNED_INDEX;
1681 pmhctl->llist_info.transmitting_end_idx =
1682 UNASSIGNED_INDEX;
1683 pmhctl->llist_info.waiting_start_idx = UNASSIGNED_INDEX;
1684 pmhctl->llist_info.waiting_end_idx = UNASSIGNED_INDEX;
1685 pmhctl->llist_info.reg_read_idx = UNASSIGNED_INDEX;
1686 pmhctl->llist_info.next_free_idx =
1687 MDDI_FIRST_DYNAMIC_LLIST_IDX;
1688 pmhctl->llist_info.reg_read_waiting = FALSE;
1689
1690 mddi_vsync_detect_enabled = FALSE;
1691 mddi_gpio.polling_enabled = FALSE;
1692
1693 pmhctl->int_type.count = 0;
1694 pmhctl->int_type.in_count = 0;
1695 pmhctl->int_type.disp_req_count = 0;
1696 pmhctl->int_type.state_change_count = 0;
1697 pmhctl->int_type.ll_done_count = 0;
1698 pmhctl->int_type.rev_avail_count = 0;
1699 pmhctl->int_type.error_count = 0;
1700 pmhctl->int_type.rev_encap_count = 0;
1701 pmhctl->int_type.llist_ptr_write_1 = 0;
1702 pmhctl->int_type.llist_ptr_write_2 = 0;
1703
1704 pmhctl->stats.fwd_crc_count = 0;
1705 pmhctl->stats.rev_crc_count = 0;
1706 pmhctl->stats.pri_underflow = 0;
1707 pmhctl->stats.sec_underflow = 0;
1708 pmhctl->stats.rev_overflow = 0;
1709 pmhctl->stats.pri_overwrite = 0;
1710 pmhctl->stats.sec_overwrite = 0;
1711 pmhctl->stats.rev_overwrite = 0;
1712 pmhctl->stats.dma_failure = 0;
1713 pmhctl->stats.rtd_failure = 0;
1714 pmhctl->stats.reg_read_failure = 0;
1715#ifdef FEATURE_MDDI_UNDERRUN_RECOVERY
1716 pmhctl->stats.pri_underrun_detected = 0;
1717#endif
1718
1719 pmhctl->log_parms.rtd_cnt = 0;
1720 pmhctl->log_parms.rev_enc_cnt = 0;
1721 pmhctl->log_parms.vid_cnt = 0;
1722 pmhctl->log_parms.reg_acc_cnt = 0;
1723 pmhctl->log_parms.cli_stat_cnt = 0;
1724 pmhctl->log_parms.cli_cap_cnt = 0;
1725 pmhctl->log_parms.reg_read_cnt = 0;
1726 pmhctl->log_parms.link_active_cnt = 0;
1727 pmhctl->log_parms.link_hibernate_cnt = 0;
1728 pmhctl->log_parms.fwd_crc_cnt = 0;
1729 pmhctl->log_parms.rev_crc_cnt = 0;
1730 pmhctl->log_parms.vsync_response_cnt = 0;
1731
1732 prev_parms[host_idx] = pmhctl->log_parms;
1733 mddi_client_capability_pkt.packet_length = 0;
1734 }
1735
1736#ifndef T_MSM7500
1737 /* tell clock driver we are user of this PLL */
1738 MDDI_HOST_ENABLE_IO_CLOCK;
1739#endif
1740 }
1741
1742 mddi_host_powerup(host_idx);
1743 pmhctl = &(mhctl[host_idx]);
1744}
1745
1746#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
1747static uint32 mddi_client_id;
1748
1749uint32 mddi_get_client_id(void)
1750{
1751
1752#ifndef FEATURE_MDDI_DISABLE_REVERSE
1753 mddi_host_type host_idx = MDDI_HOST_PRIM;
1754 static boolean client_detection_try = FALSE;
1755 mddi_host_cntl_type *pmhctl;
1756 unsigned long flags;
1757 uint16 saved_rev_pkt_size;
1758
1759 if (!client_detection_try) {
1760 /* Toshiba display requires larger drive_lo value */
1761 mddi_host_reg_out(DRIVE_LO, 0x0050);
1762
1763 pmhctl = &(mhctl[MDDI_HOST_PRIM]);
1764
1765 saved_rev_pkt_size = pmhctl->rev_pkt_size;
1766
1767 /* Increase Rev Encap Size */
1768 pmhctl->rev_pkt_size = MDDI_CLIENT_CAPABILITY_REV_PKT_SIZE;
1769 mddi_host_reg_out(REV_ENCAP_SZ, pmhctl->rev_pkt_size);
1770
1771 /* disable hibernation temporarily */
1772 if (!pmhctl->disable_hibernation)
1773 mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE);
1774
1775 mddi_rev_user.waiting = TRUE;
1776 INIT_COMPLETION(mddi_rev_user.done_comp);
1777
1778 spin_lock_irqsave(&mddi_host_spin_lock, flags);
1779
1780 /* turn on clock(s), if they have been disabled */
1781 mddi_host_enable_hclk();
1782 mddi_host_enable_io_clock();
1783
1784 mddi_client_capability_request = TRUE;
1785
1786 if (pmhctl->rev_state == MDDI_REV_IDLE) {
1787 /* attempt to send the reverse encapsulation now */
1788 mddi_issue_reverse_encapsulation();
1789 }
1790 spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
1791
1792 wait_for_completion_killable(&(mddi_rev_user.done_comp));
1793
1794 /* Set Rev Encap Size back to its original value */
1795 pmhctl->rev_pkt_size = saved_rev_pkt_size;
1796 mddi_host_reg_out(REV_ENCAP_SZ, pmhctl->rev_pkt_size);
1797
1798 /* reenable auto-hibernate */
1799 if (!pmhctl->disable_hibernation)
1800 mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE | 1);
1801
1802 mddi_host_reg_out(DRIVE_LO, 0x0032);
1803 client_detection_try = TRUE;
1804
1805 mddi_client_id = (mddi_client_capability_pkt.Mfr_Name<<16) |
1806 mddi_client_capability_pkt.Product_Code;
1807
1808 if (!mddi_client_id)
1809 mddi_disable(1);
1810 }
1811
1812#if 0
1813 switch (mddi_client_capability_pkt.Mfr_Name) {
1814 case 0x4474:
1815 if ((mddi_client_capability_pkt.Product_Code != 0x8960) &&
1816 (target == DISPLAY_1)) {
1817 ret = PRISM_WVGA;
1818 }
1819 break;
1820
1821 case 0xD263:
1822 if (target == DISPLAY_1)
1823 ret = TOSHIBA_VGA_PRIM;
1824 else if (target == DISPLAY_2)
1825 ret = TOSHIBA_QCIF_SECD;
1826 break;
1827
1828 case 0:
1829 if (mddi_client_capability_pkt.Product_Code == 0x8835) {
1830 if (target == DISPLAY_1)
1831 ret = SHARP_QVGA_PRIM;
1832 else if (target == DISPLAY_2)
1833 ret = SHARP_128x128_SECD;
1834 }
1835 break;
1836
1837 default:
1838 break;
1839 }
1840
1841 if ((!client_detection_try) && (ret != TOSHIBA_VGA_PRIM)
1842 && (ret != TOSHIBA_QCIF_SECD)) {
1843 /* Not a Toshiba display, so change drive_lo back to default value */
1844 mddi_host_reg_out(DRIVE_LO, 0x0032);
1845 }
1846#endif
1847
1848#endif
1849
1850 return mddi_client_id;
1851}
1852#endif
1853
1854void mddi_host_powerdown(mddi_host_type host_idx)
1855{
1856 mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
1857
1858 if (host_idx >= MDDI_NUM_HOST_CORES) {
1859 MDDI_MSG_ERR("Invalid host core index\n");
1860 return;
1861 }
1862
1863 if (pmhctl->driver_state == MDDI_DRIVER_RESET) {
1864 return;
1865 }
1866
1867 if (host_idx == MDDI_HOST_PRIM) {
1868 /* disable timer */
1869 del_timer(&mddi_host_timer);
1870 }
1871
1872 mddi_host_configure_interrupts(host_idx, FALSE);
1873
1874 /* turn on HCLK to MDDI host core if it has been disabled */
1875 mddi_host_enable_hclk();
1876
1877 /* MDDI Reset command */
1878 mddi_host_reg_out(CMD, MDDI_CMD_RESET);
1879
1880 /* Pad Control Register */
1881 mddi_host_reg_out(PAD_CTL, 0x0);
1882
1883 /* disable IO_CLK and hclk to MDDI host core */
1884 mddi_host_disable_io_clock();
1885 mddi_host_disable_hclk();
1886
1887 pmhctl->link_state = MDDI_LINK_DISABLED;
1888 pmhctl->driver_state = MDDI_DRIVER_RESET;
1889
1890 MDDI_MSG_NOTICE("MDDI Host: Disabling Link\n");
1891
1892}
1893
1894uint16 mddi_get_next_free_llist_item(mddi_host_type host_idx, boolean wait)
1895{
1896 unsigned long flags;
1897 uint16 ret_idx;
1898 boolean forced_wait = FALSE;
1899 mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
1900
1901 ret_idx = pmhctl->llist_info.next_free_idx;
1902
1903 pmhctl->llist_info.next_free_idx++;
1904 if (pmhctl->llist_info.next_free_idx >= MDDI_NUM_DYNAMIC_LLIST_ITEMS)
1905 pmhctl->llist_info.next_free_idx = MDDI_FIRST_DYNAMIC_LLIST_IDX;
1906 spin_lock_irqsave(&mddi_host_spin_lock, flags);
1907 if (pmhctl->llist_notify[ret_idx].in_use) {
1908 if (!wait) {
1909 pmhctl->llist_info.next_free_idx = ret_idx;
1910 ret_idx = UNASSIGNED_INDEX;
1911 } else {
1912 forced_wait = TRUE;
1913 INIT_COMPLETION(pmhctl->mddi_llist_avail_comp);
1914 }
1915 }
1916 spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
1917
1918 if (forced_wait) {
1919 wait_for_completion_killable(&
1920 (pmhctl->
1921 mddi_llist_avail_comp));
1922 MDDI_MSG_ERR("task waiting on mddi llist item\n");
1923 }
1924
1925 if (ret_idx != UNASSIGNED_INDEX) {
1926 pmhctl->llist_notify[ret_idx].waiting = FALSE;
1927 pmhctl->llist_notify[ret_idx].done_cb = NULL;
1928 pmhctl->llist_notify[ret_idx].in_use = TRUE;
1929 pmhctl->llist_notify[ret_idx].next_idx = UNASSIGNED_INDEX;
1930 }
1931
1932 return ret_idx;
1933}
1934
1935uint16 mddi_get_reg_read_llist_item(mddi_host_type host_idx, boolean wait)
1936{
1937#ifdef FEATURE_MDDI_DISABLE_REVERSE
1938 MDDI_MSG_CRIT("No reverse link available\n");
1939 (void)wait;
1940 return FALSE;
1941#else
1942 unsigned long flags;
1943 uint16 ret_idx;
1944 boolean error = FALSE;
1945 mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
1946
1947 spin_lock_irqsave(&mddi_host_spin_lock, flags);
1948 if (pmhctl->llist_info.reg_read_idx != UNASSIGNED_INDEX) {
1949 /* need to block here or is this an error condition? */
1950 error = TRUE;
1951 ret_idx = UNASSIGNED_INDEX;
1952 }
1953 spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
1954
1955 if (!error) {
1956 ret_idx = pmhctl->llist_info.reg_read_idx =
1957 mddi_get_next_free_llist_item(host_idx, wait);
1958 /* clear the reg_read_waiting flag */
1959 pmhctl->llist_info.reg_read_waiting = FALSE;
1960 }
1961
1962 if (error)
1963 MDDI_MSG_ERR("***** Reg read still in progress! ****\n");
1964 return ret_idx;
1965#endif
1966
1967}
1968
1969void mddi_queue_forward_packets(uint16 first_llist_idx,
1970 uint16 last_llist_idx,
1971 boolean wait,
1972 mddi_llist_done_cb_type llist_done_cb,
1973 mddi_host_type host_idx)
1974{
1975 unsigned long flags;
1976 mddi_linked_list_type *llist;
1977 mddi_linked_list_type *llist_dma;
1978 mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
1979
1980 if ((first_llist_idx >= UNASSIGNED_INDEX) ||
1981 (last_llist_idx >= UNASSIGNED_INDEX)) {
1982 MDDI_MSG_ERR("MDDI queueing invalid linked list\n");
1983 return;
1984 }
1985
1986 if (pmhctl->link_state == MDDI_LINK_DISABLED)
1987 MDDI_MSG_CRIT("MDDI host powered down!\n");
1988
1989 llist = pmhctl->llist_ptr;
1990 llist_dma = pmhctl->llist_dma_ptr;
1991
1992 /* clean cache so MDDI host can read data */
1993 memory_barrier();
1994
1995 pmhctl->llist_notify[last_llist_idx].waiting = wait;
1996 if (wait)
1997 INIT_COMPLETION(pmhctl->llist_notify[last_llist_idx].done_comp);
1998 pmhctl->llist_notify[last_llist_idx].done_cb = llist_done_cb;
1999
2000 spin_lock_irqsave(&mddi_host_spin_lock, flags);
2001
2002 if ((pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) &&
2003 (pmhctl->llist_info.waiting_start_idx == UNASSIGNED_INDEX) &&
2004 (pmhctl->rev_state == MDDI_REV_IDLE)) {
2005 /* no packets are currently transmitting */
2006#ifndef FEATURE_MDDI_DISABLE_REVERSE
2007 if (first_llist_idx == pmhctl->llist_info.reg_read_idx) {
2008 /* This is the special case where the packet is a register read. */
2009 pmhctl->rev_state = MDDI_REV_REG_READ_ISSUED;
2010 mddi_reg_read_retry = 0;
2011 /* mddi_rev_reg_read_attempt = 1; */
2012 }
2013#endif
2014 /* assign transmitting index values */
2015 pmhctl->llist_info.transmitting_start_idx = first_llist_idx;
2016 pmhctl->llist_info.transmitting_end_idx = last_llist_idx;
2017
2018 /* turn on clock(s), if they have been disabled */
2019 mddi_host_enable_hclk();
2020 mddi_host_enable_io_clock();
2021 pmhctl->int_type.llist_ptr_write_1++;
2022 /* Write to primary pointer register */
2023 dma_coherent_pre_ops();
2024 mddi_host_reg_out(PRI_PTR, &llist_dma[first_llist_idx]);
2025
2026 /* enable interrupt when complete */
2027 mddi_host_reg_outm(INTEN, MDDI_INT_PRI_LINK_LIST_DONE,
2028 MDDI_INT_PRI_LINK_LIST_DONE);
2029
2030 } else if (pmhctl->llist_info.waiting_start_idx == UNASSIGNED_INDEX) {
2031#ifndef FEATURE_MDDI_DISABLE_REVERSE
2032 if (first_llist_idx == pmhctl->llist_info.reg_read_idx) {
2033 /*
2034 * we have a register read to send but need to wait
2035 * for current reverse activity to end or there are
2036 * packets currently transmitting
2037 */
2038 /* mddi_rev_reg_read_attempt = 0; */
2039 pmhctl->llist_info.reg_read_waiting = TRUE;
2040 }
2041#endif
2042
2043 /* assign waiting index values */
2044 pmhctl->llist_info.waiting_start_idx = first_llist_idx;
2045 pmhctl->llist_info.waiting_end_idx = last_llist_idx;
2046 } else {
2047 uint16 prev_end_idx = pmhctl->llist_info.waiting_end_idx;
2048#ifndef FEATURE_MDDI_DISABLE_REVERSE
2049 if (first_llist_idx == pmhctl->llist_info.reg_read_idx) {
2050 /*
2051 * we have a register read to send but need to wait
2052 * for current reverse activity to end or there are
2053 * packets currently transmitting
2054 */
2055 /* mddi_rev_reg_read_attempt = 0; */
2056 pmhctl->llist_info.reg_read_waiting = TRUE;
2057 }
2058#endif
2059
2060 llist = pmhctl->llist_ptr;
2061
2062 /* clear end flag in previous last packet */
2063 llist[prev_end_idx].link_controller_flags = 0;
2064 pmhctl->llist_notify[prev_end_idx].next_idx = first_llist_idx;
2065
2066 /* set the next_packet_pointer of the previous last packet */
2067 llist[prev_end_idx].next_packet_pointer =
2068 (void *)(&llist_dma[first_llist_idx]);
2069
2070 /* clean cache so MDDI host can read data */
2071 memory_barrier();
2072
2073 /* assign new waiting last index value */
2074 pmhctl->llist_info.waiting_end_idx = last_llist_idx;
2075 }
2076
2077 spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
2078
2079}
2080
2081void mddi_host_write_pix_attr_reg(uint32 value)
2082{
2083 (void)value;
2084}
2085
2086void mddi_queue_reverse_encapsulation(boolean wait)
2087{
2088#ifdef FEATURE_MDDI_DISABLE_REVERSE
2089 MDDI_MSG_CRIT("No reverse link available\n");
2090 (void)wait;
2091#else
2092 unsigned long flags;
2093 boolean error = FALSE;
2094 mddi_host_type host_idx = MDDI_HOST_PRIM;
2095 mddi_host_cntl_type *pmhctl = &(mhctl[MDDI_HOST_PRIM]);
2096
2097 spin_lock_irqsave(&mddi_host_spin_lock, flags);
2098
2099 /* turn on clock(s), if they have been disabled */
2100 mddi_host_enable_hclk();
2101 mddi_host_enable_io_clock();
2102
2103 if (wait) {
2104 if (!mddi_rev_user.waiting) {
2105 mddi_rev_user.waiting = TRUE;
2106 INIT_COMPLETION(mddi_rev_user.done_comp);
2107 } else
2108 error = TRUE;
2109 }
2110 mddi_rev_encap_user_request = TRUE;
2111
2112 if (pmhctl->rev_state == MDDI_REV_IDLE) {
2113 /* attempt to send the reverse encapsulation now */
2114 mddi_host_type orig_host_idx = mddi_curr_host;
2115 mddi_curr_host = host_idx;
2116 mddi_issue_reverse_encapsulation();
2117 mddi_curr_host = orig_host_idx;
2118 }
2119 spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
2120
2121 if (error) {
2122 MDDI_MSG_ERR("Reverse Encap request already in progress\n");
2123 } else if (wait)
2124 wait_for_completion_killable(&(mddi_rev_user.done_comp));
2125#endif
2126}
2127
2128/* ISR to be executed */
2129boolean mddi_set_rev_handler(mddi_rev_handler_type handler, uint16 pkt_type)
2130{
2131#ifdef FEATURE_MDDI_DISABLE_REVERSE
2132 MDDI_MSG_CRIT("No reverse link available\n");
2133 (void)handler;
2134 (void)pkt_type;
2135 return (FALSE);
2136#else
2137 unsigned long flags;
2138 uint16 hdlr;
2139 boolean handler_set = FALSE;
2140 boolean overwrite = FALSE;
2141 mddi_host_type host_idx = MDDI_HOST_PRIM;
2142 mddi_host_cntl_type *pmhctl = &(mhctl[MDDI_HOST_PRIM]);
2143
2144 /* Disable interrupts */
2145 spin_lock_irqsave(&mddi_host_spin_lock, flags);
2146
2147 for (hdlr = 0; hdlr < MAX_MDDI_REV_HANDLERS; hdlr++) {
2148 if (mddi_rev_pkt_handler[hdlr].pkt_type == pkt_type) {
2149 mddi_rev_pkt_handler[hdlr].handler = handler;
2150 if (handler == NULL) {
2151 /* clearing handler from table */
2152 mddi_rev_pkt_handler[hdlr].pkt_type =
2153 INVALID_PKT_TYPE;
2154 handler_set = TRUE;
2155 if (pkt_type == 0x10) { /* video stream packet */
2156 /* ensure HCLK on to MDDI host core before register write */
2157 mddi_host_enable_hclk();
2158 /* No longer getting video, so reset rev encap size to default */
2159 pmhctl->rev_pkt_size =
2160 MDDI_DEFAULT_REV_PKT_SIZE;
2161 mddi_host_reg_out(REV_ENCAP_SZ,
2162 pmhctl->rev_pkt_size);
2163 }
2164 } else {
2165 /* already a handler for this packet */
2166 overwrite = TRUE;
2167 }
2168 break;
2169 }
2170 }
2171 if ((hdlr >= MAX_MDDI_REV_HANDLERS) && (handler != NULL)) {
2172 /* assigning new handler */
2173 for (hdlr = 0; hdlr < MAX_MDDI_REV_HANDLERS; hdlr++) {
2174 if (mddi_rev_pkt_handler[hdlr].pkt_type ==
2175 INVALID_PKT_TYPE) {
2176 if ((pkt_type == 0x10) && /* video stream packet */
2177 (pmhctl->rev_pkt_size <
2178 MDDI_VIDEO_REV_PKT_SIZE)) {
2179 /* ensure HCLK on to MDDI host core before register write */
2180 mddi_host_enable_hclk();
2181 /* Increase Rev Encap Size */
2182 pmhctl->rev_pkt_size =
2183 MDDI_VIDEO_REV_PKT_SIZE;
2184 mddi_host_reg_out(REV_ENCAP_SZ,
2185 pmhctl->rev_pkt_size);
2186 }
2187 mddi_rev_pkt_handler[hdlr].handler = handler;
2188 mddi_rev_pkt_handler[hdlr].pkt_type = pkt_type;
2189 handler_set = TRUE;
2190 break;
2191 }
2192 }
2193 }
2194
2195 /* Restore interrupts */
2196 spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
2197
2198 if (overwrite)
2199 MDDI_MSG_ERR("Overwriting previous rev packet handler\n");
2200
2201 return handler_set;
2202
2203#endif
2204} /* mddi_set_rev_handler */
2205
2206void mddi_host_disable_hibernation(boolean disable)
2207{
2208 mddi_host_type host_idx = MDDI_HOST_PRIM;
2209 mddi_host_cntl_type *pmhctl = &(mhctl[MDDI_HOST_PRIM]);
2210
2211 if (disable) {
2212 pmhctl->disable_hibernation = TRUE;
2213 /* hibernation will be turned off by isr next time it is entered */
2214 } else {
2215 if (pmhctl->disable_hibernation) {
2216 unsigned long flags;
2217 spin_lock_irqsave(&mddi_host_spin_lock, flags);
2218 if (!MDDI_HOST_IS_HCLK_ON)
2219 MDDI_HOST_ENABLE_HCLK;
2220 mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE | 1);
2221 spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
2222 pmhctl->disable_hibernation = FALSE;
2223 }
2224 }
2225}
2226
2227void mddi_mhctl_remove(mddi_host_type host_idx)
2228{
2229 mddi_host_cntl_type *pmhctl;
2230
2231 pmhctl = &(mhctl[host_idx]);
2232
2233 dma_free_coherent(NULL, MDDI_LLIST_POOL_SIZE, (void *)pmhctl->llist_ptr,
2234 pmhctl->llist_dma_addr);
2235
2236 dma_free_coherent(NULL, MDDI_MAX_REV_DATA_SIZE,
2237 (void *)pmhctl->rev_data_buf,
2238 pmhctl->rev_data_dma_addr);
2239}
diff --git a/drivers/staging/msm/mddihosti.h b/drivers/staging/msm/mddihosti.h
new file mode 100644
index 000000000000..7b26a4253896
--- /dev/null
+++ b/drivers/staging/msm/mddihosti.h
@@ -0,0 +1,547 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are met:
5 * * Redistributions of source code must retain the above copyright
6 * notice, this list of conditions and the following disclaimer.
7 * * Redistributions in binary form must reproduce the above copyright
8 * notice, this list of conditions and the following disclaimer in the
9 * documentation and/or other materials provided with the distribution.
10 * * Neither the name of Code Aurora nor
11 * the names of its contributors may be used to endorse or promote
12 * products derived from this software without specific prior written
13 * permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 */
28
29#ifndef MDDIHOSTI_H
30#define MDDIHOSTI_H
31
32#include "msm_fb.h"
33#include "mddihost.h"
34#include <linux/clk.h>
35
36/* Register offsets in MDDI, applies to both msm_pmdh_base and
37 * (u32)msm_emdh_base. */
38#define MDDI_CMD 0x0000
39#define MDDI_VERSION 0x0004
40#define MDDI_PRI_PTR 0x0008
41#define MDDI_BPS 0x0010
42#define MDDI_SPM 0x0014
43#define MDDI_INT 0x0018
44#define MDDI_INTEN 0x001c
45#define MDDI_REV_PTR 0x0020
46#define MDDI_REV_SIZE 0x0024
47#define MDDI_STAT 0x0028
48#define MDDI_REV_RATE_DIV 0x002c
49#define MDDI_REV_CRC_ERR 0x0030
50#define MDDI_TA1_LEN 0x0034
51#define MDDI_TA2_LEN 0x0038
52#define MDDI_TEST 0x0040
53#define MDDI_REV_PKT_CNT 0x0044
54#define MDDI_DRIVE_HI 0x0048
55#define MDDI_DRIVE_LO 0x004c
56#define MDDI_DISP_WAKE 0x0050
57#define MDDI_REV_ENCAP_SZ 0x0054
58#define MDDI_RTD_VAL 0x0058
59#define MDDI_PAD_CTL 0x0068
60#define MDDI_DRIVER_START_CNT 0x006c
61#define MDDI_CORE_VER 0x008c
62#define MDDI_FIFO_ALLOC 0x0090
63#define MDDI_PAD_IO_CTL 0x00a0
64#define MDDI_PAD_CAL 0x00a4
65
66extern u32 mddi_msg_level;
67
68/* No longer need to write to clear these registers */
69#define xxxx_mddi_host_reg_outm(reg, mask, val) \
70do { \
71 if (host_idx == MDDI_HOST_PRIM) \
72 mddi_host_reg_outm_pmdh(reg, mask, val); \
73 else \
74 mddi_host_reg_outm_emdh(reg, mask, val); \
75} while (0)
76
77#define mddi_host_reg_outm(reg, mask, val) \
78do { \
79 unsigned long __addr; \
80 if (host_idx == MDDI_HOST_PRIM) \
81 __addr = (u32)msm_pmdh_base + MDDI_##reg; \
82 else \
83 __addr = (u32)msm_emdh_base + MDDI_##reg; \
84 writel((readl(__addr) & ~(mask)) | ((val) & (mask)), __addr); \
85} while (0)
86
87#define xxxx_mddi_host_reg_out(reg, val) \
88do { \
89 if (host_idx == MDDI_HOST_PRIM) \
90 mddi_host_reg_out_pmdh(reg, val); \
91 else \
92 mddi_host_reg_out_emdh(reg, val); \
93 } while (0)
94
95#define mddi_host_reg_out(reg, val) \
96do { \
97 if (host_idx == MDDI_HOST_PRIM) \
98 writel(val, (u32)msm_pmdh_base + MDDI_##reg); \
99 else \
100 writel(val, (u32)msm_emdh_base + MDDI_##reg); \
101} while (0)
102
103#define xxxx_mddi_host_reg_in(reg) \
104 ((host_idx) ? \
105 mddi_host_reg_in_emdh(reg) : mddi_host_reg_in_pmdh(reg));
106
107#define mddi_host_reg_in(reg) \
108((host_idx) ? \
109 readl((u32)msm_emdh_base + MDDI_##reg) : \
110 readl((u32)msm_pmdh_base + MDDI_##reg)) \
111
112#define xxxx_mddi_host_reg_inm(reg, mask) \
113 ((host_idx) ? \
114 mddi_host_reg_inm_emdh(reg, mask) : \
115 mddi_host_reg_inm_pmdh(reg, mask);)
116
117#define mddi_host_reg_inm(reg, mask) \
118((host_idx) ? \
119 readl((u32)msm_emdh_base + MDDI_##reg) & (mask) : \
120 readl((u32)msm_pmdh_base + MDDI_##reg) & (mask)) \
121
122/* Using non-cacheable pmem, so do nothing */
123#define mddi_invalidate_cache_lines(addr_start, num_bytes)
124/*
125 * Using non-cacheable pmem, so do nothing with cache
126 * but, ensure write goes out to memory
127 */
128#define mddi_flush_cache_lines(addr_start, num_bytes) \
129 (void) addr_start; \
130 (void) num_bytes; \
131 memory_barrier()
132
133/* Since this translates to Remote Procedure Calls to check on clock status
134* just use a local variable to keep track of io_clock */
135#define MDDI_HOST_IS_IO_CLOCK_ON mddi_host_io_clock_on
136#define MDDI_HOST_ENABLE_IO_CLOCK
137#define MDDI_HOST_DISABLE_IO_CLOCK
138#define MDDI_HOST_IS_HCLK_ON mddi_host_hclk_on
139#define MDDI_HOST_ENABLE_HCLK
140#define MDDI_HOST_DISABLE_HCLK
141#define FEATURE_MDDI_HOST_IO_CLOCK_CONTROL_DISABLE
142#define FEATURE_MDDI_HOST_HCLK_CONTROL_DISABLE
143
144#define TRAMP_MDDI_HOST_ISR TRAMP_MDDI_PRI_ISR
145#define TRAMP_MDDI_HOST_EXT_ISR TRAMP_MDDI_EXT_ISR
146#define MDP_LINE_COUNT_BMSK 0x3ff
147#define MDP_SYNC_STATUS 0x000c
148#define MDP_LINE_COUNT \
149(readl(msm_mdp_base + MDP_SYNC_STATUS) & MDP_LINE_COUNT_BMSK)
150
151/* MDP sends 256 pixel packets, so lower value hibernates more without
152* significantly increasing latency of waiting for next subframe */
153#define MDDI_HOST_BYTES_PER_SUBFRAME 0x3C00
154
155#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40)
156#define MDDI_HOST_TA2_LEN 0x001a
157#define MDDI_HOST_REV_RATE_DIV 0x0004
158#else
159#define MDDI_HOST_TA2_LEN 0x000c
160#define MDDI_HOST_REV_RATE_DIV 0x0002
161#endif
162
163#define MDDI_MSG_EMERG(msg, ...) \
164 if (mddi_msg_level > 0) \
165 printk(KERN_EMERG msg, ## __VA_ARGS__);
166#define MDDI_MSG_ALERT(msg, ...) \
167 if (mddi_msg_level > 1) \
168 printk(KERN_ALERT msg, ## __VA_ARGS__);
169#define MDDI_MSG_CRIT(msg, ...) \
170 if (mddi_msg_level > 2) \
171 printk(KERN_CRIT msg, ## __VA_ARGS__);
172#define MDDI_MSG_ERR(msg, ...) \
173 if (mddi_msg_level > 3) \
174 printk(KERN_ERR msg, ## __VA_ARGS__);
175#define MDDI_MSG_WARNING(msg, ...) \
176 if (mddi_msg_level > 4) \
177 printk(KERN_WARNING msg, ## __VA_ARGS__);
178#define MDDI_MSG_NOTICE(msg, ...) \
179 if (mddi_msg_level > 5) \
180 printk(KERN_NOTICE msg, ## __VA_ARGS__);
181#define MDDI_MSG_INFO(msg, ...) \
182 if (mddi_msg_level > 6) \
183 printk(KERN_INFO msg, ## __VA_ARGS__);
184#define MDDI_MSG_DEBUG(msg, ...) \
185 if (mddi_msg_level > 7) \
186 printk(KERN_DEBUG msg, ## __VA_ARGS__);
187
188#define GCC_PACKED __attribute__((packed))
189typedef struct GCC_PACKED {
190 uint16 packet_length;
191 /* total # of bytes in the packet not including
192 the packet_length field. */
193
194 uint16 packet_type;
195 /* A Packet Type of 70 identifies the packet as
196 a Client status Packet. */
197
198 uint16 bClient_ID;
199 /* This field is reserved for future use and shall
200 be set to zero. */
201
202} mddi_rev_packet_type;
203
204typedef struct GCC_PACKED {
205 uint16 packet_length;
206 /* total # of bytes in the packet not including
207 the packet_length field. */
208
209 uint16 packet_type;
210 /* A Packet Type of 70 identifies the packet as
211 a Client status Packet. */
212
213 uint16 bClient_ID;
214 /* This field is reserved for future use and shall
215 be set to zero. */
216
217 uint16 reverse_link_request;
218 /* 16 bit unsigned integer with number of bytes client
219 needs in the * reverse encapsulation message
220 to transmit data. */
221
222 uint8 crc_error_count;
223 uint8 capability_change;
224 uint16 graphics_busy_flags;
225
226 uint16 parameter_CRC;
227 /* 16-bit CRC of all the bytes in the packet
228 including Packet Length. */
229
230} mddi_client_status_type;
231
232typedef struct GCC_PACKED {
233 uint16 packet_length;
234 /* total # of bytes in the packet not including
235 the packet_length field. */
236
237 uint16 packet_type;
238 /* A Packet Type of 66 identifies the packet as
239 a Client Capability Packet. */
240
241 uint16 bClient_ID;
242 /* This field is reserved for future use and
243 shall be set to zero. */
244
245 uint16 Protocol_Version;
246 uint16 Minimum_Protocol_Version;
247 uint16 Data_Rate_Capability;
248 uint8 Interface_Type_Capability;
249 uint8 Number_of_Alt_Displays;
250 uint16 PostCal_Data_Rate;
251 uint16 Bitmap_Width;
252 uint16 Bitmap_Height;
253 uint16 Display_Window_Width;
254 uint16 Display_Window_Height;
255 uint32 Color_Map_Size;
256 uint16 Color_Map_RGB_Width;
257 uint16 RGB_Capability;
258 uint8 Monochrome_Capability;
259 uint8 Reserved_1;
260 uint16 Y_Cb_Cr_Capability;
261 uint16 Bayer_Capability;
262 uint16 Alpha_Cursor_Image_Planes;
263 uint32 Client_Feature_Capability_Indicators;
264 uint8 Maximum_Video_Frame_Rate_Capability;
265 uint8 Minimum_Video_Frame_Rate_Capability;
266 uint16 Minimum_Sub_frame_Rate;
267 uint16 Audio_Buffer_Depth;
268 uint16 Audio_Channel_Capability;
269 uint16 Audio_Sample_Rate_Capability;
270 uint8 Audio_Sample_Resolution;
271 uint8 Mic_Audio_Sample_Resolution;
272 uint16 Mic_Sample_Rate_Capability;
273 uint8 Keyboard_Data_Format;
274 uint8 pointing_device_data_format;
275 uint16 content_protection_type;
276 uint16 Mfr_Name;
277 uint16 Product_Code;
278 uint16 Reserved_3;
279 uint32 Serial_Number;
280 uint8 Week_of_Manufacture;
281 uint8 Year_of_Manufacture;
282
283 uint16 parameter_CRC;
284 /* 16-bit CRC of all the bytes in the packet including Packet Length. */
285
286} mddi_client_capability_type;
287
288typedef struct GCC_PACKED {
289 uint16 packet_length;
290 /* total # of bytes in the packet not including the packet_length field. */
291
292 uint16 packet_type;
293 /* A Packet Type of 16 identifies the packet as a Video Stream Packet. */
294
295 uint16 bClient_ID;
296 /* This field is reserved for future use and shall be set to zero. */
297
298 uint16 video_data_format_descriptor;
299 /* format of each pixel in the Pixel Data in the present stream in the
300 * present packet.
301 * If bits [15:13] = 000 monochrome
302 * If bits [15:13] = 001 color pixels (palette).
303 * If bits [15:13] = 010 color pixels in raw RGB
304 * If bits [15:13] = 011 data in 4:2:2 Y Cb Cr format
305 * If bits [15:13] = 100 Bayer pixels
306 */
307
308 uint16 pixel_data_attributes;
309 /* interpreted as follows:
310 * Bits [1:0] = 11 pixel data is displayed to both eyes
311 * Bits [1:0] = 10 pixel data is routed to the left eye only.
312 * Bits [1:0] = 01 pixel data is routed to the right eye only.
313 * Bits [1:0] = 00 pixel data is routed to the alternate display.
314 * Bit 2 is 0 Pixel Data is in the standard progressive format.
315 * Bit 2 is 1 Pixel Data is in interlace format.
316 * Bit 3 is 0 Pixel Data is in the standard progressive format.
317 * Bit 3 is 1 Pixel Data is in alternate pixel format.
318 * Bit 4 is 0 Pixel Data is to or from the display frame buffer.
319 * Bit 4 is 1 Pixel Data is to or from the camera.
320 * Bit 5 is 0 pixel data contains the next consecutive row of pixels.
321 * Bit 5 is 1 X Left Edge, Y Top Edge, X Right Edge, Y Bottom Edge,
322 * X Start, and Y Start parameters are not defined and
323 * shall be ignored by the client.
324 * Bits [7:6] = 01 Pixel data is written to the offline image buffer.
325 * Bits [7:6] = 00 Pixel data is written to the buffer to refresh display.
326 * Bits [7:6] = 11 Pixel data is written to all image buffers.
327 * Bits [7:6] = 10 Invalid. Reserved for future use.
328 * Bits 8 through 11 alternate display number.
329 * Bits 12 through 14 are reserved for future use and shall be set to zero.
330 * Bit 15 is 1 the row of pixels is the last row of pixels in a frame.
331 */
332
333 uint16 x_left_edge;
334 uint16 y_top_edge;
335 /* X,Y coordinate of the top left edge of the screen window */
336
337 uint16 x_right_edge;
338 uint16 y_bottom_edge;
339 /* X,Y coordinate of the bottom right edge of the window being updated. */
340
341 uint16 x_start;
342 uint16 y_start;
343 /* (X Start, Y Start) is the first pixel in the Pixel Data field below. */
344
345 uint16 pixel_count;
346 /* number of pixels in the Pixel Data field below. */
347
348 uint16 parameter_CRC;
349 /* 16-bit CRC of all bytes from the Packet Length to the Pixel Count. */
350
351 uint16 reserved;
352 /* 16-bit variable to make structure align on 4 byte boundary */
353
354} mddi_video_stream_packet_type;
355
356typedef struct GCC_PACKED {
357 uint16 packet_length;
358 /* total # of bytes in the packet not including the packet_length field. */
359
360 uint16 packet_type;
361 /* A Packet Type of 146 identifies the packet as a Register Access Packet. */
362
363 uint16 bClient_ID;
364 /* This field is reserved for future use and shall be set to zero. */
365
366 uint16 read_write_info;
367 /* Bits 13:0 a 14-bit unsigned integer that specifies the number of
368 * 32-bit Register Data List items to be transferred in the
369 * Register Data List field.
370 * Bits[15:14] = 00 Write to register(s);
371 * Bits[15:14] = 10 Read from register(s);
372 * Bits[15:14] = 11 Response to a Read.
373 * Bits[15:14] = 01 this value is reserved for future use. */
374
375 uint32 register_address;
376 /* the register address that is to be written to or read from. */
377
378 uint16 parameter_CRC;
379 /* 16-bit CRC of all bytes from the Packet Length to the Register Address. */
380
381 uint32 register_data_list;
382 /* list of 4-byte register data values for/from client registers */
383
384} mddi_register_access_packet_type;
385
386typedef union GCC_PACKED {
387 mddi_video_stream_packet_type video_pkt;
388 mddi_register_access_packet_type register_pkt;
389 /* add 48 byte pad to ensure 64 byte llist struct, that can be
390 * manipulated easily with cache */
391 uint32 alignment_pad[12]; /* 48 bytes */
392} mddi_packet_header_type;
393
394typedef struct GCC_PACKED mddi_host_llist_struct {
395 uint16 link_controller_flags;
396 uint16 packet_header_count;
397 uint16 packet_data_count;
398 void *packet_data_pointer;
399 struct mddi_host_llist_struct *next_packet_pointer;
400 uint16 reserved;
401 mddi_packet_header_type packet_header;
402} mddi_linked_list_type;
403
404typedef struct {
405 struct completion done_comp;
406 mddi_llist_done_cb_type done_cb;
407 uint16 next_idx;
408 boolean waiting;
409 boolean in_use;
410} mddi_linked_list_notify_type;
411
412#define MDDI_LLIST_POOL_SIZE 0x1000
413#define MDDI_MAX_NUM_LLIST_ITEMS (MDDI_LLIST_POOL_SIZE / \
414 sizeof(mddi_linked_list_type))
415#define UNASSIGNED_INDEX MDDI_MAX_NUM_LLIST_ITEMS
416#define MDDI_FIRST_DYNAMIC_LLIST_IDX 0
417
418/* Static llist items can be used for applications that frequently send
419 * the same set of packets using the linked list interface. */
420/* Here we configure for 6 static linked list items:
421 * The 1st is used for a the adaptive backlight setting.
422 * and the remaining 5 are used for sending window adjustments for
423 * MDDI clients that need windowing info sent separate from video
424 * packets. */
425#define MDDI_NUM_STATIC_ABL_ITEMS 1
426#define MDDI_NUM_STATIC_WINDOW_ITEMS 5
427#define MDDI_NUM_STATIC_LLIST_ITEMS (MDDI_NUM_STATIC_ABL_ITEMS + \
428 MDDI_NUM_STATIC_WINDOW_ITEMS)
429#define MDDI_NUM_DYNAMIC_LLIST_ITEMS (MDDI_MAX_NUM_LLIST_ITEMS - \
430 MDDI_NUM_STATIC_LLIST_ITEMS)
431
432#define MDDI_FIRST_STATIC_LLIST_IDX MDDI_NUM_DYNAMIC_LLIST_ITEMS
433#define MDDI_FIRST_STATIC_ABL_IDX MDDI_FIRST_STATIC_LLIST_IDX
434#define MDDI_FIRST_STATIC_WINDOW_IDX (MDDI_FIRST_STATIC_LLIST_IDX + \
435 MDDI_NUM_STATIC_ABL_ITEMS)
436
437/* GPIO registers */
438#define VSYNC_WAKEUP_REG 0x80
439#define GPIO_REG 0x81
440#define GPIO_OUTPUT_REG 0x82
441#define GPIO_INTERRUPT_REG 0x83
442#define GPIO_INTERRUPT_ENABLE_REG 0x84
443#define GPIO_POLARITY_REG 0x85
444
445/* Interrupt Bits */
446#define MDDI_INT_PRI_PTR_READ 0x0001
447#define MDDI_INT_SEC_PTR_READ 0x0002
448#define MDDI_INT_REV_DATA_AVAIL 0x0004
449#define MDDI_INT_DISP_REQ 0x0008
450#define MDDI_INT_PRI_UNDERFLOW 0x0010
451#define MDDI_INT_SEC_UNDERFLOW 0x0020
452#define MDDI_INT_REV_OVERFLOW 0x0040
453#define MDDI_INT_CRC_ERROR 0x0080
454#define MDDI_INT_MDDI_IN 0x0100
455#define MDDI_INT_PRI_OVERWRITE 0x0200
456#define MDDI_INT_SEC_OVERWRITE 0x0400
457#define MDDI_INT_REV_OVERWRITE 0x0800
458#define MDDI_INT_DMA_FAILURE 0x1000
459#define MDDI_INT_LINK_ACTIVE 0x2000
460#define MDDI_INT_IN_HIBERNATION 0x4000
461#define MDDI_INT_PRI_LINK_LIST_DONE 0x8000
462#define MDDI_INT_SEC_LINK_LIST_DONE 0x10000
463#define MDDI_INT_NO_CMD_PKTS_PEND 0x20000
464#define MDDI_INT_RTD_FAILURE 0x40000
465
466#define MDDI_INT_ERROR_CONDITIONS ( \
467 MDDI_INT_PRI_UNDERFLOW | MDDI_INT_SEC_UNDERFLOW | \
468 MDDI_INT_REV_OVERFLOW | MDDI_INT_CRC_ERROR | \
469 MDDI_INT_PRI_OVERWRITE | MDDI_INT_SEC_OVERWRITE | \
470 MDDI_INT_RTD_FAILURE | \
471 MDDI_INT_REV_OVERWRITE | MDDI_INT_DMA_FAILURE)
472
473#define MDDI_INT_LINK_STATE_CHANGES ( \
474 MDDI_INT_LINK_ACTIVE | MDDI_INT_IN_HIBERNATION)
475
476/* Status Bits */
477#define MDDI_STAT_LINK_ACTIVE 0x0001
478#define MDDI_STAT_NEW_REV_PTR 0x0002
479#define MDDI_STAT_NEW_PRI_PTR 0x0004
480#define MDDI_STAT_NEW_SEC_PTR 0x0008
481#define MDDI_STAT_IN_HIBERNATION 0x0010
482#define MDDI_STAT_PRI_LINK_LIST_DONE 0x0020
483#define MDDI_STAT_SEC_LINK_LIST_DONE 0x0040
484#define MDDI_STAT_PENDING_TIMING_PKT 0x0080
485#define MDDI_STAT_PENDING_REV_ENCAP 0x0100
486#define MDDI_STAT_PENDING_POWERDOWN 0x0200
487#define MDDI_STAT_RTD_MEAS_FAIL 0x0800
488#define MDDI_STAT_CLIENT_WAKEUP_REQ 0x1000
489
490/* Command Bits */
491#define MDDI_CMD_POWERDOWN 0x0100
492#define MDDI_CMD_POWERUP 0x0200
493#define MDDI_CMD_HIBERNATE 0x0300
494#define MDDI_CMD_RESET 0x0400
495#define MDDI_CMD_DISP_IGNORE 0x0501
496#define MDDI_CMD_DISP_LISTEN 0x0500
497#define MDDI_CMD_SEND_REV_ENCAP 0x0600
498#define MDDI_CMD_GET_CLIENT_CAP 0x0601
499#define MDDI_CMD_GET_CLIENT_STATUS 0x0602
500#define MDDI_CMD_SEND_RTD 0x0700
501#define MDDI_CMD_LINK_ACTIVE 0x0900
502#define MDDI_CMD_PERIODIC_REV_ENCAP 0x0A00
503
504extern void mddi_host_init(mddi_host_type host);
505extern void mddi_host_powerdown(mddi_host_type host);
506extern uint16 mddi_get_next_free_llist_item(mddi_host_type host, boolean wait);
507extern uint16 mddi_get_reg_read_llist_item(mddi_host_type host, boolean wait);
508extern void mddi_queue_forward_packets(uint16 first_llist_idx,
509 uint16 last_llist_idx,
510 boolean wait,
511 mddi_llist_done_cb_type llist_done_cb,
512 mddi_host_type host);
513
514extern void mddi_host_write_pix_attr_reg(uint32 value);
515extern void mddi_client_lcd_gpio_poll(uint32 poll_reg_val);
516extern void mddi_client_lcd_vsync_detected(boolean detected);
517extern void mddi_host_disable_hibernation(boolean disable);
518
519extern mddi_linked_list_type *llist_extern[];
520extern mddi_linked_list_type *llist_dma_extern[];
521extern mddi_linked_list_notify_type *llist_extern_notify[];
522extern struct timer_list mddi_host_timer;
523
524typedef struct {
525 uint16 transmitting_start_idx;
526 uint16 transmitting_end_idx;
527 uint16 waiting_start_idx;
528 uint16 waiting_end_idx;
529 uint16 reg_read_idx;
530 uint16 next_free_idx;
531 boolean reg_read_waiting;
532} mddi_llist_info_type;
533
534extern mddi_llist_info_type mddi_llist;
535
536#define MDDI_GPIO_DEFAULT_POLLING_INTERVAL 200
537typedef struct {
538 uint32 polling_reg;
539 uint32 polling_val;
540 uint32 polling_interval;
541 boolean polling_enabled;
542} mddi_gpio_info_type;
543
544uint32 mddi_get_client_id(void);
545void mddi_mhctl_remove(mddi_host_type host_idx);
546void mddi_host_timer_service(unsigned long data);
547#endif /* MDDIHOSTI_H */
diff --git a/drivers/staging/msm/mdp.c b/drivers/staging/msm/mdp.c
new file mode 100644
index 000000000000..36053afdebe2
--- /dev/null
+++ b/drivers/staging/msm/mdp.c
@@ -0,0 +1,1113 @@
1/* Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/sched.h>
21#include <linux/time.h>
22#include <linux/init.h>
23#include <linux/interrupt.h>
24#include <linux/spinlock.h>
25#include <linux/hrtimer.h>
26#include <linux/clk.h>
27#include <mach/hardware.h>
28#include <linux/io.h>
29#include <linux/debugfs.h>
30#include <linux/delay.h>
31#include <linux/mutex.h>
32
33#include <asm/system.h>
34#include <asm/mach-types.h>
35#include <linux/semaphore.h>
36#include <linux/uaccess.h>
37
38#include "mdp.h"
39#include "msm_fb.h"
40#ifdef CONFIG_FB_MSM_MDP40
41#include "mdp4.h"
42#endif
43
44static struct clk *mdp_clk;
45static struct clk *mdp_pclk;
46
47struct completion mdp_ppp_comp;
48struct semaphore mdp_ppp_mutex;
49struct semaphore mdp_pipe_ctrl_mutex;
50
51unsigned long mdp_timer_duration = (HZ); /* 1 sec */
52/* unsigned long mdp_mdp_timer_duration=0; */
53
54boolean mdp_ppp_waiting = FALSE;
55uint32 mdp_tv_underflow_cnt;
56uint32 mdp_lcdc_underflow_cnt;
57
58boolean mdp_current_clk_on = FALSE;
59boolean mdp_is_in_isr = FALSE;
60
61/*
62 * legacy mdp_in_processing is only for DMA2-MDDI
63 * this applies to DMA2 block only
64 */
65uint32 mdp_in_processing = FALSE;
66
67#ifdef CONFIG_FB_MSM_MDP40
68uint32 mdp_intr_mask = MDP4_ANY_INTR_MASK;
69#else
70uint32 mdp_intr_mask = MDP_ANY_INTR_MASK;
71#endif
72
73MDP_BLOCK_TYPE mdp_debug[MDP_MAX_BLOCK];
74
75int32 mdp_block_power_cnt[MDP_MAX_BLOCK];
76
77spinlock_t mdp_spin_lock;
78struct workqueue_struct *mdp_dma_wq; /*mdp dma wq */
79struct workqueue_struct *mdp_vsync_wq; /*mdp vsync wq */
80
81static struct workqueue_struct *mdp_pipe_ctrl_wq; /* mdp mdp pipe ctrl wq */
82static struct delayed_work mdp_pipe_ctrl_worker;
83
84#ifdef CONFIG_FB_MSM_MDP40
85struct mdp_dma_data dma2_data;
86struct mdp_dma_data dma_s_data;
87struct mdp_dma_data dma_e_data;
88#else
89static struct mdp_dma_data dma2_data;
90static struct mdp_dma_data dma_s_data;
91static struct mdp_dma_data dma_e_data;
92#endif
93static struct mdp_dma_data dma3_data;
94
95extern ktime_t mdp_dma2_last_update_time;
96
97extern uint32 mdp_dma2_update_time_in_usec;
98extern int mdp_lcd_rd_cnt_offset_slow;
99extern int mdp_lcd_rd_cnt_offset_fast;
100extern int mdp_usec_diff_threshold;
101
102#ifdef CONFIG_FB_MSM_LCDC
103extern int mdp_lcdc_pclk_clk_rate;
104extern int mdp_lcdc_pad_pclk_clk_rate;
105extern int first_pixel_start_x;
106extern int first_pixel_start_y;
107#endif
108
109#ifdef MSM_FB_ENABLE_DBGFS
110struct dentry *mdp_dir;
111#endif
112
113#if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND)
114static int mdp_suspend(struct platform_device *pdev, pm_message_t state);
115#else
116#define mdp_suspend NULL
117#endif
118
119struct timeval mdp_dma2_timeval;
120struct timeval mdp_ppp_timeval;
121
122#ifdef CONFIG_HAS_EARLYSUSPEND
123static struct early_suspend early_suspend;
124#endif
125
126#ifndef CONFIG_FB_MSM_MDP22
127DEFINE_MUTEX(mdp_lut_push_sem);
128static int mdp_lut_i;
129static int mdp_lut_hw_update(struct fb_cmap *cmap)
130{
131 int i;
132 u16 *c[3];
133 u16 r, g, b;
134
135 c[0] = cmap->green;
136 c[1] = cmap->blue;
137 c[2] = cmap->red;
138
139 for (i = 0; i < cmap->len; i++) {
140 if (copy_from_user(&r, cmap->red++, sizeof(r)) ||
141 copy_from_user(&g, cmap->green++, sizeof(g)) ||
142 copy_from_user(&b, cmap->blue++, sizeof(b)))
143 return -EFAULT;
144
145#ifdef CONFIG_FB_MSM_MDP40
146 MDP_OUTP(MDP_BASE + 0x94800 +
147#else
148 MDP_OUTP(MDP_BASE + 0x93800 +
149#endif
150 (0x400*mdp_lut_i) + cmap->start*4 + i*4,
151 ((g & 0xff) |
152 ((b & 0xff) << 8) |
153 ((r & 0xff) << 16)));
154 }
155
156 return 0;
157}
158
159static int mdp_lut_push;
160static int mdp_lut_push_i;
161static int mdp_lut_update_nonlcdc(struct fb_info *info, struct fb_cmap *cmap)
162{
163 int ret;
164
165 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
166 ret = mdp_lut_hw_update(cmap);
167 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
168
169 if (ret)
170 return ret;
171
172 mutex_lock(&mdp_lut_push_sem);
173 mdp_lut_push = 1;
174 mdp_lut_push_i = mdp_lut_i;
175 mutex_unlock(&mdp_lut_push_sem);
176
177 mdp_lut_i = (mdp_lut_i + 1)%2;
178
179 return 0;
180}
181
182static int mdp_lut_update_lcdc(struct fb_info *info, struct fb_cmap *cmap)
183{
184 int ret;
185
186 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
187 ret = mdp_lut_hw_update(cmap);
188
189 if (ret) {
190 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
191 return ret;
192 }
193
194 MDP_OUTP(MDP_BASE + 0x90070, (mdp_lut_i << 10) | 0x17);
195 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
196 mdp_lut_i = (mdp_lut_i + 1)%2;
197
198 return 0;
199}
200
201#define MDP_HIST_MAX_BIN 32
202static __u32 mdp_hist_r[MDP_HIST_MAX_BIN];
203static __u32 mdp_hist_g[MDP_HIST_MAX_BIN];
204static __u32 mdp_hist_b[MDP_HIST_MAX_BIN];
205
206#ifdef CONFIG_FB_MSM_MDP40
207struct mdp_histogram mdp_hist;
208struct completion mdp_hist_comp;
209#else
210static struct mdp_histogram mdp_hist;
211static struct completion mdp_hist_comp;
212#endif
213
214static int mdp_do_histogram(struct fb_info *info, struct mdp_histogram *hist)
215{
216 int ret = 0;
217
218 if (!hist->frame_cnt || (hist->bin_cnt == 0) ||
219 (hist->bin_cnt > MDP_HIST_MAX_BIN))
220 return -EINVAL;
221
222 INIT_COMPLETION(mdp_hist_comp);
223
224 mdp_hist.bin_cnt = hist->bin_cnt;
225 mdp_hist.r = (hist->r) ? mdp_hist_r : 0;
226 mdp_hist.g = (hist->g) ? mdp_hist_g : 0;
227 mdp_hist.b = (hist->b) ? mdp_hist_b : 0;
228
229#ifdef CONFIG_FB_MSM_MDP40
230 MDP_OUTP(MDP_BASE + 0x95004, hist->frame_cnt);
231 MDP_OUTP(MDP_BASE + 0x95000, 1);
232#else
233 MDP_OUTP(MDP_BASE + 0x94004, hist->frame_cnt);
234 MDP_OUTP(MDP_BASE + 0x94000, 1);
235#endif
236 wait_for_completion_killable(&mdp_hist_comp);
237
238 if (hist->r) {
239 ret = copy_to_user(hist->r, mdp_hist.r, hist->bin_cnt*4);
240 if (ret)
241 goto hist_err;
242 }
243 if (hist->g) {
244 ret = copy_to_user(hist->g, mdp_hist.g, hist->bin_cnt*4);
245 if (ret)
246 goto hist_err;
247 }
248 if (hist->b) {
249 ret = copy_to_user(hist->b, mdp_hist.b, hist->bin_cnt*4);
250 if (ret)
251 goto hist_err;
252 }
253 return 0;
254
255hist_err:
256 printk(KERN_ERR "%s: invalid hist buffer\n", __func__);
257 return ret;
258}
259#endif
260
261/* Returns < 0 on error, 0 on timeout, or > 0 on successful wait */
262
263int mdp_ppp_pipe_wait(void)
264{
265 int ret = 1;
266
267 /* wait 5 seconds for the operation to complete before declaring
268 the MDP hung */
269
270 if (mdp_ppp_waiting == TRUE) {
271 ret = wait_for_completion_interruptible_timeout(&mdp_ppp_comp,
272 5 * HZ);
273
274 if (!ret)
275 printk(KERN_ERR "%s: Timed out waiting for the MDP.\n",
276 __func__);
277 }
278
279 return ret;
280}
281
282static DEFINE_SPINLOCK(mdp_lock);
283static int mdp_irq_mask;
284static int mdp_irq_enabled;
285
286void mdp_enable_irq(uint32 term)
287{
288 unsigned long irq_flags;
289
290 spin_lock_irqsave(&mdp_lock, irq_flags);
291 if (mdp_irq_mask & term) {
292 printk(KERN_ERR "MDP IRQ term-0x%x is already set\n", term);
293 } else {
294 mdp_irq_mask |= term;
295 if (mdp_irq_mask && !mdp_irq_enabled) {
296 mdp_irq_enabled = 1;
297 enable_irq(INT_MDP);
298 }
299 }
300 spin_unlock_irqrestore(&mdp_lock, irq_flags);
301}
302
303void mdp_disable_irq(uint32 term)
304{
305 unsigned long irq_flags;
306
307 spin_lock_irqsave(&mdp_lock, irq_flags);
308 if (!(mdp_irq_mask & term)) {
309 printk(KERN_ERR "MDP IRQ term-0x%x is not set\n", term);
310 } else {
311 mdp_irq_mask &= ~term;
312 if (!mdp_irq_mask && mdp_irq_enabled) {
313 mdp_irq_enabled = 0;
314 disable_irq(INT_MDP);
315 }
316 }
317 spin_unlock_irqrestore(&mdp_lock, irq_flags);
318}
319
320void mdp_disable_irq_nolock(uint32 term)
321{
322
323 if (!(mdp_irq_mask & term)) {
324 printk(KERN_ERR "MDP IRQ term-0x%x is not set\n", term);
325 } else {
326 mdp_irq_mask &= ~term;
327 if (!mdp_irq_mask && mdp_irq_enabled) {
328 mdp_irq_enabled = 0;
329 disable_irq(INT_MDP);
330 }
331 }
332}
333
334void mdp_pipe_kickoff(uint32 term, struct msm_fb_data_type *mfd)
335{
336
337 dmb(); /* memory barrier */
338
339 /* kick off PPP engine */
340 if (term == MDP_PPP_TERM) {
341 if (mdp_debug[MDP_PPP_BLOCK])
342 jiffies_to_timeval(jiffies, &mdp_ppp_timeval);
343
344 /* let's turn on PPP block */
345 mdp_pipe_ctrl(MDP_PPP_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
346
347 mdp_enable_irq(term);
348 INIT_COMPLETION(mdp_ppp_comp);
349 mdp_ppp_waiting = TRUE;
350 outpdw(MDP_BASE + 0x30, 0x1000);
351 wait_for_completion_killable(&mdp_ppp_comp);
352 mdp_disable_irq(term);
353
354 if (mdp_debug[MDP_PPP_BLOCK]) {
355 struct timeval now;
356
357 jiffies_to_timeval(jiffies, &now);
358 mdp_ppp_timeval.tv_usec =
359 now.tv_usec - mdp_ppp_timeval.tv_usec;
360 MSM_FB_INFO("MDP-PPP: %d\n",
361 (int)mdp_ppp_timeval.tv_usec);
362 }
363 } else if (term == MDP_DMA2_TERM) {
364 if (mdp_debug[MDP_DMA2_BLOCK]) {
365 MSM_FB_INFO("MDP-DMA2: %d\n",
366 (int)mdp_dma2_timeval.tv_usec);
367 jiffies_to_timeval(jiffies, &mdp_dma2_timeval);
368 }
369 /* DMA update timestamp */
370 mdp_dma2_last_update_time = ktime_get_real();
371 /* let's turn on DMA2 block */
372#if 0
373 mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
374#endif
375#ifdef CONFIG_FB_MSM_MDP22
376 outpdw(MDP_CMD_DEBUG_ACCESS_BASE + 0x0044, 0x0);/* start DMA */
377#else
378 if (mdp_lut_push) {
379 mutex_lock(&mdp_lut_push_sem);
380 mdp_lut_push = 0;
381 MDP_OUTP(MDP_BASE + 0x90070,
382 (mdp_lut_push_i << 10) | 0x17);
383 mutex_unlock(&mdp_lut_push_sem);
384 }
385#ifdef CONFIG_FB_MSM_MDP40
386 outpdw(MDP_BASE + 0x000c, 0x0); /* start DMA */
387#else
388 outpdw(MDP_BASE + 0x0044, 0x0); /* start DMA */
389#endif
390#endif
391#ifdef CONFIG_FB_MSM_MDP40
392 } else if (term == MDP_DMA_S_TERM) {
393 mdp_pipe_ctrl(MDP_DMA_S_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
394 outpdw(MDP_BASE + 0x0010, 0x0); /* start DMA */
395 } else if (term == MDP_DMA_E_TERM) {
396 mdp_pipe_ctrl(MDP_DMA_E_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
397 outpdw(MDP_BASE + 0x0014, 0x0); /* start DMA */
398 } else if (term == MDP_OVERLAY0_TERM) {
399 mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
400 outpdw(MDP_BASE + 0x0004, 0);
401 } else if (term == MDP_OVERLAY1_TERM) {
402 mdp_pipe_ctrl(MDP_OVERLAY1_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
403 outpdw(MDP_BASE + 0x0008, 0);
404 }
405#else
406 } else if (term == MDP_DMA_S_TERM) {
407 mdp_pipe_ctrl(MDP_DMA_S_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
408 outpdw(MDP_BASE + 0x0048, 0x0); /* start DMA */
409 }
410#endif
411}
412
413static void mdp_pipe_ctrl_workqueue_handler(struct work_struct *work)
414{
415 mdp_pipe_ctrl(MDP_MASTER_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
416}
417
418void mdp_pipe_ctrl(MDP_BLOCK_TYPE block, MDP_BLOCK_POWER_STATE state,
419 boolean isr)
420{
421 boolean mdp_all_blocks_off = TRUE;
422 int i;
423 unsigned long flag;
424
425 spin_lock_irqsave(&mdp_spin_lock, flag);
426 if (MDP_BLOCK_POWER_ON == state) {
427 mdp_block_power_cnt[block]++;
428
429 if (MDP_DMA2_BLOCK == block)
430 mdp_in_processing = TRUE;
431 } else {
432 mdp_block_power_cnt[block]--;
433
434 if (mdp_block_power_cnt[block] < 0) {
435 /*
436 * Master has to serve a request to power off MDP always
437 * It also has a timer to power off. So, in case of
438 * timer expires first and DMA2 finishes later,
439 * master has to power off two times
440 * There shouldn't be multiple power-off request for
441 * other blocks
442 */
443 if (block != MDP_MASTER_BLOCK) {
444 MSM_FB_INFO("mdp_block_power_cnt[block=%d] \
445 multiple power-off request\n", block);
446 }
447 mdp_block_power_cnt[block] = 0;
448 }
449
450 if (MDP_DMA2_BLOCK == block)
451 mdp_in_processing = FALSE;
452 }
453 spin_unlock_irqrestore(&mdp_spin_lock, flag);
454
455 /*
456 * If it's in isr, we send our request to workqueue.
457 * Otherwise, processing happens in the current context
458 */
459 if (isr) {
460 /* checking all blocks power state */
461 for (i = 0; i < MDP_MAX_BLOCK; i++) {
462 if (mdp_block_power_cnt[i] > 0)
463 mdp_all_blocks_off = FALSE;
464 }
465
466 if ((mdp_all_blocks_off) && (mdp_current_clk_on)) {
467 /* send workqueue to turn off mdp power */
468 queue_delayed_work(mdp_pipe_ctrl_wq,
469 &mdp_pipe_ctrl_worker,
470 mdp_timer_duration);
471 }
472 } else {
473 down(&mdp_pipe_ctrl_mutex);
474 /* checking all blocks power state */
475 for (i = 0; i < MDP_MAX_BLOCK; i++) {
476 if (mdp_block_power_cnt[i] > 0)
477 mdp_all_blocks_off = FALSE;
478 }
479
480 /*
481 * find out whether a delayable work item is currently
482 * pending
483 */
484
485 if (delayed_work_pending(&mdp_pipe_ctrl_worker)) {
486 /*
487 * try to cancel the current work if it fails to
488 * stop (which means del_timer can't delete it
489 * from the list, it's about to expire and run),
490 * we have to let it run. queue_delayed_work won't
491 * accept the next job which is same as
492 * queue_delayed_work(mdp_timer_duration = 0)
493 */
494 cancel_delayed_work(&mdp_pipe_ctrl_worker);
495 }
496
497 if ((mdp_all_blocks_off) && (mdp_current_clk_on)) {
498 if (block == MDP_MASTER_BLOCK) {
499 mdp_current_clk_on = FALSE;
500 /* turn off MDP clks */
501 if (mdp_clk != NULL) {
502 clk_disable(mdp_clk);
503 MSM_FB_DEBUG("MDP CLK OFF\n");
504 }
505 if (mdp_pclk != NULL) {
506 clk_disable(mdp_pclk);
507 MSM_FB_DEBUG("MDP PCLK OFF\n");
508 }
509 } else {
510 /* send workqueue to turn off mdp power */
511 queue_delayed_work(mdp_pipe_ctrl_wq,
512 &mdp_pipe_ctrl_worker,
513 mdp_timer_duration);
514 }
515 } else if ((!mdp_all_blocks_off) && (!mdp_current_clk_on)) {
516 mdp_current_clk_on = TRUE;
517 /* turn on MDP clks */
518 if (mdp_clk != NULL) {
519 clk_enable(mdp_clk);
520 MSM_FB_DEBUG("MDP CLK ON\n");
521 }
522 if (mdp_pclk != NULL) {
523 clk_enable(mdp_pclk);
524 MSM_FB_DEBUG("MDP PCLK ON\n");
525 }
526 }
527 up(&mdp_pipe_ctrl_mutex);
528 }
529}
530
531#ifndef CONFIG_FB_MSM_MDP40
532irqreturn_t mdp_isr(int irq, void *ptr)
533{
534 uint32 mdp_interrupt = 0;
535 struct mdp_dma_data *dma;
536
537 mdp_is_in_isr = TRUE;
538 do {
539 mdp_interrupt = inp32(MDP_INTR_STATUS);
540 outp32(MDP_INTR_CLEAR, mdp_interrupt);
541
542 mdp_interrupt &= mdp_intr_mask;
543
544 if (mdp_interrupt & TV_ENC_UNDERRUN) {
545 mdp_interrupt &= ~(TV_ENC_UNDERRUN);
546 mdp_tv_underflow_cnt++;
547 }
548
549 if (!mdp_interrupt)
550 break;
551
552 /* DMA3 TV-Out Start */
553 if (mdp_interrupt & TV_OUT_DMA3_START) {
554 /* let's disable TV out interrupt */
555 mdp_intr_mask &= ~TV_OUT_DMA3_START;
556 outp32(MDP_INTR_ENABLE, mdp_intr_mask);
557
558 dma = &dma3_data;
559 if (dma->waiting) {
560 dma->waiting = FALSE;
561 complete(&dma->comp);
562 }
563 }
564#ifndef CONFIG_FB_MSM_MDP22
565 if (mdp_interrupt & MDP_HIST_DONE) {
566 outp32(MDP_BASE + 0x94018, 0x3);
567 outp32(MDP_INTR_CLEAR, MDP_HIST_DONE);
568 if (mdp_hist.r)
569 memcpy(mdp_hist.r, MDP_BASE + 0x94100,
570 mdp_hist.bin_cnt*4);
571 if (mdp_hist.g)
572 memcpy(mdp_hist.g, MDP_BASE + 0x94200,
573 mdp_hist.bin_cnt*4);
574 if (mdp_hist.b)
575 memcpy(mdp_hist.b, MDP_BASE + 0x94300,
576 mdp_hist.bin_cnt*4);
577 complete(&mdp_hist_comp);
578 }
579
580 /* LCDC UnderFlow */
581 if (mdp_interrupt & LCDC_UNDERFLOW) {
582 mdp_lcdc_underflow_cnt++;
583 }
584 /* LCDC Frame Start */
585 if (mdp_interrupt & LCDC_FRAME_START) {
586 /* let's disable LCDC interrupt */
587 mdp_intr_mask &= ~LCDC_FRAME_START;
588 outp32(MDP_INTR_ENABLE, mdp_intr_mask);
589
590 dma = &dma2_data;
591 if (dma->waiting) {
592 dma->waiting = FALSE;
593 complete(&dma->comp);
594 }
595 }
596
597 /* DMA2 LCD-Out Complete */
598 if (mdp_interrupt & MDP_DMA_S_DONE) {
599 dma = &dma_s_data;
600 dma->busy = FALSE;
601 mdp_pipe_ctrl(MDP_DMA_S_BLOCK, MDP_BLOCK_POWER_OFF,
602 TRUE);
603 complete(&dma->comp);
604 }
605#endif
606
607 /* DMA2 LCD-Out Complete */
608 if (mdp_interrupt & MDP_DMA_P_DONE) {
609 struct timeval now;
610 ktime_t now_k;
611
612 now_k = ktime_get_real();
613 mdp_dma2_last_update_time.tv.sec =
614 now_k.tv.sec - mdp_dma2_last_update_time.tv.sec;
615 mdp_dma2_last_update_time.tv.nsec =
616 now_k.tv.nsec - mdp_dma2_last_update_time.tv.nsec;
617
618 if (mdp_debug[MDP_DMA2_BLOCK]) {
619 jiffies_to_timeval(jiffies, &now);
620 mdp_dma2_timeval.tv_usec =
621 now.tv_usec - mdp_dma2_timeval.tv_usec;
622 }
623
624 dma = &dma2_data;
625 dma->busy = FALSE;
626 mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_OFF,
627 TRUE);
628 complete(&dma->comp);
629 }
630 /* PPP Complete */
631 if (mdp_interrupt & MDP_PPP_DONE) {
632#ifdef CONFIG_MDP_PPP_ASYNC_OP
633 mdp_ppp_djob_done();
634#else
635 mdp_pipe_ctrl(MDP_PPP_BLOCK,
636 MDP_BLOCK_POWER_OFF, TRUE);
637 if (mdp_ppp_waiting) {
638 mdp_ppp_waiting = FALSE;
639 complete(&mdp_ppp_comp);
640 }
641#endif
642 }
643 } while (1);
644
645 mdp_is_in_isr = FALSE;
646
647 return IRQ_HANDLED;
648}
649#endif
650
651static void mdp_drv_init(void)
652{
653 int i;
654
655 for (i = 0; i < MDP_MAX_BLOCK; i++) {
656 mdp_debug[i] = 0;
657 }
658
659 /* initialize spin lock and workqueue */
660 spin_lock_init(&mdp_spin_lock);
661 mdp_dma_wq = create_singlethread_workqueue("mdp_dma_wq");
662 mdp_vsync_wq = create_singlethread_workqueue("mdp_vsync_wq");
663 mdp_pipe_ctrl_wq = create_singlethread_workqueue("mdp_pipe_ctrl_wq");
664 INIT_DELAYED_WORK(&mdp_pipe_ctrl_worker,
665 mdp_pipe_ctrl_workqueue_handler);
666#ifdef CONFIG_MDP_PPP_ASYNC_OP
667 mdp_ppp_dq_init();
668#endif
669
670 /* initialize semaphore */
671 init_completion(&mdp_ppp_comp);
672 init_MUTEX(&mdp_ppp_mutex);
673 init_MUTEX(&mdp_pipe_ctrl_mutex);
674
675 dma2_data.busy = FALSE;
676 dma2_data.waiting = FALSE;
677 init_completion(&dma2_data.comp);
678 init_MUTEX(&dma2_data.mutex);
679 mutex_init(&dma2_data.ov_mutex);
680
681 dma3_data.busy = FALSE;
682 dma3_data.waiting = FALSE;
683 init_completion(&dma3_data.comp);
684 init_MUTEX(&dma3_data.mutex);
685
686 dma_s_data.busy = FALSE;
687 dma_s_data.waiting = FALSE;
688 init_completion(&dma_s_data.comp);
689 init_MUTEX(&dma_s_data.mutex);
690
691 dma_e_data.busy = FALSE;
692 dma_e_data.waiting = FALSE;
693 init_completion(&dma_e_data.comp);
694
695#ifndef CONFIG_FB_MSM_MDP22
696 init_completion(&mdp_hist_comp);
697#endif
698
699 /* initializing mdp power block counter to 0 */
700 for (i = 0; i < MDP_MAX_BLOCK; i++) {
701 mdp_block_power_cnt[i] = 0;
702 }
703
704#ifdef MSM_FB_ENABLE_DBGFS
705 {
706 struct dentry *root;
707 char sub_name[] = "mdp";
708
709 root = msm_fb_get_debugfs_root();
710 if (root != NULL) {
711 mdp_dir = debugfs_create_dir(sub_name, root);
712
713 if (mdp_dir) {
714 msm_fb_debugfs_file_create(mdp_dir,
715 "dma2_update_time_in_usec",
716 (u32 *) &mdp_dma2_update_time_in_usec);
717 msm_fb_debugfs_file_create(mdp_dir,
718 "vs_rdcnt_slow",
719 (u32 *) &mdp_lcd_rd_cnt_offset_slow);
720 msm_fb_debugfs_file_create(mdp_dir,
721 "vs_rdcnt_fast",
722 (u32 *) &mdp_lcd_rd_cnt_offset_fast);
723 msm_fb_debugfs_file_create(mdp_dir,
724 "mdp_usec_diff_threshold",
725 (u32 *) &mdp_usec_diff_threshold);
726 msm_fb_debugfs_file_create(mdp_dir,
727 "mdp_current_clk_on",
728 (u32 *) &mdp_current_clk_on);
729#ifdef CONFIG_FB_MSM_LCDC
730 msm_fb_debugfs_file_create(mdp_dir,
731 "lcdc_start_x",
732 (u32 *) &first_pixel_start_x);
733 msm_fb_debugfs_file_create(mdp_dir,
734 "lcdc_start_y",
735 (u32 *) &first_pixel_start_y);
736 msm_fb_debugfs_file_create(mdp_dir,
737 "mdp_lcdc_pclk_clk_rate",
738 (u32 *) &mdp_lcdc_pclk_clk_rate);
739 msm_fb_debugfs_file_create(mdp_dir,
740 "mdp_lcdc_pad_pclk_clk_rate",
741 (u32 *) &mdp_lcdc_pad_pclk_clk_rate);
742#endif
743 }
744 }
745 }
746#endif
747}
748
749static int mdp_probe(struct platform_device *pdev);
750static int mdp_remove(struct platform_device *pdev);
751
752static struct platform_driver mdp_driver = {
753 .probe = mdp_probe,
754 .remove = mdp_remove,
755#ifndef CONFIG_HAS_EARLYSUSPEND
756 .suspend = mdp_suspend,
757 .resume = NULL,
758#endif
759 .shutdown = NULL,
760 .driver = {
761 /*
762 * Driver name must match the device name added in
763 * platform.c.
764 */
765 .name = "mdp",
766 },
767};
768
769static int mdp_off(struct platform_device *pdev)
770{
771 int ret = 0;
772
773#ifdef MDP_HW_VSYNC
774 struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);
775#endif
776
777 ret = panel_next_off(pdev);
778
779#ifdef MDP_HW_VSYNC
780 mdp_hw_vsync_clk_disable(mfd);
781#endif
782
783 return ret;
784}
785
786static int mdp_on(struct platform_device *pdev)
787{
788#ifdef MDP_HW_VSYNC
789 struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);
790#endif
791
792 int ret = 0;
793
794#ifdef MDP_HW_VSYNC
795 mdp_hw_vsync_clk_enable(mfd);
796#endif
797
798 ret = panel_next_on(pdev);
799
800 return ret;
801}
802
803static int mdp_irq_clk_setup(void)
804{
805 int ret;
806
807#ifdef CONFIG_FB_MSM_MDP40
808 ret = request_irq(INT_MDP, mdp4_isr, IRQF_DISABLED, "MDP", 0);
809#else
810 ret = request_irq(INT_MDP, mdp_isr, IRQF_DISABLED, "MDP", 0);
811#endif
812 if (ret) {
813 printk(KERN_ERR "mdp request_irq() failed!\n");
814 return ret;
815 }
816 disable_irq(INT_MDP);
817
818 mdp_clk = clk_get(NULL, "mdp_clk");
819
820 if (IS_ERR(mdp_clk)) {
821 ret = PTR_ERR(mdp_clk);
822 printk(KERN_ERR "can't get mdp_clk error:%d!\n", ret);
823 free_irq(INT_MDP, 0);
824 return ret;
825 }
826
827 mdp_pclk = clk_get(NULL, "mdp_pclk");
828 if (IS_ERR(mdp_pclk))
829 mdp_pclk = NULL;
830
831
832#ifdef CONFIG_FB_MSM_MDP40
833 /*
834 * mdp_clk should greater than mdp_pclk always
835 */
836 clk_set_rate(mdp_clk, 122880000); /* 122.88 Mhz */
837 printk(KERN_INFO "mdp_clk: mdp_clk=%d mdp_pclk=%d\n",
838 (int)clk_get_rate(mdp_clk), (int)clk_get_rate(mdp_pclk));
839#endif
840
841 return 0;
842}
843
844static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
845static int pdev_list_cnt;
846static int mdp_resource_initialized;
847static struct msm_panel_common_pdata *mdp_pdata;
848
849static int mdp_probe(struct platform_device *pdev)
850{
851 struct platform_device *msm_fb_dev = NULL;
852 struct msm_fb_data_type *mfd;
853 struct msm_fb_panel_data *pdata = NULL;
854 int rc;
855 resource_size_t size ;
856#ifdef CONFIG_FB_MSM_MDP40
857 int intf, if_no;
858#else
859 unsigned long flag;
860#endif
861
862 if ((pdev->id == 0) && (pdev->num_resources > 0)) {
863 mdp_pdata = pdev->dev.platform_data;
864
865 size = resource_size(&pdev->resource[0]);
866 msm_mdp_base = ioremap(pdev->resource[0].start, size);
867
868 MSM_FB_INFO("MDP HW Base phy_Address = 0x%x virt = 0x%x\n",
869 (int)pdev->resource[0].start, (int)msm_mdp_base);
870
871 if (unlikely(!msm_mdp_base))
872 return -ENOMEM;
873
874 printk("irq clk setup\n");
875 rc = mdp_irq_clk_setup();
876 printk("irq clk setup done\n");
877 if (rc)
878 return rc;
879
880 /* initializing mdp hw */
881#ifdef CONFIG_FB_MSM_MDP40
882 mdp4_hw_init();
883#else
884 mdp_hw_init();
885#endif
886
887 mdp_resource_initialized = 1;
888 return 0;
889 }
890
891 if (!mdp_resource_initialized)
892 return -EPERM;
893
894 mfd = platform_get_drvdata(pdev);
895
896 if (!mfd)
897 return -ENODEV;
898
899 if (mfd->key != MFD_KEY)
900 return -EINVAL;
901
902 if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
903 return -ENOMEM;
904
905 msm_fb_dev = platform_device_alloc("msm_fb", pdev->id);
906 if (!msm_fb_dev)
907 return -ENOMEM;
908
909 /* link to the latest pdev */
910 mfd->pdev = msm_fb_dev;
911
912 /* add panel data */
913 if (platform_device_add_data
914 (msm_fb_dev, pdev->dev.platform_data,
915 sizeof(struct msm_fb_panel_data))) {
916 printk(KERN_ERR "mdp_probe: platform_device_add_data failed!\n");
917 rc = -ENOMEM;
918 goto mdp_probe_err;
919 }
920 /* data chain */
921 pdata = msm_fb_dev->dev.platform_data;
922 pdata->on = mdp_on;
923 pdata->off = mdp_off;
924 pdata->next = pdev;
925
926 switch (mfd->panel.type) {
927 case EXT_MDDI_PANEL:
928 case MDDI_PANEL:
929 case EBI2_PANEL:
930 INIT_WORK(&mfd->dma_update_worker,
931 mdp_lcd_update_workqueue_handler);
932 INIT_WORK(&mfd->vsync_resync_worker,
933 mdp_vsync_resync_workqueue_handler);
934 mfd->hw_refresh = FALSE;
935
936 if (mfd->panel.type == EXT_MDDI_PANEL) {
937 /* 15 fps -> 66 msec */
938 mfd->refresh_timer_duration = (66 * HZ / 1000);
939 } else {
940 /* 24 fps -> 42 msec */
941 mfd->refresh_timer_duration = (42 * HZ / 1000);
942 }
943
944#ifdef CONFIG_FB_MSM_MDP22
945 mfd->dma_fnc = mdp_dma2_update;
946 mfd->dma = &dma2_data;
947#else
948 if (mfd->panel_info.pdest == DISPLAY_1) {
949#ifdef CONFIG_FB_MSM_OVERLAY
950 mfd->dma_fnc = mdp4_mddi_overlay;
951#else
952 mfd->dma_fnc = mdp_dma2_update;
953#endif
954 mfd->dma = &dma2_data;
955 mfd->lut_update = mdp_lut_update_nonlcdc;
956 mfd->do_histogram = mdp_do_histogram;
957 } else {
958 mfd->dma_fnc = mdp_dma_s_update;
959 mfd->dma = &dma_s_data;
960 }
961#endif
962 if (mdp_pdata)
963 mfd->vsync_gpio = mdp_pdata->gpio;
964 else
965 mfd->vsync_gpio = -1;
966
967#ifdef CONFIG_FB_MSM_MDP40
968 if (mfd->panel.type == EBI2_PANEL)
969 intf = EBI2_INTF;
970 else
971 intf = MDDI_INTF;
972
973 if (mfd->panel_info.pdest == DISPLAY_1)
974 if_no = PRIMARY_INTF_SEL;
975 else
976 if_no = SECONDARY_INTF_SEL;
977
978 mdp4_display_intf_sel(if_no, intf);
979#endif
980 mdp_config_vsync(mfd);
981 break;
982
983 case HDMI_PANEL:
984 case LCDC_PANEL:
985 pdata->on = mdp_lcdc_on;
986 pdata->off = mdp_lcdc_off;
987 mfd->hw_refresh = TRUE;
988 mfd->cursor_update = mdp_hw_cursor_update;
989#ifndef CONFIG_FB_MSM_MDP22
990 mfd->lut_update = mdp_lut_update_lcdc;
991 mfd->do_histogram = mdp_do_histogram;
992#endif
993#ifdef CONFIG_FB_MSM_OVERLAY
994 mfd->dma_fnc = mdp4_lcdc_overlay;
995#else
996 mfd->dma_fnc = mdp_lcdc_update;
997#endif
998
999#ifdef CONFIG_FB_MSM_MDP40
1000 if (mfd->panel.type == HDMI_PANEL) {
1001 mfd->dma = &dma_e_data;
1002 mdp4_display_intf_sel(EXTERNAL_INTF_SEL, LCDC_RGB_INTF);
1003 } else {
1004 mfd->dma = &dma2_data;
1005 mdp4_display_intf_sel(PRIMARY_INTF_SEL, LCDC_RGB_INTF);
1006 }
1007#else
1008 mfd->dma = &dma2_data;
1009 spin_lock_irqsave(&mdp_spin_lock, flag);
1010 mdp_intr_mask &= ~MDP_DMA_P_DONE;
1011 outp32(MDP_INTR_ENABLE, mdp_intr_mask);
1012 spin_unlock_irqrestore(&mdp_spin_lock, flag);
1013#endif
1014 break;
1015
1016 case TV_PANEL:
1017 pdata->on = mdp_dma3_on;
1018 pdata->off = mdp_dma3_off;
1019 mfd->hw_refresh = TRUE;
1020 mfd->dma_fnc = mdp_dma3_update;
1021 mfd->dma = &dma3_data;
1022 break;
1023
1024 default:
1025 printk(KERN_ERR "mdp_probe: unknown device type!\n");
1026 rc = -ENODEV;
1027 goto mdp_probe_err;
1028 }
1029
1030 /* set driver data */
1031 platform_set_drvdata(msm_fb_dev, mfd);
1032
1033 rc = platform_device_add(msm_fb_dev);
1034 if (rc) {
1035 goto mdp_probe_err;
1036 }
1037
1038 pdev_list[pdev_list_cnt++] = pdev;
1039 return 0;
1040
1041 mdp_probe_err:
1042 platform_device_put(msm_fb_dev);
1043 return rc;
1044}
1045
1046static void mdp_suspend_sub(void)
1047{
1048 /* cancel pipe ctrl worker */
1049 cancel_delayed_work(&mdp_pipe_ctrl_worker);
1050
1051 /* for workder can't be cancelled... */
1052 flush_workqueue(mdp_pipe_ctrl_wq);
1053
1054 /* let's wait for PPP completion */
1055 while (mdp_block_power_cnt[MDP_PPP_BLOCK] > 0) ;
1056
1057 /* try to power down */
1058 mdp_pipe_ctrl(MDP_MASTER_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
1059}
1060
1061#if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND)
1062static int mdp_suspend(struct platform_device *pdev, pm_message_t state)
1063{
1064 mdp_suspend_sub();
1065 return 0;
1066}
1067#endif
1068
1069#ifdef CONFIG_HAS_EARLYSUSPEND
1070static void mdp_early_suspend(struct early_suspend *h)
1071{
1072 mdp_suspend_sub();
1073}
1074#endif
1075
1076static int mdp_remove(struct platform_device *pdev)
1077{
1078 iounmap(msm_mdp_base);
1079 return 0;
1080}
1081
1082static int mdp_register_driver(void)
1083{
1084#ifdef CONFIG_HAS_EARLYSUSPEND
1085 early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 1;
1086 early_suspend.suspend = mdp_early_suspend;
1087 register_early_suspend(&early_suspend);
1088#endif
1089
1090 return platform_driver_register(&mdp_driver);
1091}
1092
1093static int __init mdp_driver_init(void)
1094{
1095 int ret;
1096
1097 mdp_drv_init();
1098
1099 ret = mdp_register_driver();
1100 if (ret) {
1101 printk(KERN_ERR "mdp_register_driver() failed!\n");
1102 return ret;
1103 }
1104
1105#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_FB_MSM_MDP40)
1106 mdp4_debugfs_init();
1107#endif
1108
1109 return 0;
1110
1111}
1112
1113module_init(mdp_driver_init);
diff --git a/drivers/staging/msm/mdp.h b/drivers/staging/msm/mdp.h
new file mode 100644
index 000000000000..0a5d6ac386ac
--- /dev/null
+++ b/drivers/staging/msm/mdp.h
@@ -0,0 +1,695 @@
1/* Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are met:
5 * * Redistributions of source code must retain the above copyright
6 * notice, this list of conditions and the following disclaimer.
7 * * Redistributions in binary form must reproduce the above copyright
8 * notice, this list of conditions and the following disclaimer in the
9 * documentation and/or other materials provided with the distribution.
10 * * Neither the name of Code Aurora nor
11 * the names of its contributors may be used to endorse or promote
12 * products derived from this software without specific prior written
13 * permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 */
28
29#ifndef MDP_H
30#define MDP_H
31
32#include <linux/kernel.h>
33#include <linux/sched.h>
34#include <linux/time.h>
35#include <linux/init.h>
36#include <linux/interrupt.h>
37#include <linux/fb.h>
38#include <linux/hrtimer.h>
39#include "msm_mdp.h"
40
41#include <mach/hardware.h>
42#include <linux/io.h>
43
44#include <asm/system.h>
45#include <asm/mach-types.h>
46
47#include "msm_fb_panel.h"
48
49#ifdef CONFIG_MDP_PPP_ASYNC_OP
50#include "mdp_ppp_dq.h"
51#endif
52
53#ifdef BIT
54#undef BIT
55#endif
56
57#define BIT(x) (1<<(x))
58
59#define MDPOP_NOP 0
60#define MDPOP_LR BIT(0) /* left to right flip */
61#define MDPOP_UD BIT(1) /* up and down flip */
62#define MDPOP_ROT90 BIT(2) /* rotate image to 90 degree */
63#define MDPOP_ROT180 (MDPOP_UD|MDPOP_LR)
64#define MDPOP_ROT270 (MDPOP_ROT90|MDPOP_UD|MDPOP_LR)
65#define MDPOP_ASCALE BIT(7)
66#define MDPOP_ALPHAB BIT(8) /* enable alpha blending */
67#define MDPOP_TRANSP BIT(9) /* enable transparency */
68#define MDPOP_DITHER BIT(10) /* enable dither */
69#define MDPOP_SHARPENING BIT(11) /* enable sharpening */
70#define MDPOP_BLUR BIT(12) /* enable blur */
71#define MDPOP_FG_PM_ALPHA BIT(13)
72
73struct mdp_table_entry {
74 uint32_t reg;
75 uint32_t val;
76};
77
78extern struct mdp_ccs mdp_ccs_yuv2rgb ;
79extern struct mdp_ccs mdp_ccs_rgb2yuv ;
80
81/*
82 * MDP Image Structure
83 */
84typedef struct mdpImg_ {
85 uint32 imgType; /* Image type */
86 uint32 *bmy_addr; /* bitmap or y addr */
87 uint32 *cbcr_addr; /* cbcr addr */
88 uint32 width; /* image width */
89 uint32 mdpOp; /* image opertion (rotation,flip up/down, alpha/tp) */
90 uint32 tpVal; /* transparency color */
91 uint32 alpha; /* alpha percentage 0%(0x0) ~ 100%(0x100) */
92 int sp_value; /* sharpening strength */
93} MDPIMG;
94
95#ifdef CONFIG_MDP_PPP_ASYNC_OP
96#define MDP_OUTP(addr, data) mdp_ppp_outdw((uint32_t)(addr), \
97 (uint32_t)(data))
98#else
99#define MDP_OUTP(addr, data) outpdw((addr), (data))
100#endif
101
102#define MDP_KTIME2USEC(kt) (kt.tv.sec*1000000 + kt.tv.nsec/1000)
103
104#define MDP_BASE msm_mdp_base
105
106typedef enum {
107 MDP_BC_SCALE_POINT2_POINT4,
108 MDP_BC_SCALE_POINT4_POINT6,
109 MDP_BC_SCALE_POINT6_POINT8,
110 MDP_BC_SCALE_POINT8_1,
111 MDP_BC_SCALE_UP,
112 MDP_PR_SCALE_POINT2_POINT4,
113 MDP_PR_SCALE_POINT4_POINT6,
114 MDP_PR_SCALE_POINT6_POINT8,
115 MDP_PR_SCALE_POINT8_1,
116 MDP_PR_SCALE_UP,
117 MDP_SCALE_BLUR,
118 MDP_INIT_SCALE
119} MDP_SCALE_MODE;
120
121typedef enum {
122 MDP_BLOCK_POWER_OFF,
123 MDP_BLOCK_POWER_ON
124} MDP_BLOCK_POWER_STATE;
125
126typedef enum {
127 MDP_MASTER_BLOCK,
128 MDP_CMD_BLOCK,
129 MDP_PPP_BLOCK,
130 MDP_DMA2_BLOCK,
131 MDP_DMA3_BLOCK,
132 MDP_DMA_S_BLOCK,
133 MDP_DMA_E_BLOCK,
134 MDP_OVERLAY0_BLOCK,
135 MDP_OVERLAY1_BLOCK,
136 MDP_MAX_BLOCK
137} MDP_BLOCK_TYPE;
138
139/* Let's keep Q Factor power of 2 for optimization */
140#define MDP_SCALE_Q_FACTOR 512
141
142#ifdef CONFIG_FB_MSM_MDP31
143#define MDP_MAX_X_SCALE_FACTOR (MDP_SCALE_Q_FACTOR*8)
144#define MDP_MIN_X_SCALE_FACTOR (MDP_SCALE_Q_FACTOR/8)
145#define MDP_MAX_Y_SCALE_FACTOR (MDP_SCALE_Q_FACTOR*8)
146#define MDP_MIN_Y_SCALE_FACTOR (MDP_SCALE_Q_FACTOR/8)
147#else
148#define MDP_MAX_X_SCALE_FACTOR (MDP_SCALE_Q_FACTOR*4)
149#define MDP_MIN_X_SCALE_FACTOR (MDP_SCALE_Q_FACTOR/4)
150#define MDP_MAX_Y_SCALE_FACTOR (MDP_SCALE_Q_FACTOR*4)
151#define MDP_MIN_Y_SCALE_FACTOR (MDP_SCALE_Q_FACTOR/4)
152#endif
153
154/* SHIM Q Factor */
155#define PHI_Q_FACTOR 29
156#define PQF_PLUS_5 (PHI_Q_FACTOR + 5) /* due to 32 phases */
157#define PQF_PLUS_4 (PHI_Q_FACTOR + 4)
158#define PQF_PLUS_2 (PHI_Q_FACTOR + 2) /* to get 4.0 */
159#define PQF_MINUS_2 (PHI_Q_FACTOR - 2) /* to get 0.25 */
160#define PQF_PLUS_5_PLUS_2 (PQF_PLUS_5 + 2)
161#define PQF_PLUS_5_MINUS_2 (PQF_PLUS_5 - 2)
162
163#define MDP_CONVTP(tpVal) (((tpVal&0xF800)<<8)|((tpVal&0x7E0)<<5)|((tpVal&0x1F)<<3))
164
165#define MDPOP_ROTATION (MDPOP_ROT90|MDPOP_LR|MDPOP_UD)
166#define MDP_CHKBIT(val, bit) ((bit) == ((val) & (bit)))
167
168/* overlay interface API defines */
169typedef enum {
170 MORE_IBUF,
171 FINAL_IBUF,
172 COMPLETE_IBUF
173} MDP_IBUF_STATE;
174
175struct mdp_dirty_region {
176 __u32 xoffset; /* source origin in the x-axis */
177 __u32 yoffset; /* source origin in the y-axis */
178 __u32 width; /* number of pixels in the x-axis */
179 __u32 height; /* number of pixels in the y-axis */
180};
181
182/*
183 * MDP extended data types
184 */
185typedef struct mdp_roi_s {
186 uint32 x;
187 uint32 y;
188 uint32 width;
189 uint32 height;
190 int32 lcd_x;
191 int32 lcd_y;
192 uint32 dst_width;
193 uint32 dst_height;
194} MDP_ROI;
195
196typedef struct mdp_ibuf_s {
197 uint8 *buf;
198 uint32 bpp;
199 uint32 ibuf_type;
200 uint32 ibuf_width;
201 uint32 ibuf_height;
202
203 MDP_ROI roi;
204 MDPIMG mdpImg;
205
206 int32 dma_x;
207 int32 dma_y;
208 uint32 dma_w;
209 uint32 dma_h;
210
211 uint32 vsync_enable;
212 uint32 visible_swapped;
213} MDPIBUF;
214
215struct mdp_dma_data {
216 boolean busy;
217 boolean waiting;
218 struct mutex ov_mutex;
219 struct semaphore mutex;
220 struct completion comp;
221};
222
223#define MDP_CMD_DEBUG_ACCESS_BASE (MDP_BASE+0x10000)
224
225#define MDP_DMA2_TERM 0x1
226#define MDP_DMA3_TERM 0x2
227#define MDP_PPP_TERM 0x4
228#define MDP_DMA_S_TERM 0x8
229#ifdef CONFIG_FB_MSM_MDP40
230#define MDP_DMA_E_TERM 0x10
231#define MDP_OVERLAY0_TERM 0x20
232#define MDP_OVERLAY1_TERM 0x40
233#endif
234
235#define ACTIVE_START_X_EN BIT(31)
236#define ACTIVE_START_Y_EN BIT(31)
237#define ACTIVE_HIGH 0
238#define ACTIVE_LOW 1
239#define MDP_DMA_S_DONE BIT(2)
240#define LCDC_FRAME_START BIT(15)
241#define LCDC_UNDERFLOW BIT(16)
242
243#ifdef CONFIG_FB_MSM_MDP22
244#define MDP_DMA_P_DONE BIT(2)
245#else
246#define MDP_DMA_P_DONE BIT(14)
247#endif
248
249#define MDP_PPP_DONE BIT(0)
250#define TV_OUT_DMA3_DONE BIT(6)
251#define TV_ENC_UNDERRUN BIT(7)
252#define TV_OUT_DMA3_START BIT(13)
253#define MDP_HIST_DONE BIT(20)
254
255#ifdef CONFIG_FB_MSM_MDP22
256#define MDP_ANY_INTR_MASK (MDP_PPP_DONE| \
257 MDP_DMA_P_DONE| \
258 TV_ENC_UNDERRUN)
259#else
260#define MDP_ANY_INTR_MASK (MDP_PPP_DONE| \
261 MDP_DMA_P_DONE| \
262 MDP_DMA_S_DONE| \
263 LCDC_UNDERFLOW| \
264 MDP_HIST_DONE| \
265 TV_ENC_UNDERRUN)
266#endif
267
268#define MDP_TOP_LUMA 16
269#define MDP_TOP_CHROMA 0
270#define MDP_BOTTOM_LUMA 19
271#define MDP_BOTTOM_CHROMA 3
272#define MDP_LEFT_LUMA 22
273#define MDP_LEFT_CHROMA 6
274#define MDP_RIGHT_LUMA 25
275#define MDP_RIGHT_CHROMA 9
276
277#define CLR_G 0x0
278#define CLR_B 0x1
279#define CLR_R 0x2
280#define CLR_ALPHA 0x3
281
282#define CLR_Y CLR_G
283#define CLR_CB CLR_B
284#define CLR_CR CLR_R
285
286/* from lsb to msb */
287#define MDP_GET_PACK_PATTERN(a,x,y,z,bit) (((a)<<(bit*3))|((x)<<(bit*2))|((y)<<bit)|(z))
288
289/*
290 * 0x0000 0x0004 0x0008 MDP sync config
291 */
292#ifdef CONFIG_FB_MSM_MDP22
293#define MDP_SYNCFG_HGT_LOC 22
294#define MDP_SYNCFG_VSYNC_EXT_EN BIT(21)
295#define MDP_SYNCFG_VSYNC_INT_EN BIT(20)
296#else
297#define MDP_SYNCFG_HGT_LOC 21
298#define MDP_SYNCFG_VSYNC_EXT_EN BIT(20)
299#define MDP_SYNCFG_VSYNC_INT_EN BIT(19)
300#define MDP_HW_VSYNC
301#endif
302
303/*
304 * 0x0018 MDP VSYNC THREASH
305 */
306#define MDP_PRIM_BELOW_LOC 0
307#define MDP_PRIM_ABOVE_LOC 8
308
309/*
310 * MDP_PRIMARY_VSYNC_OUT_CTRL
311 * 0x0080,84,88 internal vsync pulse config
312 */
313#define VSYNC_PULSE_EN BIT(31)
314#define VSYNC_PULSE_INV BIT(30)
315
316/*
317 * 0x008c MDP VSYNC CONTROL
318 */
319#define DISP0_VSYNC_MAP_VSYNC0 0
320#define DISP0_VSYNC_MAP_VSYNC1 BIT(0)
321#define DISP0_VSYNC_MAP_VSYNC2 BIT(0)|BIT(1)
322
323#define DISP1_VSYNC_MAP_VSYNC0 0
324#define DISP1_VSYNC_MAP_VSYNC1 BIT(2)
325#define DISP1_VSYNC_MAP_VSYNC2 BIT(2)|BIT(3)
326
327#define PRIMARY_LCD_SYNC_EN BIT(4)
328#define PRIMARY_LCD_SYNC_DISABLE 0
329
330#define SECONDARY_LCD_SYNC_EN BIT(5)
331#define SECONDARY_LCD_SYNC_DISABLE 0
332
333#define EXTERNAL_LCD_SYNC_EN BIT(6)
334#define EXTERNAL_LCD_SYNC_DISABLE 0
335
336/*
337 * 0x101f0 MDP VSYNC Threshold
338 */
339#define VSYNC_THRESHOLD_ABOVE_LOC 0
340#define VSYNC_THRESHOLD_BELOW_LOC 16
341#define VSYNC_ANTI_TEAR_EN BIT(31)
342
343/*
344 * 0x10004 command config
345 */
346#define MDP_CMD_DBGBUS_EN BIT(0)
347
348/*
349 * 0x10124 or 0x101d4PPP source config
350 */
351#define PPP_SRC_C0G_8BITS (BIT(1)|BIT(0))
352#define PPP_SRC_C1B_8BITS (BIT(3)|BIT(2))
353#define PPP_SRC_C2R_8BITS (BIT(5)|BIT(4))
354#define PPP_SRC_C3A_8BITS (BIT(7)|BIT(6))
355
356#define PPP_SRC_C0G_6BITS BIT(1)
357#define PPP_SRC_C1B_6BITS BIT(3)
358#define PPP_SRC_C2R_6BITS BIT(5)
359
360#define PPP_SRC_C0G_5BITS BIT(0)
361#define PPP_SRC_C1B_5BITS BIT(2)
362#define PPP_SRC_C2R_5BITS BIT(4)
363
364#define PPP_SRC_C3_ALPHA_EN BIT(8)
365
366#define PPP_SRC_BPP_INTERLVD_1BYTES 0
367#define PPP_SRC_BPP_INTERLVD_2BYTES BIT(9)
368#define PPP_SRC_BPP_INTERLVD_3BYTES BIT(10)
369#define PPP_SRC_BPP_INTERLVD_4BYTES (BIT(10)|BIT(9))
370
371#define PPP_SRC_BPP_ROI_ODD_X BIT(11)
372#define PPP_SRC_BPP_ROI_ODD_Y BIT(12)
373#define PPP_SRC_INTERLVD_2COMPONENTS BIT(13)
374#define PPP_SRC_INTERLVD_3COMPONENTS BIT(14)
375#define PPP_SRC_INTERLVD_4COMPONENTS (BIT(14)|BIT(13))
376
377/*
378 * RGB666 unpack format
379 * TIGHT means R6+G6+B6 together
380 * LOOSE means R6+2 +G6+2+ B6+2 (with MSB)
381 * or 2+R6 +2+G6 +2+B6 (with LSB)
382 */
383#define PPP_SRC_UNPACK_TIGHT BIT(17)
384#define PPP_SRC_UNPACK_LOOSE 0
385#define PPP_SRC_UNPACK_ALIGN_LSB 0
386#define PPP_SRC_UNPACK_ALIGN_MSB BIT(18)
387
388#define PPP_SRC_FETCH_PLANES_INTERLVD 0
389#define PPP_SRC_FETCH_PLANES_PSEUDOPLNR BIT(20)
390
391#define PPP_SRC_WMV9_MODE BIT(21) /* window media version 9 */
392
393/*
394 * 0x10138 PPP operation config
395 */
396#define PPP_OP_SCALE_X_ON BIT(0)
397#define PPP_OP_SCALE_Y_ON BIT(1)
398
399#define PPP_OP_CONVERT_RGB2YCBCR 0
400#define PPP_OP_CONVERT_YCBCR2RGB BIT(2)
401#define PPP_OP_CONVERT_ON BIT(3)
402
403#define PPP_OP_CONVERT_MATRIX_PRIMARY 0
404#define PPP_OP_CONVERT_MATRIX_SECONDARY BIT(4)
405
406#define PPP_OP_LUT_C0_ON BIT(5)
407#define PPP_OP_LUT_C1_ON BIT(6)
408#define PPP_OP_LUT_C2_ON BIT(7)
409
410/* rotate or blend enable */
411#define PPP_OP_ROT_ON BIT(8)
412
413#define PPP_OP_ROT_90 BIT(9)
414#define PPP_OP_FLIP_LR BIT(10)
415#define PPP_OP_FLIP_UD BIT(11)
416
417#define PPP_OP_BLEND_ON BIT(12)
418
419#define PPP_OP_BLEND_SRCPIXEL_ALPHA 0
420#define PPP_OP_BLEND_DSTPIXEL_ALPHA BIT(13)
421#define PPP_OP_BLEND_CONSTANT_ALPHA BIT(14)
422#define PPP_OP_BLEND_SRCPIXEL_TRANSP (BIT(13)|BIT(14))
423
424#define PPP_OP_BLEND_ALPHA_BLEND_NORMAL 0
425#define PPP_OP_BLEND_ALPHA_BLEND_REVERSE BIT(15)
426
427#define PPP_OP_DITHER_EN BIT(16)
428
429#define PPP_OP_COLOR_SPACE_RGB 0
430#define PPP_OP_COLOR_SPACE_YCBCR BIT(17)
431
432#define PPP_OP_SRC_CHROMA_RGB 0
433#define PPP_OP_SRC_CHROMA_H2V1 BIT(18)
434#define PPP_OP_SRC_CHROMA_H1V2 BIT(19)
435#define PPP_OP_SRC_CHROMA_420 (BIT(18)|BIT(19))
436#define PPP_OP_SRC_CHROMA_COSITE 0
437#define PPP_OP_SRC_CHROMA_OFFSITE BIT(20)
438
439#define PPP_OP_DST_CHROMA_RGB 0
440#define PPP_OP_DST_CHROMA_H2V1 BIT(21)
441#define PPP_OP_DST_CHROMA_H1V2 BIT(22)
442#define PPP_OP_DST_CHROMA_420 (BIT(21)|BIT(22))
443#define PPP_OP_DST_CHROMA_COSITE 0
444#define PPP_OP_DST_CHROMA_OFFSITE BIT(23)
445
446#define PPP_BLEND_CALPHA_TRNASP BIT(24)
447
448#define PPP_OP_BG_CHROMA_RGB 0
449#define PPP_OP_BG_CHROMA_H2V1 BIT(25)
450#define PPP_OP_BG_CHROMA_H1V2 BIT(26)
451#define PPP_OP_BG_CHROMA_420 BIT(25)|BIT(26)
452#define PPP_OP_BG_CHROMA_SITE_COSITE 0
453#define PPP_OP_BG_CHROMA_SITE_OFFSITE BIT(27)
454#define PPP_OP_DEINT_EN BIT(29)
455
456#define PPP_BLEND_BG_USE_ALPHA_SEL (1 << 0)
457#define PPP_BLEND_BG_ALPHA_REVERSE (1 << 3)
458#define PPP_BLEND_BG_SRCPIXEL_ALPHA (0 << 1)
459#define PPP_BLEND_BG_DSTPIXEL_ALPHA (1 << 1)
460#define PPP_BLEND_BG_CONSTANT_ALPHA (2 << 1)
461#define PPP_BLEND_BG_CONST_ALPHA_VAL(x) ((x) << 24)
462
463#define PPP_OP_DST_RGB 0
464#define PPP_OP_DST_YCBCR BIT(30)
465/*
466 * 0x10150 PPP destination config
467 */
468#define PPP_DST_C0G_8BIT (BIT(0)|BIT(1))
469#define PPP_DST_C1B_8BIT (BIT(3)|BIT(2))
470#define PPP_DST_C2R_8BIT (BIT(5)|BIT(4))
471#define PPP_DST_C3A_8BIT (BIT(7)|BIT(6))
472
473#define PPP_DST_C0G_6BIT BIT(1)
474#define PPP_DST_C1B_6BIT BIT(3)
475#define PPP_DST_C2R_6BIT BIT(5)
476
477#define PPP_DST_C0G_5BIT BIT(0)
478#define PPP_DST_C1B_5BIT BIT(2)
479#define PPP_DST_C2R_5BIT BIT(4)
480
481#define PPP_DST_C3A_8BIT (BIT(7)|BIT(6))
482#define PPP_DST_C3ALPHA_EN BIT(8)
483
484#define PPP_DST_PACKET_CNT_INTERLVD_2ELEM BIT(9)
485#define PPP_DST_PACKET_CNT_INTERLVD_3ELEM BIT(10)
486#define PPP_DST_PACKET_CNT_INTERLVD_4ELEM (BIT(10)|BIT(9))
487#define PPP_DST_PACKET_CNT_INTERLVD_6ELEM (BIT(11)|BIT(9))
488
489#define PPP_DST_PACK_LOOSE 0
490#define PPP_DST_PACK_TIGHT BIT(13)
491#define PPP_DST_PACK_ALIGN_LSB 0
492#define PPP_DST_PACK_ALIGN_MSB BIT(14)
493
494#define PPP_DST_OUT_SEL_AXI 0
495#define PPP_DST_OUT_SEL_MDDI BIT(15)
496
497#define PPP_DST_BPP_2BYTES BIT(16)
498#define PPP_DST_BPP_3BYTES BIT(17)
499#define PPP_DST_BPP_4BYTES (BIT(17)|BIT(16))
500
501#define PPP_DST_PLANE_INTERLVD 0
502#define PPP_DST_PLANE_PLANAR BIT(18)
503#define PPP_DST_PLANE_PSEUDOPLN BIT(19)
504
505#define PPP_DST_TO_TV BIT(20)
506
507#define PPP_DST_MDDI_PRIMARY 0
508#define PPP_DST_MDDI_SECONDARY BIT(21)
509#define PPP_DST_MDDI_EXTERNAL BIT(22)
510
511/*
512 * 0x10180 DMA config
513 */
514#define DMA_DSTC0G_8BITS (BIT(1)|BIT(0))
515#define DMA_DSTC1B_8BITS (BIT(3)|BIT(2))
516#define DMA_DSTC2R_8BITS (BIT(5)|BIT(4))
517
518#define DMA_DSTC0G_6BITS BIT(1)
519#define DMA_DSTC1B_6BITS BIT(3)
520#define DMA_DSTC2R_6BITS BIT(5)
521
522#define DMA_DSTC0G_5BITS BIT(0)
523#define DMA_DSTC1B_5BITS BIT(2)
524#define DMA_DSTC2R_5BITS BIT(4)
525
526#define DMA_PACK_TIGHT BIT(6)
527#define DMA_PACK_LOOSE 0
528#define DMA_PACK_ALIGN_LSB 0
529/*
530 * use DMA_PACK_ALIGN_MSB if the upper 6 bits from 8 bits output
531 * from LCDC block maps into 6 pins out to the panel
532 */
533#define DMA_PACK_ALIGN_MSB BIT(7)
534#define DMA_PACK_PATTERN_RGB \
535 (MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 2)<<8)
536#define DMA_PACK_PATTERN_BGR \
537 (MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 2)<<8)
538#define DMA_OUT_SEL_AHB 0
539#define DMA_OUT_SEL_LCDC BIT(20)
540#define DMA_IBUF_FORMAT_RGB888 0
541#define DMA_IBUF_FORMAT_xRGB8888_OR_ARGB8888 BIT(26)
542
543#ifdef CONFIG_FB_MSM_MDP22
544#define DMA_OUT_SEL_MDDI BIT(14)
545#define DMA_AHBM_LCD_SEL_PRIMARY 0
546#define DMA_AHBM_LCD_SEL_SECONDARY BIT(15)
547#define DMA_IBUF_C3ALPHA_EN BIT(16)
548#define DMA_DITHER_EN BIT(17)
549#define DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY 0
550#define DMA_MDDI_DMAOUT_LCD_SEL_SECONDARY BIT(18)
551#define DMA_MDDI_DMAOUT_LCD_SEL_EXTERNAL BIT(19)
552#define DMA_IBUF_FORMAT_RGB565 BIT(20)
553#define DMA_IBUF_FORMAT_RGB888_OR_ARGB8888 0
554#define DMA_IBUF_NONCONTIGUOUS BIT(21)
555#else
556#define DMA_OUT_SEL_MDDI BIT(19)
557#define DMA_AHBM_LCD_SEL_PRIMARY 0
558#define DMA_AHBM_LCD_SEL_SECONDARY 0
559#define DMA_IBUF_C3ALPHA_EN 0
560#define DMA_DITHER_EN BIT(24)
561#define DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY 0
562#define DMA_MDDI_DMAOUT_LCD_SEL_SECONDARY 0
563#define DMA_MDDI_DMAOUT_LCD_SEL_EXTERNAL 0
564#define DMA_IBUF_FORMAT_RGB565 BIT(25)
565#define DMA_IBUF_NONCONTIGUOUS 0
566#endif
567
568/*
569 * MDDI Register
570 */
571#define MDDI_VDO_PACKET_DESC 0x5666
572
573#ifdef CONFIG_FB_MSM_MDP40
574#define MDP_INTR_ENABLE (msm_mdp_base + 0x0050)
575#define MDP_INTR_STATUS (msm_mdp_base + 0x0054)
576#define MDP_INTR_CLEAR (msm_mdp_base + 0x0058)
577#define MDP_EBI2_LCD0 (msm_mdp_base + 0x0060)
578#define MDP_EBI2_LCD1 (msm_mdp_base + 0x0064)
579#define MDP_EBI2_PORTMAP_MODE (msm_mdp_base + 0x0070)
580
581#define MDP_DMA_P_HIST_INTR_STATUS (msm_mdp_base + 0x95014)
582#define MDP_DMA_P_HIST_INTR_CLEAR (msm_mdp_base + 0x95018)
583#define MDP_DMA_P_HIST_INTR_ENABLE (msm_mdp_base + 0x9501C)
584#else
585#define MDP_INTR_ENABLE (msm_mdp_base + 0x0020)
586#define MDP_INTR_STATUS (msm_mdp_base + 0x0024)
587#define MDP_INTR_CLEAR (msm_mdp_base + 0x0028)
588#define MDP_EBI2_LCD0 (msm_mdp_base + 0x003c)
589#define MDP_EBI2_LCD1 (msm_mdp_base + 0x0040)
590#define MDP_EBI2_PORTMAP_MODE (msm_mdp_base + 0x005c)
591#endif
592
593#define MDP_FULL_BYPASS_WORD43 (msm_mdp_base + 0x101ac)
594
595#define MDP_CSC_PFMVn(n) (msm_mdp_base + 0x40400 + 4 * (n))
596#define MDP_CSC_PRMVn(n) (msm_mdp_base + 0x40440 + 4 * (n))
597#define MDP_CSC_PRE_BV1n(n) (msm_mdp_base + 0x40500 + 4 * (n))
598#define MDP_CSC_PRE_BV2n(n) (msm_mdp_base + 0x40540 + 4 * (n))
599#define MDP_CSC_POST_BV1n(n) (msm_mdp_base + 0x40580 + 4 * (n))
600#define MDP_CSC_POST_BV2n(n) (msm_mdp_base + 0x405c0 + 4 * (n))
601
602#ifdef CONFIG_FB_MSM_MDP31
603#define MDP_CSC_PRE_LV1n(n) (msm_mdp_base + 0x40600 + 4 * (n))
604#define MDP_CSC_PRE_LV2n(n) (msm_mdp_base + 0x40640 + 4 * (n))
605#define MDP_CSC_POST_LV1n(n) (msm_mdp_base + 0x40680 + 4 * (n))
606#define MDP_CSC_POST_LV2n(n) (msm_mdp_base + 0x406c0 + 4 * (n))
607#define MDP_PPP_SCALE_COEFF_LSBn(n) (msm_mdp_base + 0x50400 + 8 * (n))
608#define MDP_PPP_SCALE_COEFF_MSBn(n) (msm_mdp_base + 0x50404 + 8 * (n))
609
610#define SCALE_D0_SET 0
611#define SCALE_D1_SET BIT(0)
612#define SCALE_D2_SET BIT(1)
613#define SCALE_U1_SET (BIT(0)|BIT(1))
614
615#else
616#define MDP_CSC_PRE_LV1n(n) (msm_mdp_base + 0x40580 + 4 * (n))
617#endif
618
619#define MDP_CURSOR_WIDTH 64
620#define MDP_CURSOR_HEIGHT 64
621#define MDP_CURSOR_SIZE (MDP_CURSOR_WIDTH*MDP_CURSOR_WIDTH*4)
622
623#define MDP_DMA_P_LUT_C0_EN BIT(0)
624#define MDP_DMA_P_LUT_C1_EN BIT(1)
625#define MDP_DMA_P_LUT_C2_EN BIT(2)
626#define MDP_DMA_P_LUT_POST BIT(4)
627
628void mdp_hw_init(void);
629int mdp_ppp_pipe_wait(void);
630void mdp_pipe_kickoff(uint32 term, struct msm_fb_data_type *mfd);
631void mdp_pipe_ctrl(MDP_BLOCK_TYPE block, MDP_BLOCK_POWER_STATE state,
632 boolean isr);
633void mdp_set_dma_pan_info(struct fb_info *info, struct mdp_dirty_region *dirty,
634 boolean sync);
635void mdp_dma_pan_update(struct fb_info *info);
636void mdp_refresh_screen(unsigned long data);
637int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req,
638 struct file **pp_src, struct file **pp_dest);
639void mdp_lcd_update_workqueue_handler(struct work_struct *work);
640void mdp_vsync_resync_workqueue_handler(struct work_struct *work);
641void mdp_dma2_update(struct msm_fb_data_type *mfd);
642void mdp_config_vsync(struct msm_fb_data_type *);
643uint32 mdp_get_lcd_line_counter(struct msm_fb_data_type *mfd);
644enum hrtimer_restart mdp_dma2_vsync_hrtimer_handler(struct hrtimer *ht);
645void mdp_set_scale(MDPIBUF *iBuf,
646 uint32 dst_roi_width,
647 uint32 dst_roi_height,
648 boolean inputRGB, boolean outputRGB, uint32 *pppop_reg_ptr);
649void mdp_init_scale_table(void);
650void mdp_adjust_start_addr(uint8 **src0,
651 uint8 **src1,
652 int v_slice,
653 int h_slice,
654 int x,
655 int y,
656 uint32 width,
657 uint32 height, int bpp, MDPIBUF *iBuf, int layer);
658void mdp_set_blend_attr(MDPIBUF *iBuf,
659 uint32 *alpha,
660 uint32 *tpVal,
661 uint32 perPixelAlpha, uint32 *pppop_reg_ptr);
662
663int mdp_dma3_on(struct platform_device *pdev);
664int mdp_dma3_off(struct platform_device *pdev);
665void mdp_dma3_update(struct msm_fb_data_type *mfd);
666
667int mdp_lcdc_on(struct platform_device *pdev);
668int mdp_lcdc_off(struct platform_device *pdev);
669void mdp_lcdc_update(struct msm_fb_data_type *mfd);
670int mdp_hw_cursor_update(struct fb_info *info, struct fb_cursor *cursor);
671void mdp_enable_irq(uint32 term);
672void mdp_disable_irq(uint32 term);
673void mdp_disable_irq_nolock(uint32 term);
674uint32_t mdp_get_bytes_per_pixel(uint32_t format);
675
676#ifdef MDP_HW_VSYNC
677void mdp_hw_vsync_clk_enable(struct msm_fb_data_type *mfd);
678void mdp_hw_vsync_clk_disable(struct msm_fb_data_type *mfd);
679#endif
680
681void mdp_dma_s_update(struct msm_fb_data_type *mfd);
682
683/* Added to support flipping */
684void mdp_set_offset_info(struct fb_info *info, uint32 address, uint32 interval);
685
686int get_gem_img(struct mdp_img *img, unsigned long *start,
687 unsigned long *len);
688int get_img(struct mdp_img *img, struct fb_info *info,
689 unsigned long *start, unsigned long *len,
690 struct file **pp_file);
691
692
693/*int get_img(struct msmfb_data *img, struct fb_info *info,
694 unsigned long *start, unsigned long *len, struct file **pp_file);*/
695#endif /* MDP_H */
diff --git a/drivers/staging/msm/mdp4.h b/drivers/staging/msm/mdp4.h
new file mode 100644
index 000000000000..26ec8f12cf64
--- /dev/null
+++ b/drivers/staging/msm/mdp4.h
@@ -0,0 +1,352 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are met:
5 * * Redistributions of source code must retain the above copyright
6 * notice, this list of conditions and the following disclaimer.
7 * * Redistributions in binary form must reproduce the above copyright
8 * notice, this list of conditions and the following disclaimer in the
9 * documentation and/or other materials provided with the distribution.
10 * * Neither the name of Code Aurora nor
11 * the names of its contributors may be used to endorse or promote
12 * products derived from this software without specific prior written
13 * permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 */
28
29#ifndef MDP4_H
30#define MDP4_H
31
32extern struct mdp_dma_data dma2_data;
33extern struct mdp_dma_data dma_s_data;
34extern struct mdp_dma_data dma_e_data;
35extern struct mdp_histogram mdp_hist;
36extern struct completion mdp_hist_comp;
37extern boolean mdp_is_in_isr;
38extern uint32 mdp_intr_mask;
39extern spinlock_t mdp_spin_lock;
40
41
42#define MDP4_NONBLOCKING /* enable non blocking ioctl */
43
44#define MDP4_OVERLAYPROC0_BASE 0x10000
45#define MDP4_OVERLAYPROC1_BASE 0x18000
46
47#define MDP4_VIDEO_BASE 0x20000
48#define MDP4_VIDEO_OFF 0x10000
49
50#define MDP4_RGB_BASE 0x40000
51#define MDP4_RGB_OFF 0x10000
52
53enum { /* display */
54 PRIMARY_INTF_SEL,
55 SECONDARY_INTF_SEL,
56 EXTERNAL_INTF_SEL
57};
58
59enum {
60 LCDC_RGB_INTF,
61 DTV_INTF = LCDC_RGB_INTF,
62 MDDI_LCDC_INTF,
63 MDDI_INTF,
64 EBI2_INTF
65};
66
67enum {
68 MDDI_PRIMARY_SET,
69 MDDI_SECONDARY_SET,
70 MDDI_EXTERNAL_SET
71};
72
73enum {
74 EBI2_LCD0,
75 EBI2_LCD1
76};
77
78enum {
79 OVERLAY_MODE_NONE,
80 OVERLAY_MODE_BLT
81};
82
83enum {
84 OVERLAY_REFRESH_ON_DEMAND,
85 OVERLAY_REFRESH_VSYNC,
86 OVERLAY_REFRESH_VSYNC_HALF,
87 OVERLAY_REFRESH_VSYNC_QUARTER
88};
89
90enum {
91 OVERLAY_FRAMEBUF,
92 OVERLAY_DIRECTOUT
93};
94
95/* system interrupts */
96#define INTR_OVERLAY0_DONE BIT(0)
97#define INTR_OVERLAY1_DONE BIT(1)
98#define INTR_DMA_S_DONE BIT(2)
99#define INTR_DMA_E_DONE BIT(3)
100#define INTR_DMA_P_DONE BIT(4)
101#define INTR_VG1_HISTOGRAM BIT(5)
102#define INTR_VG2_HISTOGRAM BIT(6)
103#define INTR_PRIMARY_VSYNC BIT(7)
104#define INTR_PRIMARY_INTF_UDERRUN BIT(8)
105#define INTR_EXTERNAL_VSYNC BIT(9)
106#define INTR_EXTERNAL_INTF_UDERRUN BIT(10)
107#define INTR_DMA_P_HISTOGRAM BIT(17)
108
109/* histogram interrupts */
110#define INTR_HIST_DONE BIT(0)
111#define INTR_HIST_RESET_SEQ_DONE BIT(1)
112
113
114#ifdef CONFIG_FB_MSM_OVERLAY
115#define MDP4_ANY_INTR_MASK (INTR_OVERLAY0_DONE)
116#else
117#define MDP4_ANY_INTR_MASK (INTR_DMA_P_DONE)
118#endif
119
120enum {
121 OVERLAY_PIPE_RGB1,
122 OVERLAY_PIPE_RGB2,
123};
124
125enum {
126 OVERLAY_PIPE_VG1, /* video/graphic */
127 OVERLAY_PIPE_VG2
128};
129
130enum {
131 OVERLAY_TYPE_RGB,
132 OVERLAY_TYPE_VG /* video/graphic */
133};
134
135enum {
136 MDP4_MIXER0,
137 MDP4_MIXER1
138};
139
140#define MDP4_MAX_MIXER 2
141
142enum {
143 OVERLAY_PLANE_INTERLEAVED,
144 OVERLAY_PLANE_PLANAR,
145 OVERLAY_PLANE_PSEUDO_PLANAR
146};
147
148enum {
149 MDP4_MIXER_STAGE_UNUNSED, /* pipe not used */
150 MDP4_MIXER_STAGE_BASE,
151 MDP4_MIXER_STAGE0, /* zorder 0 */
152 MDP4_MIXER_STAGE1, /* zorder 1 */
153 MDP4_MIXER_STAGE2 /* zorder 2 */
154};
155
156#define MDP4_MAX_STAGE 4
157
158enum {
159 MDP4_FRAME_FORMAT_LINEAR,
160 MDP4_FRAME_FORMAT_ARGB_TILE,
161 MDP4_FRAME_FORMAT_VIDEO_SUPERTILE
162};
163
164enum {
165 MDP4_CHROMA_RGB,
166 MDP4_CHROMA_H2V1,
167 MDP4_CHROMA_H1V2,
168 MDP4_CHROMA_420
169};
170
171#define MDP4_BLEND_BG_TRANSP_EN BIT(9)
172#define MDP4_BLEND_FG_TRANSP_EN BIT(8)
173#define MDP4_BLEND_BG_MOD_ALPHA BIT(7)
174#define MDP4_BLEND_BG_INV_ALPHA BIT(6)
175#define MDP4_BLEND_BG_ALPHA_FG_CONST (0 << 4)
176#define MDP4_BLEND_BG_ALPHA_BG_CONST (1 << 4)
177#define MDP4_BLEND_BG_ALPHA_FG_PIXEL (2 << 4)
178#define MDP4_BLEND_BG_ALPHA_BG_PIXEL (3 << 4)
179#define MDP4_BLEND_FG_MOD_ALPHA BIT(3)
180#define MDP4_BLEND_FG_INV_ALPHA BIT(2)
181#define MDP4_BLEND_FG_ALPHA_FG_CONST (0 << 0)
182#define MDP4_BLEND_FG_ALPHA_BG_CONST (1 << 0)
183#define MDP4_BLEND_FG_ALPHA_FG_PIXEL (2 << 0)
184#define MDP4_BLEND_FG_ALPHA_BG_PIXEL (3 << 0)
185
186#define MDP4_FORMAT_SOLID_FILL BIT(22)
187#define MDP4_FORMAT_UNPACK_ALIGN_MSB BIT(18)
188#define MDP4_FORMAT_UNPACK_TIGHT BIT(17)
189#define MDP4_FORMAT_90_ROTATED BIT(12)
190#define MDP4_FORMAT_ALPHA_ENABLE BIT(8)
191
192#define MDP4_OP_DEINT_ODD_REF BIT(19)
193#define MDP4_OP_IGC_LUT_EN BIT(16)
194#define MDP4_OP_DITHER_EN BIT(15)
195#define MDP4_OP_FLIP_UD BIT(14)
196#define MDP4_OP_FLIP_LR BIT(13)
197#define MDP4_OP_CSC_EN BIT(11)
198#define MDP4_OP_SRC_DATA_YCBCR BIT(9)
199#define MDP4_OP_SCALEY_FIR (0 << 4)
200#define MDP4_OP_SCALEY_MN_PHASE (1 << 4)
201#define MDP4_OP_SCALEY_PIXEL_RPT (2 << 4)
202#define MDP4_OP_SCALEX_FIR (0 << 2)
203#define MDP4_OP_SCALEX_MN_PHASE (1 << 2)
204#define MDP4_OP_SCALEX_PIXEL_RPT (2 << 2)
205#define MDP4_OP_SCALEY_EN BIT(1)
206#define MDP4_OP_SCALEX_EN BIT(0)
207
208#define MDP4_PIPE_PER_MIXER 2
209
210#define MDP4_MAX_PLANE 4
211
212#define MDP4_MAX_VIDEO_PIPE 2
213#define MDP4_MAX_RGB_PIPE 2
214#define MDP4_MAX_OVERLAY_PIPE 16
215
216
217struct mdp4_overlay_pipe {
218 uint32 pipe_type; /* rgb, video/graphic */
219 uint32 pipe_num;
220 uint32 pipe_ndx;
221 uint32 mixer_num; /* which mixer used */
222 uint32 mixer_stage; /* which stage of mixer used */
223 uint32 src_format;
224 uint32 src_width; /* source img width */
225 uint32 src_height; /* source img height */
226 uint32 src_w; /* roi */
227 uint32 src_h; /* roi */
228 uint32 src_x; /* roi */
229 uint32 src_y; /* roi */
230 uint32 dst_w; /* roi */
231 uint32 dst_h; /* roi */
232 uint32 dst_x; /* roi */
233 uint32 dst_y; /* roi */
234 uint32 op_mode;
235 uint32 transp;
236 uint32 blend_op;
237 uint32 phasex_step;
238 uint32 phasey_step;
239 uint32 alpha;
240 uint32 is_fg; /* control alpha & color key */
241 uint32 srcp0_addr; /* interleave, luma */
242 uint32 srcp0_ystride;
243 uint32 srcp1_addr; /* pseudoplanar, chroma plane */
244 uint32 srcp1_ystride;
245 uint32 srcp2_addr; /* planar color 2*/
246 uint32 srcp2_ystride;
247 uint32 srcp3_addr; /* alpha/color 3 */
248 uint32 srcp3_ystride;
249 uint32 fetch_plane;
250 uint32 frame_format; /* video */
251 uint32 chroma_site; /* video */
252 uint32 chroma_sample; /* video */
253 uint32 solid_fill;
254 uint32 vc1_reduce; /* video */
255 uint32 fatch_planes; /* video */
256 uint32 unpack_align_msb;/* 0 to LSB, 1 to MSB */
257 uint32 unpack_tight;/* 0 for loose, 1 for tight */
258 uint32 unpack_count;/* 0 = 1 component, 1 = 2 component ... */
259 uint32 rotated_90; /* has been rotated 90 degree */
260 uint32 bpp; /* byte per pixel */
261 uint32 alpha_enable;/* source has alpha */
262 /*
263 * number of bits for source component,
264 * 0 = 1 bit, 1 = 2 bits, 2 = 6 bits, 3 = 8 bits
265 */
266 uint32 a_bit; /* component 3, alpha */
267 uint32 r_bit; /* component 2, R_Cr */
268 uint32 b_bit; /* component 1, B_Cb */
269 uint32 g_bit; /* component 0, G_lumz */
270 /*
271 * unpack pattern
272 * A = C3, R = C2, B = C1, G = C0
273 */
274 uint32 element3; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */
275 uint32 element2; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */
276 uint32 element1; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */
277 uint32 element0; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */
278 struct completion comp;
279 struct mdp_overlay req_data;
280};
281
282void mdp4_sw_reset(unsigned long bits);
283void mdp4_display_intf_sel(int output, unsigned long intf);
284void mdp4_overlay_cfg(int layer, int blt_mode, int refresh, int direct_out);
285void mdp4_ebi2_lcd_setup(int lcd, unsigned long base, int ystride);
286void mdp4_mddi_setup(int which, unsigned long id);
287unsigned long mdp4_display_status(void);
288void mdp4_enable_clk_irq(void);
289void mdp4_disable_clk_irq(void);
290void mdp4_dma_p_update(struct msm_fb_data_type *mfd);
291void mdp4_dma_s_update(struct msm_fb_data_type *mfd);
292void mdp_pipe_ctrl(MDP_BLOCK_TYPE block, MDP_BLOCK_POWER_STATE state,
293 boolean isr);
294void mdp4_pipe_kickoff(uint32 pipe, struct msm_fb_data_type *mfd);
295int mdp4_lcdc_on(struct platform_device *pdev);
296int mdp4_lcdc_off(struct platform_device *pdev);
297void mdp4_lcdc_update(struct msm_fb_data_type *mfd);
298void mdp4_intr_clear_set(ulong clear, ulong set);
299void mdp4_dma_p_cfg(void);
300void mdp4_hw_init(void);
301void mdp4_isr_read(int);
302void mdp4_clear_lcdc(void);
303void mdp4_mixer_blend_init(int mixer_num);
304void mdp4_vg_qseed_init(int vg_num);
305void mdp4_vg_csc_mv_setup(int vp_num);
306void mdp4_vg_csc_pre_bv_setup(int vp_num);
307void mdp4_vg_csc_post_bv_setup(int vp_num);
308void mdp4_vg_csc_pre_lv_setup(int vp_num);
309void mdp4_vg_csc_post_lv_setup(int vp_num);
310irqreturn_t mdp4_isr(int irq, void *ptr);
311void mdp4_overlay_format_to_pipe(uint32 format, struct mdp4_overlay_pipe *pipe);
312uint32 mdp4_overlay_format(struct mdp4_overlay_pipe *pipe);
313uint32 mdp4_overlay_unpack_pattern(struct mdp4_overlay_pipe *pipe);
314uint32 mdp4_overlay_op_mode(struct mdp4_overlay_pipe *pipe);
315void mdp4_lcdc_overlay(struct msm_fb_data_type *mfd);
316void mdp4_overlay_rgb_setup(struct mdp4_overlay_pipe *pipe);
317void mdp4_overlay_reg_flush(struct mdp4_overlay_pipe *pipe, int all);
318void mdp4_mixer_blend_setup(struct mdp4_overlay_pipe *pipe);
319void mdp4_mixer_stage_up(struct mdp4_overlay_pipe *pipe);
320void mdp4_mixer_stage_down(struct mdp4_overlay_pipe *pipe);
321int mdp4_mixer_stage_can_run(struct mdp4_overlay_pipe *pipe);
322void mdp4_overlayproc_cfg(struct mdp4_overlay_pipe *pipe);
323void mdp4_mddi_overlay(struct msm_fb_data_type *mfd);
324int mdp4_overlay_format2type(uint32 format);
325int mdp4_overlay_format2pipe(struct mdp4_overlay_pipe *pipe);
326int mdp4_overlay_get(struct fb_info *info, struct mdp_overlay *req);
327int mdp4_overlay_set(struct fb_info *info, struct mdp_overlay *req);
328int mdp4_overlay_unset(struct fb_info *info, int ndx);
329int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req,
330 struct file **pp_src_file);
331struct mdp4_overlay_pipe *mdp4_overlay_pipe_alloc(void);
332void mdp4_overlay_pipe_free(struct mdp4_overlay_pipe *pipe);
333void mdp4_overlay_dmap_cfg(struct msm_fb_data_type *mfd, int lcdc);
334void mdp4_overlay_dmap_xy(struct mdp4_overlay_pipe *pipe);
335int mdp4_overlay_active(int mixer);
336void mdp4_overlay0_done_lcdc(void);
337void mdp4_overlay0_done_mddi(void);
338void mdp4_mddi_overlay_restore(void);
339void mdp4_mddi_overlay_kickoff(struct msm_fb_data_type *mfd,
340 struct mdp4_overlay_pipe *pipe);
341void mdp4_rgb_igc_lut_setup(int num);
342void mdp4_vg_igc_lut_setup(int num);
343void mdp4_mixer_gc_lut_setup(int mixer_num);
344
345#ifdef CONFIG_DEBUG_FS
346int mdp4_debugfs_init(void);
347#endif
348
349int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req,
350 struct file **pp_src_file, struct file **pp_dst_file);
351
352#endif /* MDP_H */
diff --git a/drivers/staging/msm/mdp4_debugfs.c b/drivers/staging/msm/mdp4_debugfs.c
new file mode 100644
index 000000000000..844d46775ecd
--- /dev/null
+++ b/drivers/staging/msm/mdp4_debugfs.c
@@ -0,0 +1,181 @@
1/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17#include <linux/module.h>
18#include <linux/kernel.h>
19#include <linux/sched.h>
20#include <linux/time.h>
21#include <linux/init.h>
22#include <linux/interrupt.h>
23#include <linux/spinlock.h>
24#include <linux/hrtimer.h>
25#include <linux/clk.h>
26#include <mach/hardware.h>
27#include <linux/io.h>
28#include <linux/debugfs.h>
29
30#include <asm/system.h>
31#include <asm/mach-types.h>
32#include <linux/semaphore.h>
33#include <linux/uaccess.h>
34
35#include "mdp.h"
36#include "msm_fb.h"
37#include "mdp4.h"
38
39
40#define MDP4_DEBUG_BUF 128
41
42
43static char mdp4_debug_buf[MDP4_DEBUG_BUF];
44static ulong mdp4_debug_offset;
45static ulong mdp4_base_addr;
46
47static int mdp4_offset_set(void *data, u64 val)
48{
49 mdp4_debug_offset = (int)val;
50 return 0;
51}
52
53static int mdp4_offset_get(void *data, u64 *val)
54{
55 *val = (u64)mdp4_debug_offset;
56 return 0;
57}
58
59DEFINE_SIMPLE_ATTRIBUTE(
60 mdp4_offset_fops,
61 mdp4_offset_get,
62 mdp4_offset_set,
63 "%llx\n");
64
65
66static int mdp4_debugfs_open(struct inode *inode, struct file *file)
67{
68 /* non-seekable */
69 file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
70 return 0;
71}
72
73static int mdp4_debugfs_release(struct inode *inode, struct file *file)
74{
75 return 0;
76}
77
78static ssize_t mdp4_debugfs_write(
79 struct file *file,
80 const char __user *buff,
81 size_t count,
82 loff_t *ppos)
83{
84 int cnt;
85 unsigned int data;
86
87 printk(KERN_INFO "%s: offset=%d count=%d *ppos=%d\n",
88 __func__, (int)mdp4_debug_offset, (int)count, (int)*ppos);
89
90 if (count > sizeof(mdp4_debug_buf))
91 return -EFAULT;
92
93 if (copy_from_user(mdp4_debug_buf, buff, count))
94 return -EFAULT;
95
96
97 mdp4_debug_buf[count] = 0; /* end of string */
98
99 cnt = sscanf(mdp4_debug_buf, "%x", &data);
100 if (cnt < 1) {
101 printk(KERN_ERR "%s: sscanf failed cnt=%d" , __func__, cnt);
102 return -EINVAL;
103 }
104
105 writel(&data, mdp4_base_addr + mdp4_debug_offset);
106
107 return 0;
108}
109
110static ssize_t mdp4_debugfs_read(
111 struct file *file,
112 char __user *buff,
113 size_t count,
114 loff_t *ppos)
115{
116 int len = 0;
117 unsigned int data;
118
119 printk(KERN_INFO "%s: offset=%d count=%d *ppos=%d\n",
120 __func__, (int)mdp4_debug_offset, (int)count, (int)*ppos);
121
122 if (*ppos)
123 return 0; /* the end */
124
125 data = readl(mdp4_base_addr + mdp4_debug_offset);
126
127 len = snprintf(mdp4_debug_buf, 4, "%x\n", data);
128
129 if (len > 0) {
130 if (len > count)
131 len = count;
132 if (copy_to_user(buff, mdp4_debug_buf, len))
133 return -EFAULT;
134 }
135
136 printk(KERN_INFO "%s: len=%d\n", __func__, len);
137
138 if (len < 0)
139 return 0;
140
141 *ppos += len; /* increase offset */
142
143 return len;
144}
145
146static const struct file_operations mdp4_debugfs_fops = {
147 .open = mdp4_debugfs_open,
148 .release = mdp4_debugfs_release,
149 .read = mdp4_debugfs_read,
150 .write = mdp4_debugfs_write,
151};
152
153int mdp4_debugfs_init(void)
154{
155 struct dentry *dent = debugfs_create_dir("mdp4", NULL);
156
157 if (IS_ERR(dent)) {
158 printk(KERN_ERR "%s(%d): debugfs_create_dir fail, error %ld\n",
159 __FILE__, __LINE__, PTR_ERR(dent));
160 return -1;
161 }
162
163 if (debugfs_create_file("offset", 0644, dent, 0, &mdp4_offset_fops)
164 == NULL) {
165 printk(KERN_ERR "%s(%d): debugfs_create_file: offset fail\n",
166 __FILE__, __LINE__);
167 return -1;
168 }
169
170 if (debugfs_create_file("regs", 0644, dent, 0, &mdp4_debugfs_fops)
171 == NULL) {
172 printk(KERN_ERR "%s(%d): debugfs_create_file: regs fail\n",
173 __FILE__, __LINE__);
174 return -1;
175 }
176
177 mdp4_debug_offset = 0;
178 mdp4_base_addr = (ulong) msm_mdp_base; /* defined at msm_fb_def.h */
179
180 return 0;
181}
diff --git a/drivers/staging/msm/mdp4_overlay.c b/drivers/staging/msm/mdp4_overlay.c
new file mode 100644
index 000000000000..304bb8297635
--- /dev/null
+++ b/drivers/staging/msm/mdp4_overlay.c
@@ -0,0 +1,1259 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/sched.h>
21#include <linux/time.h>
22#include <linux/init.h>
23#include <linux/interrupt.h>
24#include <linux/spinlock.h>
25#include <linux/hrtimer.h>
26#include <linux/clk.h>
27#include <mach/hardware.h>
28#include <linux/io.h>
29#include <linux/debugfs.h>
30#include <linux/fb.h>
31#include <msm_mdp.h>
32#include <linux/file.h>
33#include "android_pmem.h"
34#include <linux/major.h>
35#include <asm/system.h>
36#include <asm/mach-types.h>
37#include <linux/semaphore.h>
38#include <linux/uaccess.h>
39#include <linux/mutex.h>
40
41#include "mdp.h"
42#include "msm_fb.h"
43#include "mdp4.h"
44
45
46struct mdp4_overlay_ctrl {
47 struct mdp4_overlay_pipe plist[MDP4_MAX_OVERLAY_PIPE];
48 struct mdp4_overlay_pipe *stage[MDP4_MAX_MIXER][MDP4_MAX_STAGE];
49} mdp4_overlay_db;
50
51static struct mdp4_overlay_ctrl *ctrl = &mdp4_overlay_db;
52
53
54void mdp4_overlay_dmap_cfg(struct msm_fb_data_type *mfd, int lcdc)
55{
56 uint32 dma2_cfg_reg;
57
58 dma2_cfg_reg = DMA_DITHER_EN;
59
60 if (mfd->fb_imgType == MDP_BGR_565)
61 dma2_cfg_reg |= DMA_PACK_PATTERN_BGR;
62 else
63 dma2_cfg_reg |= DMA_PACK_PATTERN_RGB;
64
65
66 if (mfd->panel_info.bpp == 18) {
67 dma2_cfg_reg |= DMA_DSTC0G_6BITS | /* 666 18BPP */
68 DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
69 } else if (mfd->panel_info.bpp == 16) {
70 dma2_cfg_reg |= DMA_DSTC0G_6BITS | /* 565 16BPP */
71 DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
72 } else {
73 dma2_cfg_reg |= DMA_DSTC0G_8BITS | /* 888 16BPP */
74 DMA_DSTC1B_8BITS | DMA_DSTC2R_8BITS;
75 }
76
77 if (lcdc)
78 dma2_cfg_reg |= DMA_PACK_ALIGN_MSB;
79
80 /* dma2 config register */
81 MDP_OUTP(MDP_BASE + 0x90000, dma2_cfg_reg);
82
83}
84
85void mdp4_overlay_dmap_xy(struct mdp4_overlay_pipe *pipe)
86{
87
88 /* dma_p source */
89 MDP_OUTP(MDP_BASE + 0x90004,
90 (pipe->src_height << 16 | pipe->src_width));
91 MDP_OUTP(MDP_BASE + 0x90008, pipe->srcp0_addr);
92 MDP_OUTP(MDP_BASE + 0x9000c, pipe->srcp0_ystride);
93
94 /* dma_p dest */
95 MDP_OUTP(MDP_BASE + 0x90010, (pipe->dst_y << 16 | pipe->dst_x));
96}
97
98#define MDP4_VG_PHASE_STEP_DEFAULT 0x20000000
99#define MDP4_VG_PHASE_STEP_SHIFT 29
100
101static int mdp4_leading_0(uint32 num)
102{
103 uint32 bit = 0x80000000;
104 int i;
105
106 for (i = 0; i < 32; i++) {
107 if (bit & num)
108 return i;
109 bit >>= 1;
110 }
111
112 return i;
113}
114
115static uint32 mdp4_scale_phase_step(int f_num, uint32 src, uint32 dst)
116{
117 uint32 val;
118 int n;
119
120 n = mdp4_leading_0(src);
121 if (n > f_num)
122 n = f_num;
123 val = src << n; /* maximum to reduce lose of resolution */
124 val /= dst;
125 if (n < f_num) {
126 n = f_num - n;
127 val <<= n;
128 }
129
130 return val;
131}
132
133static void mdp4_scale_setup(struct mdp4_overlay_pipe *pipe)
134{
135
136 pipe->phasex_step = MDP4_VG_PHASE_STEP_DEFAULT;
137 pipe->phasey_step = MDP4_VG_PHASE_STEP_DEFAULT;
138
139 if (pipe->dst_h && pipe->src_h != pipe->dst_h) {
140 if (pipe->dst_h >= pipe->src_h * 8) /* too much */
141 return;
142 pipe->op_mode |= MDP4_OP_SCALEY_EN;
143
144 if (pipe->pipe_type == OVERLAY_TYPE_VG) {
145 if (pipe->dst_h <= (pipe->src_h / 4))
146 pipe->op_mode |= MDP4_OP_SCALEY_MN_PHASE;
147 else
148 pipe->op_mode |= MDP4_OP_SCALEY_FIR;
149 }
150
151 pipe->phasey_step = mdp4_scale_phase_step(29,
152 pipe->src_h, pipe->dst_h);
153 }
154
155 if (pipe->dst_w && pipe->src_w != pipe->dst_w) {
156 if (pipe->dst_w >= pipe->src_w * 8) /* too much */
157 return;
158 pipe->op_mode |= MDP4_OP_SCALEX_EN;
159
160 if (pipe->pipe_type == OVERLAY_TYPE_VG) {
161 if (pipe->dst_w <= (pipe->src_w / 4))
162 pipe->op_mode |= MDP4_OP_SCALEY_MN_PHASE;
163 else
164 pipe->op_mode |= MDP4_OP_SCALEY_FIR;
165 }
166
167 pipe->phasex_step = mdp4_scale_phase_step(29,
168 pipe->src_w, pipe->dst_w);
169 }
170}
171
172void mdp4_overlay_rgb_setup(struct mdp4_overlay_pipe *pipe)
173{
174 char *rgb_base;
175 uint32 src_size, src_xy, dst_size, dst_xy;
176 uint32 format, pattern;
177
178 rgb_base = MDP_BASE + MDP4_RGB_BASE;
179 rgb_base += (MDP4_RGB_OFF * pipe->pipe_num);
180
181 src_size = ((pipe->src_h << 16) | pipe->src_w);
182 src_xy = ((pipe->src_y << 16) | pipe->src_x);
183 dst_size = ((pipe->dst_h << 16) | pipe->dst_w);
184 dst_xy = ((pipe->dst_y << 16) | pipe->dst_x);
185
186 format = mdp4_overlay_format(pipe);
187 pattern = mdp4_overlay_unpack_pattern(pipe);
188
189 pipe->op_mode |= MDP4_OP_IGC_LUT_EN;
190
191 mdp4_scale_setup(pipe);
192
193 outpdw(rgb_base + 0x0000, src_size); /* MDP_RGB_SRC_SIZE */
194 outpdw(rgb_base + 0x0004, src_xy); /* MDP_RGB_SRC_XY */
195 outpdw(rgb_base + 0x0008, dst_size); /* MDP_RGB_DST_SIZE */
196 outpdw(rgb_base + 0x000c, dst_xy); /* MDP_RGB_DST_XY */
197
198 outpdw(rgb_base + 0x0010, pipe->srcp0_addr);
199 outpdw(rgb_base + 0x0040, pipe->srcp0_ystride);
200
201 outpdw(rgb_base + 0x0050, format);/* MDP_RGB_SRC_FORMAT */
202 outpdw(rgb_base + 0x0054, pattern);/* MDP_RGB_SRC_UNPACK_PATTERN */
203 outpdw(rgb_base + 0x0058, pipe->op_mode);/* MDP_RGB_OP_MODE */
204 outpdw(rgb_base + 0x005c, pipe->phasex_step);
205 outpdw(rgb_base + 0x0060, pipe->phasey_step);
206
207 /* 16 bytes-burst x 3 req <= 48 bytes */
208 outpdw(rgb_base + 0x1004, 0xc2); /* MDP_RGB_FETCH_CFG */
209}
210
211void mdp4_overlay_vg_setup(struct mdp4_overlay_pipe *pipe)
212{
213 char *vg_base;
214 uint32 frame_size, src_size, src_xy, dst_size, dst_xy;
215 uint32 format, pattern;
216
217 vg_base = MDP_BASE + MDP4_VIDEO_BASE;
218 vg_base += (MDP4_VIDEO_OFF * pipe->pipe_num);
219
220 frame_size = ((pipe->src_height << 16) | pipe->src_width);
221 src_size = ((pipe->src_h << 16) | pipe->src_w);
222 src_xy = ((pipe->src_y << 16) | pipe->src_x);
223 dst_size = ((pipe->dst_h << 16) | pipe->dst_w);
224 dst_xy = ((pipe->dst_y << 16) | pipe->dst_x);
225
226 format = mdp4_overlay_format(pipe);
227 pattern = mdp4_overlay_unpack_pattern(pipe);
228
229 pipe->op_mode |= (MDP4_OP_CSC_EN | MDP4_OP_SRC_DATA_YCBCR |
230 MDP4_OP_IGC_LUT_EN);
231
232 mdp4_scale_setup(pipe);
233
234 outpdw(vg_base + 0x0000, src_size); /* MDP_RGB_SRC_SIZE */
235 outpdw(vg_base + 0x0004, src_xy); /* MDP_RGB_SRC_XY */
236 outpdw(vg_base + 0x0008, dst_size); /* MDP_RGB_DST_SIZE */
237 outpdw(vg_base + 0x000c, dst_xy); /* MDP_RGB_DST_XY */
238 outpdw(vg_base + 0x0048, frame_size); /* TILE frame size */
239
240 /* luma component plane */
241 outpdw(vg_base + 0x0010, pipe->srcp0_addr);
242
243 /* chroma component plane */
244 outpdw(vg_base + 0x0014, pipe->srcp1_addr);
245
246 outpdw(vg_base + 0x0040,
247 pipe->srcp1_ystride << 16 | pipe->srcp0_ystride);
248
249 outpdw(vg_base + 0x0050, format); /* MDP_RGB_SRC_FORMAT */
250 outpdw(vg_base + 0x0054, pattern); /* MDP_RGB_SRC_UNPACK_PATTERN */
251 outpdw(vg_base + 0x0058, pipe->op_mode);/* MDP_RGB_OP_MODE */
252 outpdw(vg_base + 0x005c, pipe->phasex_step);
253 outpdw(vg_base + 0x0060, pipe->phasey_step);
254
255 if (pipe->op_mode & MDP4_OP_DITHER_EN) {
256 outpdw(vg_base + 0x0068,
257 pipe->r_bit << 4 | pipe->b_bit << 2 | pipe->g_bit);
258 }
259
260 /* 16 bytes-burst x 3 req <= 48 bytes */
261 outpdw(vg_base + 0x1004, 0xc2); /* MDP_VG_FETCH_CFG */
262}
263
264int mdp4_overlay_format2type(uint32 format)
265{
266 switch (format) {
267 case MDP_RGB_565:
268 case MDP_RGB_888:
269 case MDP_BGR_565:
270 case MDP_ARGB_8888:
271 case MDP_RGBA_8888:
272 case MDP_BGRA_8888:
273 return OVERLAY_TYPE_RGB;
274 case MDP_YCRYCB_H2V1:
275 case MDP_Y_CRCB_H2V1:
276 case MDP_Y_CBCR_H2V1:
277 case MDP_Y_CRCB_H2V2:
278 case MDP_Y_CBCR_H2V2:
279 case MDP_Y_CBCR_H2V2_TILE:
280 case MDP_Y_CRCB_H2V2_TILE:
281 return OVERLAY_TYPE_VG;
282 default:
283 return -ERANGE;
284 }
285
286}
287
288#define C3_ALPHA 3 /* alpha */
289#define C2_R_Cr 2 /* R/Cr */
290#define C1_B_Cb 1 /* B/Cb */
291#define C0_G_Y 0 /* G/luma */
292
293int mdp4_overlay_format2pipe(struct mdp4_overlay_pipe *pipe)
294{
295 switch (pipe->src_format) {
296 case MDP_RGB_565:
297 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
298 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
299 pipe->a_bit = 0;
300 pipe->r_bit = 1; /* R, 5 bits */
301 pipe->b_bit = 1; /* B, 5 bits */
302 pipe->g_bit = 2; /* G, 6 bits */
303 pipe->alpha_enable = 0;
304 pipe->unpack_tight = 1;
305 pipe->unpack_align_msb = 0;
306 pipe->unpack_count = 2;
307 pipe->element2 = C2_R_Cr; /* R */
308 pipe->element1 = C0_G_Y; /* G */
309 pipe->element0 = C1_B_Cb; /* B */
310 pipe->bpp = 2; /* 2 bpp */
311 break;
312 case MDP_RGB_888:
313 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
314 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
315 pipe->a_bit = 0;
316 pipe->r_bit = 3; /* R, 8 bits */
317 pipe->b_bit = 3; /* B, 8 bits */
318 pipe->g_bit = 3; /* G, 8 bits */
319 pipe->alpha_enable = 0;
320 pipe->unpack_tight = 1;
321 pipe->unpack_align_msb = 0;
322 pipe->unpack_count = 2;
323 pipe->element2 = C2_R_Cr; /* R */
324 pipe->element1 = C0_G_Y; /* G */
325 pipe->element0 = C1_B_Cb; /* B */
326 pipe->bpp = 3; /* 3 bpp */
327 break;
328 case MDP_BGR_565:
329 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
330 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
331 pipe->a_bit = 0;
332 pipe->r_bit = 1; /* R, 5 bits */
333 pipe->b_bit = 1; /* B, 5 bits */
334 pipe->g_bit = 2; /* G, 6 bits */
335 pipe->alpha_enable = 0;
336 pipe->unpack_tight = 1;
337 pipe->unpack_align_msb = 0;
338 pipe->unpack_count = 2;
339 pipe->element2 = C1_B_Cb; /* B */
340 pipe->element1 = C0_G_Y; /* G */
341 pipe->element0 = C2_R_Cr; /* R */
342 pipe->bpp = 2; /* 2 bpp */
343 break;
344 case MDP_ARGB_8888:
345 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
346 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
347 pipe->a_bit = 3; /* alpha, 4 bits */
348 pipe->r_bit = 3; /* R, 8 bits */
349 pipe->b_bit = 3; /* B, 8 bits */
350 pipe->g_bit = 3; /* G, 8 bits */
351 pipe->alpha_enable = 1;
352 pipe->unpack_tight = 1;
353 pipe->unpack_align_msb = 0;
354 pipe->unpack_count = 3;
355 pipe->element3 = C3_ALPHA; /* alpha */
356 pipe->element2 = C2_R_Cr; /* R */
357 pipe->element1 = C0_G_Y; /* G */
358 pipe->element0 = C1_B_Cb; /* B */
359 pipe->bpp = 4; /* 4 bpp */
360 break;
361 case MDP_RGBA_8888:
362 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
363 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
364 pipe->a_bit = 3; /* alpha, 4 bits */
365 pipe->r_bit = 3; /* R, 8 bits */
366 pipe->b_bit = 3; /* B, 8 bits */
367 pipe->g_bit = 3; /* G, 8 bits */
368 pipe->alpha_enable = 1;
369 pipe->unpack_tight = 1;
370 pipe->unpack_align_msb = 0;
371 pipe->unpack_count = 3;
372 pipe->element3 = C2_R_Cr; /* R */
373 pipe->element2 = C0_G_Y; /* G */
374 pipe->element1 = C1_B_Cb; /* B */
375 pipe->element0 = C3_ALPHA; /* alpha */
376 pipe->bpp = 4; /* 4 bpp */
377 break;
378 case MDP_BGRA_8888:
379 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
380 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
381 pipe->a_bit = 3; /* alpha, 4 bits */
382 pipe->r_bit = 3; /* R, 8 bits */
383 pipe->b_bit = 3; /* B, 8 bits */
384 pipe->g_bit = 3; /* G, 8 bits */
385 pipe->alpha_enable = 1;
386 pipe->unpack_tight = 1;
387 pipe->unpack_align_msb = 0;
388 pipe->unpack_count = 3;
389 pipe->element3 = C1_B_Cb; /* B */
390 pipe->element2 = C0_G_Y; /* G */
391 pipe->element1 = C2_R_Cr; /* R */
392 pipe->element0 = C3_ALPHA; /* alpha */
393 pipe->bpp = 4; /* 4 bpp */
394 break;
395 case MDP_YCRYCB_H2V1:
396 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
397 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
398 pipe->a_bit = 0; /* alpha, 4 bits */
399 pipe->r_bit = 3; /* R, 8 bits */
400 pipe->b_bit = 3; /* B, 8 bits */
401 pipe->g_bit = 3; /* G, 8 bits */
402 pipe->alpha_enable = 0;
403 pipe->unpack_tight = 1;
404 pipe->unpack_align_msb = 0;
405 pipe->unpack_count = 3;
406 pipe->element3 = C0_G_Y; /* G */
407 pipe->element2 = C2_R_Cr; /* R */
408 pipe->element1 = C0_G_Y; /* G */
409 pipe->element0 = C1_B_Cb; /* B */
410 pipe->bpp = 2; /* 2 bpp */
411 pipe->chroma_sample = MDP4_CHROMA_H2V1;
412 break;
413 case MDP_Y_CRCB_H2V1:
414 case MDP_Y_CBCR_H2V1:
415 case MDP_Y_CRCB_H2V2:
416 case MDP_Y_CBCR_H2V2:
417 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
418 pipe->fetch_plane = OVERLAY_PLANE_PSEUDO_PLANAR;
419 pipe->a_bit = 0;
420 pipe->r_bit = 3; /* R, 8 bits */
421 pipe->b_bit = 3; /* B, 8 bits */
422 pipe->g_bit = 3; /* G, 8 bits */
423 pipe->alpha_enable = 0;
424 pipe->unpack_tight = 1;
425 pipe->unpack_align_msb = 0;
426 pipe->unpack_count = 1; /* 2 */
427 pipe->element3 = C0_G_Y; /* not used */
428 pipe->element2 = C0_G_Y; /* not used */
429 if (pipe->src_format == MDP_Y_CRCB_H2V1) {
430 pipe->element1 = C2_R_Cr; /* R */
431 pipe->element0 = C1_B_Cb; /* B */
432 pipe->chroma_sample = MDP4_CHROMA_H2V1;
433 } else if (pipe->src_format == MDP_Y_CBCR_H2V1) {
434 pipe->element1 = C1_B_Cb; /* B */
435 pipe->element0 = C2_R_Cr; /* R */
436 pipe->chroma_sample = MDP4_CHROMA_H2V1;
437 } else if (pipe->src_format == MDP_Y_CRCB_H2V2) {
438 pipe->element1 = C2_R_Cr; /* R */
439 pipe->element0 = C1_B_Cb; /* B */
440 pipe->chroma_sample = MDP4_CHROMA_420;
441 } else if (pipe->src_format == MDP_Y_CBCR_H2V2) {
442 pipe->element1 = C1_B_Cb; /* B */
443 pipe->element0 = C2_R_Cr; /* R */
444 pipe->chroma_sample = MDP4_CHROMA_420;
445 }
446 pipe->bpp = 2; /* 2 bpp */
447 break;
448 case MDP_Y_CBCR_H2V2_TILE:
449 case MDP_Y_CRCB_H2V2_TILE:
450 pipe->frame_format = MDP4_FRAME_FORMAT_VIDEO_SUPERTILE;
451 pipe->fetch_plane = OVERLAY_PLANE_PSEUDO_PLANAR;
452 pipe->a_bit = 0;
453 pipe->r_bit = 3; /* R, 8 bits */
454 pipe->b_bit = 3; /* B, 8 bits */
455 pipe->g_bit = 3; /* G, 8 bits */
456 pipe->alpha_enable = 0;
457 pipe->unpack_tight = 1;
458 pipe->unpack_align_msb = 0;
459 pipe->unpack_count = 1; /* 2 */
460 pipe->element3 = C0_G_Y; /* not used */
461 pipe->element2 = C0_G_Y; /* not used */
462 if (pipe->src_format == MDP_Y_CRCB_H2V2_TILE) {
463 pipe->element1 = C2_R_Cr; /* R */
464 pipe->element0 = C1_B_Cb; /* B */
465 pipe->chroma_sample = MDP4_CHROMA_420;
466 } else if (pipe->src_format == MDP_Y_CBCR_H2V2_TILE) {
467 pipe->element1 = C1_B_Cb; /* B */
468 pipe->element0 = C2_R_Cr; /* R */
469 pipe->chroma_sample = MDP4_CHROMA_420;
470 }
471 pipe->bpp = 2; /* 2 bpp */
472 break;
473 default:
474 /* not likely */
475 return -ERANGE;
476 }
477
478 return 0;
479}
480
481/*
482 * color_key_convert: output with 12 bits color key
483 */
484static uint32 color_key_convert(int start, int num, uint32 color)
485{
486
487 uint32 data;
488
489 data = (color >> start) & ((1 << num) - 1);
490
491 if (num == 5)
492 data = (data << 7) + (data << 2) + (data >> 3);
493 else if (num == 6)
494 data = (data << 6) + data;
495 else /* 8 bits */
496 data = (data << 4) + (data >> 4);
497
498 return data;
499
500}
501
502void transp_color_key(int format, uint32 transp,
503 uint32 *c0, uint32 *c1, uint32 *c2)
504{
505 int b_start, g_start, r_start;
506 int b_num, g_num, r_num;
507
508 switch (format) {
509 case MDP_RGB_565:
510 b_start = 0;
511 g_start = 5;
512 r_start = 11;
513 r_num = 5;
514 g_num = 6;
515 b_num = 5;
516 break;
517 case MDP_RGB_888:
518 case MDP_XRGB_8888:
519 case MDP_ARGB_8888:
520 b_start = 0;
521 g_start = 8;
522 r_start = 16;
523 r_num = 8;
524 g_num = 8;
525 b_num = 8;
526 break;
527 case MDP_BGR_565:
528 b_start = 11;
529 g_start = 5;
530 r_start = 0;
531 r_num = 5;
532 g_num = 6;
533 b_num = 5;
534 break;
535 case MDP_Y_CBCR_H2V2:
536 case MDP_Y_CBCR_H2V1:
537 b_start = 8;
538 g_start = 16;
539 r_start = 0;
540 r_num = 8;
541 g_num = 8;
542 b_num = 8;
543 break;
544 case MDP_Y_CRCB_H2V2:
545 case MDP_Y_CRCB_H2V1:
546 b_start = 0;
547 g_start = 16;
548 r_start = 8;
549 r_num = 8;
550 g_num = 8;
551 b_num = 8;
552 break;
553 default:
554 b_start = 0;
555 g_start = 8;
556 r_start = 16;
557 r_num = 8;
558 g_num = 8;
559 b_num = 8;
560 break;
561 }
562
563 *c0 = color_key_convert(g_start, g_num, transp);
564 *c1 = color_key_convert(b_start, b_num, transp);
565 *c2 = color_key_convert(r_start, r_num, transp);
566}
567
568uint32 mdp4_overlay_format(struct mdp4_overlay_pipe *pipe)
569{
570 uint32 format;
571
572 format = 0;
573
574 if (pipe->solid_fill)
575 format |= MDP4_FORMAT_SOLID_FILL;
576
577 if (pipe->unpack_align_msb)
578 format |= MDP4_FORMAT_UNPACK_ALIGN_MSB;
579
580 if (pipe->unpack_tight)
581 format |= MDP4_FORMAT_UNPACK_TIGHT;
582
583 if (pipe->alpha_enable)
584 format |= MDP4_FORMAT_ALPHA_ENABLE;
585
586 format |= (pipe->unpack_count << 13);
587 format |= ((pipe->bpp - 1) << 9);
588 format |= (pipe->a_bit << 6);
589 format |= (pipe->r_bit << 4);
590 format |= (pipe->b_bit << 2);
591 format |= pipe->g_bit;
592
593 format |= (pipe->frame_format << 29);
594
595 if (pipe->fetch_plane == OVERLAY_PLANE_PSEUDO_PLANAR) {
596 /* video/graphic */
597 format |= (pipe->fetch_plane << 19);
598 format |= (pipe->chroma_site << 28);
599 format |= (pipe->chroma_sample << 26);
600 }
601
602 return format;
603}
604
605uint32 mdp4_overlay_unpack_pattern(struct mdp4_overlay_pipe *pipe)
606{
607 return (pipe->element3 << 24) | (pipe->element2 << 16) |
608 (pipe->element1 << 8) | pipe->element0;
609}
610
611void mdp4_overlayproc_cfg(struct mdp4_overlay_pipe *pipe)
612{
613 uint32 data;
614 char *overlay_base;
615
616 if (pipe->mixer_num == MDP4_MIXER1)
617 overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
618 else
619 overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
620
621 /* MDP_OVERLAYPROC_CFG */
622 outpdw(overlay_base + 0x0004, 0x01); /* directout */
623 data = pipe->src_height;
624 data <<= 16;
625 data |= pipe->src_width;
626 outpdw(overlay_base + 0x0008, data); /* ROI, height + width */
627 outpdw(overlay_base + 0x000c, pipe->srcp0_addr);
628 outpdw(overlay_base + 0x0010, pipe->srcp0_ystride);
629 outpdw(overlay_base + 0x0014, 0x4); /* GC_LUT_EN, 888 */
630}
631
632int mdp4_overlay_active(int mixer)
633{
634 uint32 data, mask, i;
635 int p1, p2;
636
637 data = inpdw(MDP_BASE + 0x10100);
638 p1 = 0;
639 p2 = 0;
640 for (i = 0; i < 8; i++) {
641 mask = data & 0x0f;
642 if (mask) {
643 if (mask <= 4)
644 p1++;
645 else
646 p2++;
647 }
648 data >>= 4;
649 }
650
651 if (mixer)
652 return p2;
653 else
654 return p1;
655}
656
657void mdp4_mixer_stage_up(struct mdp4_overlay_pipe *pipe)
658{
659 uint32 data, mask, snum, stage, mixer;
660
661 stage = pipe->mixer_stage;
662 mixer = pipe->mixer_num;
663
664 /* MDP_LAYERMIXER_IN_CFG, shard by both mixer 0 and 1 */
665 data = inpdw(MDP_BASE + 0x10100);
666
667 if (mixer == MDP4_MIXER1)
668 stage += 8;
669
670 if (pipe->pipe_type == OVERLAY_TYPE_VG) {/* VG1 and VG2 */
671 snum = 0;
672 snum += (4 * pipe->pipe_num);
673 } else {
674 snum = 8;
675 snum += (4 * pipe->pipe_num); /* RGB1 and RGB2 */
676 }
677
678 mask = 0x0f;
679 mask <<= snum;
680 stage <<= snum;
681 data &= ~mask; /* clear old bits */
682
683 data |= stage;
684
685 outpdw(MDP_BASE + 0x10100, data); /* MDP_LAYERMIXER_IN_CFG */
686
687 data = inpdw(MDP_BASE + 0x10100);
688
689 ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = pipe; /* keep it */
690}
691
692void mdp4_mixer_stage_down(struct mdp4_overlay_pipe *pipe)
693{
694 uint32 data, mask, snum, stage, mixer;
695
696 stage = pipe->mixer_stage;
697 mixer = pipe->mixer_num;
698
699 if (pipe != ctrl->stage[mixer][stage]) /* not runing */
700 return;
701
702 /* MDP_LAYERMIXER_IN_CFG, shard by both mixer 0 and 1 */
703 data = inpdw(MDP_BASE + 0x10100);
704
705 if (mixer == MDP4_MIXER1)
706 stage += 8;
707
708 if (pipe->pipe_type == OVERLAY_TYPE_VG) {/* VG1 and VG2 */
709 snum = 0;
710 snum += (4 * pipe->pipe_num);
711 } else {
712 snum = 8;
713 snum += (4 * pipe->pipe_num); /* RGB1 and RGB2 */
714 }
715
716 mask = 0x0f;
717 mask <<= snum;
718 data &= ~mask; /* clear old bits */
719
720 outpdw(MDP_BASE + 0x10100, data); /* MDP_LAYERMIXER_IN_CFG */
721
722 data = inpdw(MDP_BASE + 0x10100);
723
724 ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = NULL; /* clear it */
725}
726
727void mdp4_mixer_blend_setup(struct mdp4_overlay_pipe *pipe)
728{
729 unsigned char *overlay_base;
730 uint32 c0, c1, c2, blend_op;
731 int off;
732
733 if (pipe->mixer_num) /* mixer number, /dev/fb0, /dev/fb1 */
734 overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
735 else
736 overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
737
738 /* stage 0 to stage 2 */
739 off = 0x20 * (pipe->mixer_stage - MDP4_MIXER_STAGE0);
740
741 blend_op = 0;
742 if (pipe->alpha_enable) /* ARGB */
743 blend_op = MDP4_BLEND_FG_ALPHA_FG_PIXEL |
744 MDP4_BLEND_BG_ALPHA_FG_PIXEL;
745 else
746 blend_op = (MDP4_BLEND_BG_ALPHA_BG_CONST |
747 MDP4_BLEND_FG_ALPHA_FG_CONST);
748
749
750 if (pipe->alpha_enable == 0) { /* not ARGB */
751 if (pipe->is_fg) {
752 outpdw(overlay_base + off + 0x108, pipe->alpha);
753 outpdw(overlay_base + off + 0x10c, 0xff - pipe->alpha);
754 } else {
755 outpdw(overlay_base + off + 0x108, 0xff - pipe->alpha);
756 outpdw(overlay_base + off + 0x10c, pipe->alpha);
757 }
758 }
759
760 if (pipe->transp != MDP_TRANSP_NOP) {
761 transp_color_key(pipe->src_format, pipe->transp, &c0, &c1, &c2);
762 if (pipe->is_fg) {
763 blend_op |= MDP4_BLEND_FG_TRANSP_EN; /* Fg blocked */
764 /* lower limit */
765 if (c0 > 0x10)
766 c0 -= 0x10;
767 if (c1 > 0x10)
768 c1 -= 0x10;
769 if (c2 > 0x10)
770 c2 -= 0x10;
771 outpdw(overlay_base + off + 0x110,
772 (c1 << 16 | c0));/* low */
773 outpdw(overlay_base + off + 0x114, c2);/* low */
774 /* upper limit */
775 if ((c0 + 0x20) < 0x0fff)
776 c0 += 0x20;
777 else
778 c0 = 0x0fff;
779 if ((c1 + 0x20) < 0x0fff)
780 c1 += 0x20;
781 else
782 c1 = 0x0fff;
783 if ((c2 + 0x20) < 0x0fff)
784 c2 += 0x20;
785 else
786 c2 = 0x0fff;
787 outpdw(overlay_base + off + 0x118,
788 (c1 << 16 | c0));/* high */
789 outpdw(overlay_base + off + 0x11c, c2);/* high */
790 } else {
791 blend_op |= MDP4_BLEND_BG_TRANSP_EN; /* bg blocked */
792 /* lower limit */
793 if (c0 > 0x10)
794 c0 -= 0x10;
795 if (c1 > 0x10)
796 c1 -= 0x10;
797 if (c2 > 0x10)
798 c2 -= 0x10;
799 outpdw(overlay_base + 0x180,
800 (c1 << 16 | c0));/* low */
801 outpdw(overlay_base + 0x184, c2);/* low */
802 /* upper limit */
803 if ((c0 + 0x20) < 0x0fff)
804 c0 += 0x20;
805 else
806 c0 = 0x0fff;
807 if ((c1 + 0x20) < 0x0fff)
808 c1 += 0x20;
809 else
810 c1 = 0x0fff;
811 if ((c2 + 0x20) < 0x0fff)
812 c2 += 0x20;
813 else
814 c2 = 0x0fff;
815 outpdw(overlay_base + 0x188,
816 (c1 << 16 | c0));/* high */
817 outpdw(overlay_base + 0x18c, c2);/* high */
818 }
819 }
820 outpdw(overlay_base + off + 0x104, blend_op);
821}
822
823void mdp4_overlay_reg_flush(struct mdp4_overlay_pipe *pipe, int all)
824{
825 uint32 bits = 0;
826
827 if (pipe->mixer_num == MDP4_MIXER1)
828 bits |= 0x02;
829 else
830 bits |= 0x01;
831
832 if (all) {
833 if (pipe->pipe_type == OVERLAY_TYPE_RGB) {
834 if (pipe->pipe_num == OVERLAY_PIPE_RGB2)
835 bits |= 0x20;
836 else
837 bits |= 0x10;
838 } else {
839 if (pipe->pipe_num == OVERLAY_PIPE_VG2)
840 bits |= 0x08;
841 else
842 bits |= 0x04;
843 }
844 }
845
846 outpdw(MDP_BASE + 0x18000, bits); /* MDP_OVERLAY_REG_FLUSH */
847
848 while (inpdw(MDP_BASE + 0x18000) & bits) /* self clear when complete */
849 ;
850}
851
852struct mdp4_overlay_pipe *mdp4_overlay_ndx2pipe(int ndx)
853{
854 struct mdp4_overlay_pipe *pipe;
855
856 if (ndx == 0 || ndx >= MDP4_MAX_OVERLAY_PIPE)
857 return NULL;
858
859 pipe = &ctrl->plist[ndx - 1]; /* ndx start from 1 */
860
861 if (pipe->pipe_ndx == 0)
862 return NULL;
863
864 return pipe;
865}
866
867struct mdp4_overlay_pipe *mdp4_overlay_pipe_alloc(void)
868{
869 int i;
870 struct mdp4_overlay_pipe *pipe;
871
872 pipe = &ctrl->plist[0];
873 for (i = 0; i < MDP4_MAX_OVERLAY_PIPE; i++) {
874 if (pipe->pipe_ndx == 0) {
875 pipe->pipe_ndx = i + 1; /* start from 1 */
876 init_completion(&pipe->comp);
877 printk(KERN_INFO "mdp4_overlay_pipe_alloc: pipe=%x ndx=%d\n",
878 (int)pipe, pipe->pipe_ndx);
879 return pipe;
880 }
881 pipe++;
882 }
883
884 return NULL;
885}
886
887
888void mdp4_overlay_pipe_free(struct mdp4_overlay_pipe *pipe)
889{
890 printk(KERN_INFO "mdp4_overlay_pipe_free: pipe=%x ndx=%d\n",
891 (int)pipe, pipe->pipe_ndx);
892 memset(pipe, 0, sizeof(*pipe));
893}
894
895static int get_pipe_num(int ptype, int stage)
896{
897 if (ptype == OVERLAY_TYPE_RGB) {
898 if (stage == MDP4_MIXER_STAGE_BASE)
899 return OVERLAY_PIPE_RGB1;
900 else
901 return OVERLAY_PIPE_RGB2;
902 } else {
903 if (stage == MDP4_MIXER_STAGE0)
904 return OVERLAY_PIPE_VG1;
905 else
906 return OVERLAY_PIPE_VG2;
907 }
908}
909
910int mdp4_overlay_req_check(uint32 id, uint32 z_order, uint32 mixer)
911{
912 struct mdp4_overlay_pipe *pipe;
913
914 pipe = ctrl->stage[mixer][z_order];
915
916 if (pipe == NULL)
917 return 0;
918
919 if (pipe->pipe_ndx == id) /* same req, recycle */
920 return 0;
921
922 return -EPERM;
923}
924
925static int mdp4_overlay_req2pipe(struct mdp_overlay *req, int mixer,
926 struct mdp4_overlay_pipe **ppipe)
927{
928 struct mdp4_overlay_pipe *pipe;
929 int ret, ptype;
930
931 if (mixer >= MDP4_MAX_MIXER) {
932 printk(KERN_ERR "mpd_overlay_req2pipe: mixer out of range!\n");
933 return -ERANGE;
934 }
935
936 if (req->z_order < 0 || req->z_order > 2) {
937 printk(KERN_ERR "mpd_overlay_req2pipe: z_order=%d out of range!\n",
938 req->z_order);
939 return -ERANGE;
940 }
941
942 if (req->src_rect.h == 0 || req->src_rect.w == 0) {
943 printk(KERN_ERR "mpd_overlay_req2pipe: src img of zero size!\n");
944 return -EINVAL;
945 }
946
947 ret = mdp4_overlay_req_check(req->id, req->z_order, mixer);
948 if (ret < 0)
949 return ret;
950
951 ptype = mdp4_overlay_format2type(req->src.format);
952 if (ptype < 0)
953 return ptype;
954
955 if (req->id == MSMFB_NEW_REQUEST) /* new request */
956 pipe = mdp4_overlay_pipe_alloc();
957 else
958 pipe = mdp4_overlay_ndx2pipe(req->id);
959
960 if (pipe == NULL)
961 return -ENOMEM;
962
963 pipe->src_format = req->src.format;
964 ret = mdp4_overlay_format2pipe(pipe);
965
966 if (ret < 0)
967 return ret;
968
969 /*
970 * base layer == 1, reserved for frame buffer
971 * zorder 0 == stage 0 == 2
972 * zorder 1 == stage 1 == 3
973 * zorder 2 == stage 2 == 4
974 */
975 if (req->id == MSMFB_NEW_REQUEST) { /* new request */
976 pipe->mixer_stage = req->z_order + MDP4_MIXER_STAGE0;
977 pipe->pipe_type = ptype;
978 pipe->pipe_num = get_pipe_num(ptype, pipe->mixer_stage);
979 printk(KERN_INFO "mpd4_overlay_req2pipe: zorder=%d pipe_num=%d\n",
980 req->z_order, pipe->pipe_num);
981 }
982
983 pipe->src_width = req->src.width & 0x07ff; /* source img width */
984 pipe->src_height = req->src.height & 0x07ff; /* source img height */
985 pipe->src_h = req->src_rect.h & 0x07ff;
986 pipe->src_w = req->src_rect.w & 0x07ff;
987 pipe->src_y = req->src_rect.y & 0x07ff;
988 pipe->src_x = req->src_rect.x & 0x07ff;
989 pipe->dst_h = req->dst_rect.h & 0x07ff;
990 pipe->dst_w = req->dst_rect.w & 0x07ff;
991 pipe->dst_y = req->dst_rect.y & 0x07ff;
992 pipe->dst_x = req->dst_rect.x & 0x07ff;
993
994 if (req->flags & MDP_FLIP_LR)
995 pipe->op_mode |= MDP4_OP_FLIP_LR;
996
997 if (req->flags & MDP_FLIP_UD)
998 pipe->op_mode |= MDP4_OP_FLIP_UD;
999
1000 if (req->flags & MDP_DITHER)
1001 pipe->op_mode |= MDP4_OP_DITHER_EN;
1002
1003 if (req->flags & MDP_DEINTERLACE)
1004 pipe->op_mode |= MDP4_OP_DEINT_ODD_REF;
1005
1006 pipe->is_fg = req->is_fg;/* control alpha and color key */
1007
1008 pipe->alpha = req->alpha & 0x0ff;
1009
1010 pipe->transp = req->transp_mask;
1011
1012 *ppipe = pipe;
1013
1014 return 0;
1015}
1016
1017int get_img(struct msmfb_data *img, struct fb_info *info,
1018 unsigned long *start, unsigned long *len, struct file **pp_file)
1019{
1020 int put_needed, ret = 0;
1021 struct file *file;
1022#ifdef CONFIG_ANDROID_PMEM
1023 unsigned long vstart;
1024#endif
1025
1026#ifdef CONFIG_ANDROID_PMEM
1027 if (!get_pmem_file(img->memory_id, start, &vstart, len, pp_file))
1028 return 0;
1029#endif
1030 file = fget_light(img->memory_id, &put_needed);
1031 if (file == NULL)
1032 return -1;
1033
1034 if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
1035 *start = info->fix.smem_start;
1036 *len = info->fix.smem_len;
1037 *pp_file = file;
1038 } else {
1039 ret = -1;
1040 fput_light(file, put_needed);
1041 }
1042 return ret;
1043}
1044int mdp4_overlay_get(struct fb_info *info, struct mdp_overlay *req)
1045{
1046 struct mdp4_overlay_pipe *pipe;
1047
1048 pipe = mdp4_overlay_ndx2pipe(req->id);
1049 if (pipe == NULL)
1050 return -ENODEV;
1051
1052 *req = pipe->req_data;
1053
1054 return 0;
1055}
1056
1057int mdp4_overlay_set(struct fb_info *info, struct mdp_overlay *req)
1058{
1059 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
1060 int ret, mixer;
1061 struct mdp4_overlay_pipe *pipe;
1062 int lcdc;
1063
1064 if (mfd == NULL)
1065 return -ENODEV;
1066
1067 if (req->src.format == MDP_FB_FORMAT)
1068 req->src.format = mfd->fb_imgType;
1069
1070 if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
1071 return -EINTR;
1072
1073 mixer = info->node; /* minor number of char device */
1074
1075 ret = mdp4_overlay_req2pipe(req, mixer, &pipe);
1076 if (ret < 0) {
1077 mutex_unlock(&mfd->dma->ov_mutex);
1078 return ret;
1079 }
1080
1081 lcdc = inpdw(MDP_BASE + 0xc0000);
1082
1083 if (lcdc == 0) { /* mddi */
1084 /* MDP cmd block enable */
1085 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
1086 }
1087
1088 /* return id back to user */
1089 req->id = pipe->pipe_ndx; /* pipe_ndx start from 1 */
1090 pipe->req_data = *req; /* keep original req */
1091
1092 mutex_unlock(&mfd->dma->ov_mutex);
1093
1094 return 0;
1095}
1096
1097int mdp4_overlay_unset(struct fb_info *info, int ndx)
1098{
1099 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
1100 struct mdp4_overlay_pipe *pipe;
1101 int lcdc;
1102
1103 if (mfd == NULL)
1104 return -ENODEV;
1105
1106 if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
1107 return -EINTR;
1108
1109 pipe = mdp4_overlay_ndx2pipe(ndx);
1110
1111 if (pipe == NULL) {
1112 mutex_unlock(&mfd->dma->ov_mutex);
1113 return -ENODEV;
1114 }
1115
1116 lcdc = inpdw(MDP_BASE + 0xc0000);
1117
1118 mdp4_mixer_stage_down(pipe);
1119
1120 if (lcdc == 0) { /* mddi */
1121 /* MDP cmd block disable */
1122 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
1123 }
1124
1125 if (lcdc) /* LCDC mode */
1126 mdp4_overlay_reg_flush(pipe, 0);
1127
1128 mdp4_overlay_pipe_free(pipe);
1129
1130 if (lcdc == 0) { /* mddi */
1131 mdp4_mddi_overlay_restore();
1132 }
1133
1134 mutex_unlock(&mfd->dma->ov_mutex);
1135
1136 return 0;
1137}
1138
1139struct tile_desc {
1140 uint32 width; /* tile's width */
1141 uint32 height; /* tile's height */
1142 uint32 row_tile_w; /* tiles per row's width */
1143 uint32 row_tile_h; /* tiles per row's height */
1144};
1145
1146void tile_samsung(struct tile_desc *tp)
1147{
1148 /*
1149 * each row of samsung tile consists of two tiles in height
1150 * and two tiles in width which means width should align to
1151 * 64 x 2 bytes and height should align to 32 x 2 bytes.
1152 * video decoder generate two tiles in width and one tile
1153 * in height which ends up height align to 32 X 1 bytes.
1154 */
1155 tp->width = 64; /* 64 bytes */
1156 tp->row_tile_w = 2; /* 2 tiles per row's width */
1157 tp->height = 32; /* 32 bytes */
1158 tp->row_tile_h = 1; /* 1 tiles per row's height */
1159}
1160
1161uint32 tile_mem_size(struct mdp4_overlay_pipe *pipe, struct tile_desc *tp)
1162{
1163 uint32 tile_w, tile_h;
1164 uint32 row_num_w, row_num_h;
1165
1166
1167 tile_w = tp->width * tp->row_tile_w;
1168 tile_h = tp->height * tp->row_tile_h;
1169
1170 row_num_w = (pipe->src_width + tile_w - 1) / tile_w;
1171 row_num_h = (pipe->src_height + tile_h - 1) / tile_h;
1172
1173 return row_num_w * row_num_h * tile_w * tile_h;
1174}
1175
1176int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req,
1177 struct file **pp_src_file)
1178{
1179 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
1180 struct msmfb_data *img;
1181 struct mdp4_overlay_pipe *pipe;
1182 ulong start, addr;
1183 ulong len = 0;
1184 struct file *p_src_file = 0;
1185 int lcdc;
1186
1187 if (mfd == NULL)
1188 return -ENODEV;
1189
1190 pipe = mdp4_overlay_ndx2pipe(req->id);
1191 if (pipe == NULL)
1192 return -ENODEV;
1193
1194 if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
1195 return -EINTR;
1196
1197 img = &req->data;
1198 get_img(img, info, &start, &len, &p_src_file);
1199 if (len == 0) {
1200 mutex_unlock(&mfd->dma->ov_mutex);
1201 printk(KERN_ERR "mdp_overlay_play: could not retrieve"
1202 " image from memory\n");
1203 return -1;
1204 }
1205 *pp_src_file = p_src_file;
1206
1207 addr = start + img->offset;
1208 pipe->srcp0_addr = addr;
1209 pipe->srcp0_ystride = pipe->src_width * pipe->bpp;
1210
1211 if (pipe->fetch_plane == OVERLAY_PLANE_PSEUDO_PLANAR) {
1212 if (pipe->frame_format == MDP4_FRAME_FORMAT_VIDEO_SUPERTILE) {
1213 struct tile_desc tile;
1214
1215 tile_samsung(&tile);
1216 pipe->srcp1_addr = addr + tile_mem_size(pipe, &tile);
1217 } else
1218 pipe->srcp1_addr = addr +
1219 pipe->src_width * pipe->src_height;
1220
1221 pipe->srcp0_ystride = pipe->src_width;
1222 pipe->srcp1_ystride = pipe->src_width;
1223 }
1224
1225 lcdc = inpdw(MDP_BASE + 0xc0000);
1226 lcdc &= 0x01; /* LCDC mode */
1227
1228 if (pipe->pipe_type == OVERLAY_TYPE_VG)
1229 mdp4_overlay_vg_setup(pipe); /* video/graphic pipe */
1230 else
1231 mdp4_overlay_rgb_setup(pipe); /* rgb pipe */
1232
1233 mdp4_mixer_blend_setup(pipe);
1234 mdp4_mixer_stage_up(pipe);
1235
1236 if (lcdc) { /* LCDC mode */
1237 mdp4_overlay_reg_flush(pipe, 1);
1238 }
1239
1240 if (lcdc) { /* LCDC mode */
1241 if (pipe->mixer_stage != MDP4_MIXER_STAGE_BASE) { /* done */
1242 mutex_unlock(&mfd->dma->ov_mutex);
1243 return 0;
1244 }
1245 }
1246
1247 if (lcdc == 0) { /* MDDI mode */
1248#ifdef MDP4_NONBLOCKING
1249 if (mfd->panel_power_on)
1250#else
1251 if (!mfd->dma->busy && mfd->panel_power_on)
1252#endif
1253 mdp4_mddi_overlay_kickoff(mfd, pipe);
1254 }
1255
1256 mutex_unlock(&mfd->dma->ov_mutex);
1257
1258 return 0;
1259}
diff --git a/drivers/staging/msm/mdp4_overlay_lcdc.c b/drivers/staging/msm/mdp4_overlay_lcdc.c
new file mode 100644
index 000000000000..a6ab8ec83f55
--- /dev/null
+++ b/drivers/staging/msm/mdp4_overlay_lcdc.c
@@ -0,0 +1,313 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/sched.h>
21#include <linux/time.h>
22#include <linux/init.h>
23#include <linux/interrupt.h>
24#include <linux/hrtimer.h>
25#include <linux/delay.h>
26#include <mach/hardware.h>
27#include <linux/io.h>
28
29#include <asm/system.h>
30#include <asm/mach-types.h>
31#include <linux/semaphore.h>
32#include <linux/spinlock.h>
33
34#include <linux/fb.h>
35
36#include "mdp.h"
37#include "msm_fb.h"
38#include "mdp4.h"
39
40#ifdef CONFIG_FB_MSM_MDP40
41#define LCDC_BASE 0xC0000
42#else
43#define LCDC_BASE 0xE0000
44#endif
45
46int first_pixel_start_x;
47int first_pixel_start_y;
48
49static struct mdp4_overlay_pipe *lcdc_pipe;
50
51int mdp_lcdc_on(struct platform_device *pdev)
52{
53 int lcdc_width;
54 int lcdc_height;
55 int lcdc_bpp;
56 int lcdc_border_clr;
57 int lcdc_underflow_clr;
58 int lcdc_hsync_skew;
59
60 int hsync_period;
61 int hsync_ctrl;
62 int vsync_period;
63 int display_hctl;
64 int display_v_start;
65 int display_v_end;
66 int active_hctl;
67 int active_h_start;
68 int active_h_end;
69 int active_v_start;
70 int active_v_end;
71 int ctrl_polarity;
72 int h_back_porch;
73 int h_front_porch;
74 int v_back_porch;
75 int v_front_porch;
76 int hsync_pulse_width;
77 int vsync_pulse_width;
78 int hsync_polarity;
79 int vsync_polarity;
80 int data_en_polarity;
81 int hsync_start_x;
82 int hsync_end_x;
83 uint8 *buf;
84 int bpp, ptype;
85 uint32 format;
86 struct fb_info *fbi;
87 struct fb_var_screeninfo *var;
88 struct msm_fb_data_type *mfd;
89 struct mdp4_overlay_pipe *pipe;
90 int ret;
91
92 mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
93
94 if (!mfd)
95 return -ENODEV;
96
97 if (mfd->key != MFD_KEY)
98 return -EINVAL;
99
100 fbi = mfd->fbi;
101 var = &fbi->var;
102
103 /* MDP cmd block enable */
104 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
105
106 bpp = fbi->var.bits_per_pixel / 8;
107 buf = (uint8 *) fbi->fix.smem_start;
108 buf += fbi->var.xoffset * bpp +
109 fbi->var.yoffset * fbi->fix.line_length;
110
111 if (bpp == 2)
112 format = MDP_RGB_565;
113 else if (bpp == 3)
114 format = MDP_RGB_888;
115 else
116 format = MDP_ARGB_8888;
117
118
119 if (lcdc_pipe == NULL) {
120 ptype = mdp4_overlay_format2type(format);
121 pipe = mdp4_overlay_pipe_alloc();
122 pipe->pipe_type = ptype;
123 /* use RGB1 pipe */
124 pipe->pipe_num = OVERLAY_PIPE_RGB1;
125 pipe->mixer_stage = MDP4_MIXER_STAGE_BASE;
126 pipe->mixer_num = MDP4_MIXER0;
127 pipe->src_format = format;
128 mdp4_overlay_format2pipe(pipe);
129
130 lcdc_pipe = pipe; /* keep it */
131 } else {
132 pipe = lcdc_pipe;
133 }
134
135 pipe->src_height = fbi->var.yres;
136 pipe->src_width = fbi->var.xres;
137 pipe->src_h = fbi->var.yres;
138 pipe->src_w = fbi->var.xres;
139 pipe->src_y = 0;
140 pipe->src_x = 0;
141 pipe->srcp0_addr = (uint32) buf;
142 pipe->srcp0_ystride = fbi->fix.line_length;
143
144 mdp4_overlay_dmap_xy(pipe);
145 mdp4_overlay_dmap_cfg(mfd, 1);
146
147 mdp4_overlay_rgb_setup(pipe);
148
149 mdp4_mixer_stage_up(pipe);
150
151 mdp4_overlayproc_cfg(pipe);
152
153 /*
154 * LCDC timing setting
155 */
156 h_back_porch = var->left_margin;
157 h_front_porch = var->right_margin;
158 v_back_porch = var->upper_margin;
159 v_front_porch = var->lower_margin;
160 hsync_pulse_width = var->hsync_len;
161 vsync_pulse_width = var->vsync_len;
162 lcdc_border_clr = mfd->panel_info.lcdc.border_clr;
163 lcdc_underflow_clr = mfd->panel_info.lcdc.underflow_clr;
164 lcdc_hsync_skew = mfd->panel_info.lcdc.hsync_skew;
165
166 lcdc_width = mfd->panel_info.xres;
167 lcdc_height = mfd->panel_info.yres;
168 lcdc_bpp = mfd->panel_info.bpp;
169
170 hsync_period =
171 hsync_pulse_width + h_back_porch + lcdc_width + h_front_porch;
172 hsync_ctrl = (hsync_period << 16) | hsync_pulse_width;
173 hsync_start_x = hsync_pulse_width + h_back_porch;
174 hsync_end_x = hsync_period - h_front_porch - 1;
175 display_hctl = (hsync_end_x << 16) | hsync_start_x;
176
177 vsync_period =
178 (vsync_pulse_width + v_back_porch + lcdc_height +
179 v_front_porch) * hsync_period;
180 display_v_start =
181 (vsync_pulse_width + v_back_porch) * hsync_period + lcdc_hsync_skew;
182 display_v_end =
183 vsync_period - (v_front_porch * hsync_period) + lcdc_hsync_skew - 1;
184
185 if (lcdc_width != var->xres) {
186 active_h_start = hsync_start_x + first_pixel_start_x;
187 active_h_end = active_h_start + var->xres - 1;
188 active_hctl =
189 ACTIVE_START_X_EN | (active_h_end << 16) | active_h_start;
190 } else {
191 active_hctl = 0;
192 }
193
194 if (lcdc_height != var->yres) {
195 active_v_start =
196 display_v_start + first_pixel_start_y * hsync_period;
197 active_v_end = active_v_start + (var->yres) * hsync_period - 1;
198 active_v_start |= ACTIVE_START_Y_EN;
199 } else {
200 active_v_start = 0;
201 active_v_end = 0;
202 }
203
204
205#ifdef CONFIG_FB_MSM_MDP40
206 hsync_polarity = 1;
207 vsync_polarity = 1;
208 lcdc_underflow_clr |= 0x80000000; /* enable recovery */
209#else
210 hsync_polarity = 0;
211 vsync_polarity = 0;
212#endif
213 data_en_polarity = 0;
214
215 ctrl_polarity =
216 (data_en_polarity << 2) | (vsync_polarity << 1) | (hsync_polarity);
217
218 MDP_OUTP(MDP_BASE + LCDC_BASE + 0x4, hsync_ctrl);
219 MDP_OUTP(MDP_BASE + LCDC_BASE + 0x8, vsync_period);
220 MDP_OUTP(MDP_BASE + LCDC_BASE + 0xc, vsync_pulse_width * hsync_period);
221 MDP_OUTP(MDP_BASE + LCDC_BASE + 0x10, display_hctl);
222 MDP_OUTP(MDP_BASE + LCDC_BASE + 0x14, display_v_start);
223 MDP_OUTP(MDP_BASE + LCDC_BASE + 0x18, display_v_end);
224 MDP_OUTP(MDP_BASE + LCDC_BASE + 0x28, lcdc_border_clr);
225 MDP_OUTP(MDP_BASE + LCDC_BASE + 0x2c, lcdc_underflow_clr);
226 MDP_OUTP(MDP_BASE + LCDC_BASE + 0x30, lcdc_hsync_skew);
227 MDP_OUTP(MDP_BASE + LCDC_BASE + 0x38, ctrl_polarity);
228 MDP_OUTP(MDP_BASE + LCDC_BASE + 0x1c, active_hctl);
229 MDP_OUTP(MDP_BASE + LCDC_BASE + 0x20, active_v_start);
230 MDP_OUTP(MDP_BASE + LCDC_BASE + 0x24, active_v_end);
231
232 ret = panel_next_on(pdev);
233 if (ret == 0) {
234 /* enable LCDC block */
235 MDP_OUTP(MDP_BASE + LCDC_BASE, 1);
236 mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
237 }
238 /* MDP cmd block disable */
239 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
240
241 return ret;
242}
243
244int mdp_lcdc_off(struct platform_device *pdev)
245{
246 int ret = 0;
247 struct mdp4_overlay_pipe *pipe;
248
249 /* MDP cmd block enable */
250 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
251 MDP_OUTP(MDP_BASE + LCDC_BASE, 0);
252 /* MDP cmd block disable */
253 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
254 mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
255
256 ret = panel_next_off(pdev);
257
258 /* delay to make sure the last frame finishes */
259 mdelay(100);
260
261 /* dis-engage rgb0 from mixer */
262 pipe = lcdc_pipe;
263 mdp4_mixer_stage_down(pipe);
264
265 return ret;
266}
267
268/*
269 * mdp4_overlay0_done_lcdc: called from isr
270 */
271void mdp4_overlay0_done_lcdc()
272{
273 complete(&lcdc_pipe->comp);
274}
275
276void mdp4_lcdc_overlay(struct msm_fb_data_type *mfd)
277{
278 struct fb_info *fbi = mfd->fbi;
279 uint8 *buf;
280 int bpp;
281 unsigned long flag;
282 struct mdp4_overlay_pipe *pipe;
283
284 if (!mfd->panel_power_on)
285 return;
286
287 /* no need to power on cmd block since it's lcdc mode */
288 bpp = fbi->var.bits_per_pixel / 8;
289 buf = (uint8 *) fbi->fix.smem_start;
290 buf += fbi->var.xoffset * bpp +
291 fbi->var.yoffset * fbi->fix.line_length;
292
293 mutex_lock(&mfd->dma->ov_mutex);
294
295 pipe = lcdc_pipe;
296 pipe->srcp0_addr = (uint32) buf;
297 mdp4_overlay_rgb_setup(pipe);
298 mdp4_overlay_reg_flush(pipe, 1); /* rgb1 and mixer0 */
299
300 /* enable irq */
301 spin_lock_irqsave(&mdp_spin_lock, flag);
302 mdp_enable_irq(MDP_OVERLAY0_TERM);
303 INIT_COMPLETION(lcdc_pipe->comp);
304 mfd->dma->waiting = TRUE;
305 outp32(MDP_INTR_CLEAR, INTR_OVERLAY0_DONE);
306 mdp_intr_mask |= INTR_OVERLAY0_DONE;
307 outp32(MDP_INTR_ENABLE, mdp_intr_mask);
308 spin_unlock_irqrestore(&mdp_spin_lock, flag);
309 wait_for_completion_killable(&lcdc_pipe->comp);
310 mdp_disable_irq(MDP_OVERLAY0_TERM);
311
312 mutex_unlock(&mfd->dma->ov_mutex);
313}
diff --git a/drivers/staging/msm/mdp4_overlay_mddi.c b/drivers/staging/msm/mdp4_overlay_mddi.c
new file mode 100644
index 000000000000..be1b2874185b
--- /dev/null
+++ b/drivers/staging/msm/mdp4_overlay_mddi.c
@@ -0,0 +1,254 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/sched.h>
21#include <linux/time.h>
22#include <linux/init.h>
23#include <linux/interrupt.h>
24#include <linux/hrtimer.h>
25#include <linux/delay.h>
26#include <mach/hardware.h>
27#include <linux/io.h>
28
29#include <asm/system.h>
30#include <asm/mach-types.h>
31#include <linux/semaphore.h>
32#include <linux/spinlock.h>
33
34#include <linux/fb.h>
35
36#include "mdp.h"
37#include "msm_fb.h"
38#include "mdp4.h"
39
40static struct mdp4_overlay_pipe *mddi_pipe;
41static struct mdp4_overlay_pipe *pending_pipe;
42static struct msm_fb_data_type *mddi_mfd;
43
44#define WHOLESCREEN
45
46void mdp4_overlay_update_lcd(struct msm_fb_data_type *mfd)
47{
48 MDPIBUF *iBuf = &mfd->ibuf;
49 uint8 *src;
50 int bpp, ptype;
51 uint32 format;
52 uint32 mddi_ld_param;
53 uint16 mddi_vdo_packet_reg;
54 struct mdp4_overlay_pipe *pipe;
55
56 if (mfd->key != MFD_KEY)
57 return;
58
59 mddi_mfd = mfd; /* keep it */
60
61 bpp = iBuf->bpp;
62
63 if (bpp == 2)
64 format = MDP_RGB_565;
65 else if (bpp == 3)
66 format = MDP_RGB_888;
67 else
68 format = MDP_ARGB_8888;
69
70 /* MDP cmd block enable */
71 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
72
73 if (mddi_pipe == NULL) {
74 ptype = mdp4_overlay_format2type(format);
75 pipe = mdp4_overlay_pipe_alloc();
76 pipe->pipe_type = ptype;
77 /* use RGB1 pipe */
78 pipe->pipe_num = OVERLAY_PIPE_RGB1;
79 pipe->mixer_num = MDP4_MIXER0;
80 pipe->src_format = format;
81 mdp4_overlay_format2pipe(pipe);
82
83 mddi_pipe = pipe; /* keep it */
84
85 mddi_ld_param = 0;
86 mddi_vdo_packet_reg = mfd->panel_info.mddi.vdopkt;
87
88 if (mfd->panel_info.type == MDDI_PANEL) {
89 if (mfd->panel_info.pdest == DISPLAY_1)
90 mddi_ld_param = 0;
91 else
92 mddi_ld_param = 1;
93 } else {
94 mddi_ld_param = 2;
95 }
96
97 MDP_OUTP(MDP_BASE + 0x00090, mddi_ld_param);
98 MDP_OUTP(MDP_BASE + 0x00094,
99 (MDDI_VDO_PACKET_DESC << 16) | mddi_vdo_packet_reg);
100 } else {
101 pipe = mddi_pipe;
102 }
103
104
105 src = (uint8 *) iBuf->buf;
106
107#ifdef WHOLESCREEN
108 {
109 struct fb_info *fbi;
110
111 fbi = mfd->fbi;
112 pipe->src_height = fbi->var.yres;
113 pipe->src_width = fbi->var.xres;
114 pipe->src_h = fbi->var.yres;
115 pipe->src_w = fbi->var.xres;
116 pipe->src_y = 0;
117 pipe->src_x = 0;
118 pipe->dst_h = fbi->var.yres;
119 pipe->dst_w = fbi->var.xres;
120 pipe->dst_y = 0;
121 pipe->dst_x = 0;
122 pipe->srcp0_addr = (uint32)src;
123 pipe->srcp0_ystride = fbi->var.xres_virtual * bpp;
124 }
125
126#else
127 if (mdp4_overlay_active(MDP4_MIXER0)) {
128 struct fb_info *fbi;
129
130 fbi = mfd->fbi;
131 pipe->src_height = fbi->var.yres;
132 pipe->src_width = fbi->var.xres;
133 pipe->src_h = fbi->var.yres;
134 pipe->src_w = fbi->var.xres;
135 pipe->src_y = 0;
136 pipe->src_x = 0;
137 pipe->dst_h = fbi->var.yres;
138 pipe->dst_w = fbi->var.xres;
139 pipe->dst_y = 0;
140 pipe->dst_x = 0;
141 pipe->srcp0_addr = (uint32) src;
142 pipe->srcp0_ystride = fbi->var.xres_virtual * bpp;
143 } else {
144 /* starting input address */
145 src += (iBuf->dma_x + iBuf->dma_y * iBuf->ibuf_width) * bpp;
146
147 pipe->src_height = iBuf->dma_h;
148 pipe->src_width = iBuf->dma_w;
149 pipe->src_h = iBuf->dma_h;
150 pipe->src_w = iBuf->dma_w;
151 pipe->src_y = 0;
152 pipe->src_x = 0;
153 pipe->dst_h = iBuf->dma_h;
154 pipe->dst_w = iBuf->dma_w;
155 pipe->dst_y = iBuf->dma_y;
156 pipe->dst_x = iBuf->dma_x;
157 pipe->srcp0_addr = (uint32) src;
158 pipe->srcp0_ystride = iBuf->ibuf_width * bpp;
159 }
160#endif
161
162 pipe->mixer_stage = MDP4_MIXER_STAGE_BASE;
163
164 mdp4_overlay_rgb_setup(pipe);
165
166 mdp4_mixer_stage_up(pipe);
167
168 mdp4_overlayproc_cfg(pipe);
169
170 mdp4_overlay_dmap_xy(pipe);
171
172 mdp4_overlay_dmap_cfg(mfd, 0);
173
174 /* MDP cmd block disable */
175 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
176
177}
178
179/*
180 * mdp4_overlay0_done_mddi: called from isr
181 */
182void mdp4_overlay0_done_mddi()
183{
184 if (pending_pipe)
185 complete(&pending_pipe->comp);
186}
187
188void mdp4_mddi_overlay_restore(void)
189{
190 /* mutex holded by caller */
191 mdp4_overlay_update_lcd(mddi_mfd);
192 mdp4_mddi_overlay_kickoff(mddi_mfd, mddi_pipe);
193}
194
195void mdp4_mddi_overlay_kickoff(struct msm_fb_data_type *mfd,
196 struct mdp4_overlay_pipe *pipe)
197{
198#ifdef MDP4_NONBLOCKING
199 unsigned long flag;
200
201 spin_lock_irqsave(&mdp_spin_lock, flag);
202 if (mfd->dma->busy == TRUE) {
203 INIT_COMPLETION(pipe->comp);
204 pending_pipe = pipe;
205 }
206 spin_unlock_irqrestore(&mdp_spin_lock, flag);
207
208 if (pending_pipe != NULL) {
209 /* wait until DMA finishes the current job */
210 wait_for_completion_killable(&pipe->comp);
211 pending_pipe = NULL;
212 }
213 down(&mfd->sem);
214 mdp_enable_irq(MDP_OVERLAY0_TERM);
215 mfd->dma->busy = TRUE;
216 /* start OVERLAY pipe */
217 mdp_pipe_kickoff(MDP_OVERLAY0_TERM, mfd);
218 up(&mfd->sem);
219#else
220 down(&mfd->sem);
221 mdp_enable_irq(MDP_OVERLAY0_TERM);
222 mfd->dma->busy = TRUE;
223 INIT_COMPLETION(pipe->comp);
224 pending_pipe = pipe;
225
226 /* start OVERLAY pipe */
227 mdp_pipe_kickoff(MDP_OVERLAY0_TERM, mfd);
228 up(&mfd->sem);
229
230 /* wait until DMA finishes the current job */
231 wait_for_completion_killable(&pipe->comp);
232 mdp_disable_irq(MDP_OVERLAY0_TERM);
233#endif
234
235}
236
237void mdp4_mddi_overlay(struct msm_fb_data_type *mfd)
238{
239 mutex_lock(&mfd->dma->ov_mutex);
240
241 if ((mfd) && (!mfd->dma->busy) && (mfd->panel_power_on)) {
242 mdp4_overlay_update_lcd(mfd);
243
244 mdp4_mddi_overlay_kickoff(mfd, mddi_pipe);
245
246 /* signal if pan function is waiting for the update completion */
247 if (mfd->pan_waiting) {
248 mfd->pan_waiting = FALSE;
249 complete(&mfd->pan_comp);
250 }
251 }
252
253 mutex_unlock(&mfd->dma->ov_mutex);
254}
diff --git a/drivers/staging/msm/mdp4_util.c b/drivers/staging/msm/mdp4_util.c
new file mode 100644
index 000000000000..fd97f5205992
--- /dev/null
+++ b/drivers/staging/msm/mdp4_util.c
@@ -0,0 +1,1686 @@
1
2/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 * 02110-1301, USA.
17 */
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/sched.h>
21#include <linux/time.h>
22#include <linux/init.h>
23#include <linux/interrupt.h>
24#include <linux/spinlock.h>
25#include <linux/hrtimer.h>
26#include <linux/clk.h>
27#include <mach/hardware.h>
28#include <linux/io.h>
29#include <linux/debugfs.h>
30
31#include <asm/system.h>
32#include <asm/mach-types.h>
33#include <linux/semaphore.h>
34#include <linux/uaccess.h>
35
36#include "mdp.h"
37#include "msm_fb.h"
38#include "mdp4.h"
39
40void mdp4_sw_reset(ulong bits)
41{
42 bits &= 0x1f; /* 5 bits */
43 outpdw(MDP_BASE + 0x001c, bits); /* MDP_SW_RESET */
44
45 while (inpdw(MDP_BASE + 0x001c) & bits) /* self clear when complete */
46 ;
47 MSM_FB_INFO("mdp4_sw_reset: 0x%x\n", (int)bits);
48}
49
50void mdp4_overlay_cfg(int overlayer, int blt_mode, int refresh, int direct_out)
51{
52 ulong bits = 0;
53
54 if (blt_mode)
55 bits |= (1 << 3);
56 refresh &= 0x03; /* 2 bites */
57 bits |= (refresh << 1);
58 direct_out &= 0x01;
59 bits |= direct_out;
60
61 if (overlayer == MDP4_MIXER0)
62 outpdw(MDP_BASE + 0x10004, bits); /* MDP_OVERLAY0_CFG */
63 else
64 outpdw(MDP_BASE + 0x18004, bits); /* MDP_OVERLAY1_CFG */
65
66 MSM_FB_INFO("mdp4_overlay_cfg: 0x%x\n", (int)inpdw(MDP_BASE + 0x10004));
67}
68
69void mdp4_display_intf_sel(int output, ulong intf)
70{
71 ulong bits, mask;
72
73 bits = inpdw(MDP_BASE + 0x0038); /* MDP_DISP_INTF_SEL */
74
75 mask = 0x03; /* 2 bits */
76 intf &= 0x03; /* 2 bits */
77
78 switch (output) {
79 case EXTERNAL_INTF_SEL:
80 intf <<= 4;
81 mask <<= 4;
82 break;
83 case SECONDARY_INTF_SEL:
84 intf &= 0x02; /* only MDDI and EBI2 support */
85 intf <<= 2;
86 mask <<= 2;
87 break;
88 default:
89 break;
90 }
91
92
93 bits &= ~mask;
94 bits |= intf;
95
96 outpdw(MDP_BASE + 0x0038, bits); /* MDP_DISP_INTF_SEL */
97
98 MSM_FB_INFO("mdp4_display_intf_sel: 0x%x\n", (int)inpdw(MDP_BASE + 0x0038));
99}
100
101unsigned long mdp4_display_status(void)
102{
103 return inpdw(MDP_BASE + 0x0018) & 0x3ff; /* MDP_DISPLAY_STATUS */
104}
105
106void mdp4_ebi2_lcd_setup(int lcd, ulong base, int ystride)
107{
108 /* always use memory map */
109 ystride &= 0x01fff; /* 13 bits */
110 if (lcd == EBI2_LCD0) {
111 outpdw(MDP_BASE + 0x0060, base);/* MDP_EBI2_LCD0 */
112 outpdw(MDP_BASE + 0x0068, ystride);/* MDP_EBI2_LCD0_YSTRIDE */
113 } else {
114 outpdw(MDP_BASE + 0x0064, base);/* MDP_EBI2_LCD1 */
115 outpdw(MDP_BASE + 0x006c, ystride);/* MDP_EBI2_LCD1_YSTRIDE */
116 }
117}
118
119void mdp4_mddi_setup(int mddi, unsigned long id)
120{
121 ulong bits;
122
123 if (mddi == MDDI_EXTERNAL_SET)
124 bits = 0x02;
125 else if (mddi == MDDI_SECONDARY_SET)
126 bits = 0x01;
127 else
128 bits = 0; /* PRIMARY_SET */
129
130 id <<= 16;
131
132 bits |= id;
133
134 outpdw(MDP_BASE + 0x0090, bits); /* MDP_MDDI_PARAM_WR_SEL */
135}
136
137int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req,
138 struct file **pp_src_file, struct file **pp_dst_file)
139{
140
141 /* not implemented yet */
142 return -1;
143}
144
145void mdp4_hw_init(void)
146{
147 ulong bits;
148
149 /* MDP cmd block enable */
150 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
151
152#ifdef MDP4_ERROR
153 /*
154 * Issue software reset on DMA_P will casue DMA_P dma engine stall
155 * on LCDC mode. However DMA_P does not stall at MDDI mode.
156 * This need further investigation.
157 */
158 mdp4_sw_reset(0x17);
159#endif
160
161 mdp4_clear_lcdc();
162
163 mdp4_mixer_blend_init(0);
164 mdp4_mixer_blend_init(1);
165 mdp4_vg_qseed_init(0);
166 mdp4_vg_qseed_init(1);
167 mdp4_vg_csc_mv_setup(0);
168 mdp4_vg_csc_mv_setup(1);
169 mdp4_vg_csc_pre_bv_setup(0);
170 mdp4_vg_csc_pre_bv_setup(1);
171 mdp4_vg_csc_post_bv_setup(0);
172 mdp4_vg_csc_post_bv_setup(1);
173 mdp4_vg_csc_pre_lv_setup(0);
174 mdp4_vg_csc_pre_lv_setup(1);
175 mdp4_vg_csc_post_lv_setup(0);
176 mdp4_vg_csc_post_lv_setup(1);
177
178 mdp4_mixer_gc_lut_setup(0);
179 mdp4_mixer_gc_lut_setup(1);
180
181 mdp4_vg_igc_lut_setup(0);
182 mdp4_vg_igc_lut_setup(1);
183
184 mdp4_rgb_igc_lut_setup(0);
185 mdp4_rgb_igc_lut_setup(1);
186
187 outp32(MDP_EBI2_PORTMAP_MODE, 0x3);
188
189 /* system interrupts */
190
191 bits = mdp_intr_mask;
192 outpdw(MDP_BASE + 0x0050, bits);/* enable specififed interrupts */
193
194 /* histogram */
195 MDP_OUTP(MDP_BASE + 0x95010, 1); /* auto clear HIST */
196
197 /* enable histogram interrupts */
198 outpdw(MDP_BASE + 0x9501c, INTR_HIST_DONE);
199
200 /* For the max read pending cmd config below, if the MDP clock */
201 /* is less than the AXI clock, then we must use 3 pending */
202 /* pending requests. Otherwise, we should use 8 pending requests. */
203 /* In the future we should do this detection automatically. */
204
205 /* max read pending cmd config */
206 outpdw(MDP_BASE + 0x004c, 0x02222); /* 3 pending requests */
207
208 /* dma_p fetch config */
209 outpdw(MDP_BASE + 0x91004, 0x27); /* burst size of 8 */
210
211#ifndef CONFIG_FB_MSM_OVERLAY
212 /* both REFRESH_MODE and DIRECT_OUT are ignored at BLT mode */
213 mdp4_overlay_cfg(MDP4_MIXER0, OVERLAY_MODE_BLT, 0, 0);
214 mdp4_overlay_cfg(MDP4_MIXER1, OVERLAY_MODE_BLT, 0, 0);
215#endif
216
217 /* MDP cmd block disable */
218 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
219}
220
221
222void mdp4_clear_lcdc(void)
223{
224 uint32 bits;
225
226 bits = inpdw(MDP_BASE + 0xc0000);
227 if (bits & 0x01) /* enabled already */
228 return;
229
230 outpdw(MDP_BASE + 0xc0004, 0); /* vsync ctrl out */
231 outpdw(MDP_BASE + 0xc0008, 0); /* vsync period */
232 outpdw(MDP_BASE + 0xc000c, 0); /* vsync pusle width */
233 outpdw(MDP_BASE + 0xc0010, 0); /* lcdc display HCTL */
234 outpdw(MDP_BASE + 0xc0014, 0); /* lcdc display v start */
235 outpdw(MDP_BASE + 0xc0018, 0); /* lcdc display v end */
236 outpdw(MDP_BASE + 0xc001c, 0); /* lcdc active hctl */
237 outpdw(MDP_BASE + 0xc0020, 0); /* lcdc active v start */
238 outpdw(MDP_BASE + 0xc0024, 0); /* lcdc active v end */
239 outpdw(MDP_BASE + 0xc0028, 0); /* lcdc board color */
240 outpdw(MDP_BASE + 0xc002c, 0); /* lcdc underflow ctrl */
241 outpdw(MDP_BASE + 0xc0030, 0); /* lcdc hsync skew */
242 outpdw(MDP_BASE + 0xc0034, 0); /* lcdc test ctl */
243 outpdw(MDP_BASE + 0xc0038, 0); /* lcdc ctl polarity */
244}
245
246static struct mdp_dma_data overlay1_data;
247static int intr_dma_p;
248static int intr_dma_s;
249static int intr_dma_e;
250static int intr_overlay0;
251static int intr_overlay1;
252
253irqreturn_t mdp4_isr(int irq, void *ptr)
254{
255 uint32 isr, mask, lcdc;
256 struct mdp_dma_data *dma;
257
258 mdp_is_in_isr = TRUE;
259
260 while (1) {
261 isr = inpdw(MDP_INTR_STATUS);
262 if (isr == 0)
263 break;
264
265 mask = inpdw(MDP_INTR_ENABLE);
266 outpdw(MDP_INTR_CLEAR, isr);
267
268 isr &= mask;
269
270 if (unlikely(isr == 0))
271 break;
272
273 if (isr & INTR_DMA_P_DONE) {
274 intr_dma_p++;
275 lcdc = inpdw(MDP_BASE + 0xc0000);
276 dma = &dma2_data;
277 if (lcdc & 0x01) { /* LCDC enable */
278 /* disable LCDC interrupt */
279 mdp_intr_mask &= ~INTR_DMA_P_DONE;
280 outp32(MDP_INTR_ENABLE, mdp_intr_mask);
281 dma->waiting = FALSE;
282 } else {
283 dma->busy = FALSE;
284 mdp_pipe_ctrl(MDP_DMA2_BLOCK,
285 MDP_BLOCK_POWER_OFF, TRUE);
286 }
287 complete(&dma->comp);
288 }
289 if (isr & INTR_DMA_S_DONE) {
290 intr_dma_s++;
291 dma = &dma_s_data;
292 dma->busy = FALSE;
293 mdp_pipe_ctrl(MDP_DMA_S_BLOCK,
294 MDP_BLOCK_POWER_OFF, TRUE);
295 complete(&dma->comp);
296 }
297 if (isr & INTR_DMA_E_DONE) {
298 intr_dma_e++;
299 dma = &dma_e_data;
300 mdp_intr_mask &= ~INTR_DMA_E_DONE;
301 outp32(MDP_INTR_ENABLE, mdp_intr_mask);
302 dma->busy = FALSE;
303
304 if (dma->waiting) {
305 dma->waiting = FALSE;
306 complete(&dma->comp);
307 }
308 }
309 if (isr & INTR_OVERLAY0_DONE) {
310 intr_overlay0++;
311 lcdc = inpdw(MDP_BASE + 0xc0000);
312 dma = &dma2_data;
313 if (lcdc & 0x01) { /* LCDC enable */
314 /* disable LCDC interrupt */
315 mdp_intr_mask &= ~INTR_OVERLAY0_DONE;
316 outp32(MDP_INTR_ENABLE, mdp_intr_mask);
317 dma->waiting = FALSE;
318 mdp4_overlay0_done_lcdc();
319 } else { /* MDDI */
320 dma->busy = FALSE;
321#ifdef MDP4_NONBLOCKING
322 mdp_disable_irq_nolock(MDP_OVERLAY0_TERM);
323#endif
324 mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK,
325 MDP_BLOCK_POWER_OFF, TRUE);
326 mdp4_overlay0_done_mddi();
327 }
328 }
329 if (isr & INTR_OVERLAY1_DONE) {
330 intr_overlay1++;
331 dma = &overlay1_data;
332 dma->busy = FALSE;
333 mdp_pipe_ctrl(MDP_OVERLAY1_BLOCK,
334 MDP_BLOCK_POWER_OFF, TRUE);
335 complete(&dma->comp);
336 }
337 if (isr & INTR_DMA_P_HISTOGRAM) {
338 isr = inpdw(MDP_DMA_P_HIST_INTR_STATUS);
339 mask = inpdw(MDP_DMA_P_HIST_INTR_ENABLE);
340 outpdw(MDP_DMA_P_HIST_INTR_CLEAR, isr);
341 isr &= mask;
342 if (isr & INTR_HIST_DONE) {
343 if (mdp_hist.r)
344 memcpy(mdp_hist.r, MDP_BASE + 0x95100,
345 mdp_hist.bin_cnt*4);
346 if (mdp_hist.g)
347 memcpy(mdp_hist.g, MDP_BASE + 0x95200,
348 mdp_hist.bin_cnt*4);
349 if (mdp_hist.b)
350 memcpy(mdp_hist.b, MDP_BASE + 0x95300,
351 mdp_hist.bin_cnt*4);
352 complete(&mdp_hist_comp);
353 }
354 }
355 }
356
357 mdp_is_in_isr = FALSE;
358
359 return IRQ_HANDLED;
360}
361
362
363/*
364 * QSEED tables
365 */
366
367static uint32 vg_qseed_table0[] = {
368 0x5556aaff, 0x00000000, 0x00000000, 0x00000000
369};
370
371static uint32 vg_qseed_table1[] = {
372 0x76543210, 0xfedcba98
373};
374
375static uint32 vg_qseed_table2[] = {
376 0x02000000, 0x00000000, 0x02060ff2, 0x00000008,
377 0x02090fe4, 0x00000013, 0x020a0fd9, 0x0ffc0021,
378 0x02080fce, 0x0ffa0030, 0x02030fc5, 0x0ff60042,
379 0x01fd0fbe, 0x0ff10054, 0x01f50fb6, 0x0fed0068,
380 0x01e90fb1, 0x0fe60080, 0x01dc0fae, 0x0fe10095,
381 0x01ca0fae, 0x0fda00ae, 0x01b70fad, 0x0fd600c6,
382 0x01a40fad, 0x0fcf00e0, 0x018f0faf, 0x0fc800fa,
383 0x01780fb1, 0x0fc30114, 0x015f0fb5, 0x0fbf012d,
384 0x01490fb7, 0x0fb70149, 0x012d0fbf, 0x0fb5015f,
385 0x01140fc3, 0x0fb10178, 0x00fa0fc8, 0x0faf018f,
386 0x00e00fcf, 0x0fad01a4, 0x00c60fd6, 0x0fad01b7,
387 0x00ae0fda, 0x0fae01ca, 0x00950fe1, 0x0fae01dc,
388 0x00800fe6, 0x0fb101e9, 0x00680fed, 0x0fb601f5,
389 0x00540ff1, 0x0fbe01fd, 0x00420ff6, 0x0fc50203,
390 0x00300ffa, 0x0fce0208, 0x00210ffc, 0x0fd9020a,
391 0x00130000, 0x0fe40209, 0x00080000, 0x0ff20206,
392 0x02000000, 0x00000000, 0x02040ff2, 0x0000000a,
393 0x02040fe4, 0x00000018, 0x02010fda, 0x0ffc0029,
394 0x01fc0fcf, 0x0ffa003b, 0x01f30fc7, 0x0ff60050,
395 0x01e90fc0, 0x0ff20065, 0x01dc0fba, 0x0fee007c,
396 0x01cc0fb6, 0x0fe80096, 0x01ba0fb4, 0x0fe400ae,
397 0x01a70fb4, 0x0fdd00c8, 0x018f0fb5, 0x0fda00e2,
398 0x017a0fb5, 0x0fd400fd, 0x01630fb8, 0x0fce0117,
399 0x014c0fba, 0x0fca0130, 0x01320fbf, 0x0fc70148,
400 0x011b0fc1, 0x0fc10163, 0x01010fc8, 0x0fc00177,
401 0x00e90fcd, 0x0fbd018d, 0x00d10fd1, 0x0fbc01a2,
402 0x00ba0fd7, 0x0fbb01b4, 0x00a30fdd, 0x0fbc01c4,
403 0x008e0fe1, 0x0fbd01d4, 0x00790fe7, 0x0fbe01e2,
404 0x00670feb, 0x0fc001ee, 0x00540ff1, 0x0fc501f6,
405 0x00430ff4, 0x0fcb01fe, 0x00340ff8, 0x0fd10203,
406 0x00260ffb, 0x0fd80207, 0x001a0ffd, 0x0fe10208,
407 0x000f0000, 0x0fea0207, 0x00060000, 0x0ff50205,
408 0x02000000, 0x00000000, 0x02020ff2, 0x0000000c,
409 0x02000fe4, 0x0000001c, 0x01fa0fda, 0x0ffc0030,
410 0x01f10fd0, 0x0ffa0045, 0x01e50fc8, 0x0ff6005d,
411 0x01d60fc3, 0x0ff30074, 0x01c60fbd, 0x0fef008e,
412 0x01b30fba, 0x0fe900aa, 0x019e0fb9, 0x0fe500c4,
413 0x01870fba, 0x0fe000df, 0x016f0fbb, 0x0fdd00f9,
414 0x01580fbc, 0x0fd80114, 0x01400fbf, 0x0fd3012e,
415 0x01280fc2, 0x0fd00146, 0x010f0fc6, 0x0fce015d,
416 0x00f90fc9, 0x0fc90175, 0x00e00fcf, 0x0fc90188,
417 0x00ca0fd4, 0x0fc6019c, 0x00b40fd8, 0x0fc601ae,
418 0x009f0fdd, 0x0fc501bf, 0x008b0fe3, 0x0fc601cc,
419 0x00780fe6, 0x0fc701db, 0x00660feb, 0x0fc801e7,
420 0x00560fef, 0x0fcb01f0, 0x00460ff3, 0x0fcf01f8,
421 0x00380ff6, 0x0fd401fe, 0x002c0ff9, 0x0fd90202,
422 0x00200ffc, 0x0fdf0205, 0x00160ffe, 0x0fe60206,
423 0x000c0000, 0x0fed0207, 0x00050000, 0x0ff70204,
424 0x02000000, 0x00000000, 0x01fe0ff3, 0x0000000f,
425 0x01f60fe5, 0x00000025, 0x01ea0fdb, 0x0ffd003e,
426 0x01db0fd2, 0x0ffb0058, 0x01c80fcc, 0x0ff70075,
427 0x01b50fc7, 0x0ff40090, 0x01a00fc3, 0x0ff000ad,
428 0x01880fc1, 0x0feb00cc, 0x01700fc1, 0x0fe800e7,
429 0x01550fc3, 0x0fe40104, 0x013b0fc5, 0x0fe2011e,
430 0x01240fc6, 0x0fde0138, 0x010c0fca, 0x0fda0150,
431 0x00f40fcd, 0x0fd90166, 0x00dd0fd1, 0x0fd7017b,
432 0x00c80fd4, 0x0fd40190, 0x00b20fd9, 0x0fd401a1,
433 0x009f0fdd, 0x0fd301b1, 0x008c0fe1, 0x0fd301c0,
434 0x007b0fe5, 0x0fd301cd, 0x006a0fea, 0x0fd401d8,
435 0x005c0fec, 0x0fd501e3, 0x004d0ff0, 0x0fd601ed,
436 0x00410ff3, 0x0fd801f4, 0x00340ff7, 0x0fdb01fa,
437 0x002a0ff9, 0x0fdf01fe, 0x00200ffb, 0x0fe30202,
438 0x00180ffd, 0x0fe70204, 0x00100ffe, 0x0fed0205,
439 0x00090000, 0x0ff20205, 0x00040000, 0x0ff90203,
440 0x02000000, 0x00000000, 0x02050ff5, 0x00000006,
441 0x02070fea, 0x0000000f, 0x02080fe1, 0x0ffd001a,
442 0x02070fd8, 0x0ffb0026, 0x02030fd1, 0x0ff80034,
443 0x01fe0fcb, 0x0ff40043, 0x01f60fc5, 0x0ff10054,
444 0x01ee0fc0, 0x0feb0067, 0x01e20fbe, 0x0fe70079,
445 0x01d40fbd, 0x0fe1008e, 0x01c40fbc, 0x0fdd00a3,
446 0x01b40fbb, 0x0fd700ba, 0x01a20fbc, 0x0fd100d1,
447 0x018d0fbd, 0x0fcd00e9, 0x01770fc0, 0x0fc80101,
448 0x01630fc1, 0x0fc1011b, 0x01480fc7, 0x0fbf0132,
449 0x01300fca, 0x0fba014c, 0x01170fce, 0x0fb80163,
450 0x00fd0fd4, 0x0fb5017a, 0x00e20fda, 0x0fb5018f,
451 0x00c80fdd, 0x0fb401a7, 0x00ae0fe4, 0x0fb401ba,
452 0x00960fe8, 0x0fb601cc, 0x007c0fee, 0x0fba01dc,
453 0x00650ff2, 0x0fc001e9, 0x00500ff6, 0x0fc701f3,
454 0x003b0ffa, 0x0fcf01fc, 0x00290ffc, 0x0fda0201,
455 0x00180000, 0x0fe40204, 0x000a0000, 0x0ff20204,
456 0x02000000, 0x00000000, 0x02030ff5, 0x00000008,
457 0x02030fea, 0x00000013, 0x02020fe1, 0x0ffd0020,
458 0x01fc0fd9, 0x0ffc002f, 0x01f60fd2, 0x0ff80040,
459 0x01ed0fcd, 0x0ff50051, 0x01e30fc7, 0x0ff10065,
460 0x01d70fc3, 0x0fec007a, 0x01c60fc2, 0x0fe9008f,
461 0x01b60fc1, 0x0fe300a6, 0x01a20fc1, 0x0fe000bd,
462 0x018f0fc1, 0x0fdb00d5, 0x017b0fc2, 0x0fd500ee,
463 0x01640fc4, 0x0fd20106, 0x014d0fc8, 0x0fce011d,
464 0x01370fc9, 0x0fc90137, 0x011d0fce, 0x0fc8014d,
465 0x01060fd2, 0x0fc40164, 0x00ee0fd5, 0x0fc2017b,
466 0x00d50fdb, 0x0fc1018f, 0x00bd0fe0, 0x0fc101a2,
467 0x00a60fe3, 0x0fc101b6, 0x008f0fe9, 0x0fc201c6,
468 0x007a0fec, 0x0fc301d7, 0x00650ff1, 0x0fc701e3,
469 0x00510ff5, 0x0fcd01ed, 0x00400ff8, 0x0fd201f6,
470 0x002f0ffc, 0x0fd901fc, 0x00200ffd, 0x0fe10202,
471 0x00130000, 0x0fea0203, 0x00080000, 0x0ff50203,
472 0x02000000, 0x00000000, 0x02020ff5, 0x00000009,
473 0x01ff0fea, 0x00000017, 0x01fb0fe2, 0x0ffd0026,
474 0x01f30fda, 0x0ffc0037, 0x01ea0fd3, 0x0ff8004b,
475 0x01df0fce, 0x0ff5005e, 0x01d10fc9, 0x0ff20074,
476 0x01c10fc6, 0x0fed008c, 0x01ae0fc5, 0x0fea00a3,
477 0x019b0fc5, 0x0fe500bb, 0x01850fc6, 0x0fe200d3,
478 0x01700fc6, 0x0fde00ec, 0x015a0fc8, 0x0fd90105,
479 0x01430fca, 0x0fd6011d, 0x012b0fcd, 0x0fd30135,
480 0x01150fcf, 0x0fcf014d, 0x00fc0fd4, 0x0fce0162,
481 0x00e50fd8, 0x0fcc0177, 0x00cf0fdb, 0x0fca018c,
482 0x00b80fe0, 0x0fc9019f, 0x00a20fe5, 0x0fca01af,
483 0x008e0fe8, 0x0fcb01bf, 0x00790fec, 0x0fcb01d0,
484 0x00670fef, 0x0fcd01dd, 0x00550ff4, 0x0fd001e7,
485 0x00440ff7, 0x0fd501f0, 0x00350ffa, 0x0fda01f7,
486 0x00270ffc, 0x0fdf01fe, 0x001b0ffe, 0x0fe70200,
487 0x00100000, 0x0fee0202, 0x00060000, 0x0ff70203,
488 0x02000000, 0x00000000, 0x01ff0ff5, 0x0000000c,
489 0x01f80fea, 0x0000001e, 0x01ef0fe2, 0x0ffd0032,
490 0x01e20fdb, 0x0ffc0047, 0x01d30fd5, 0x0ff9005f,
491 0x01c20fd1, 0x0ff60077, 0x01b00fcd, 0x0ff30090,
492 0x019b0fcb, 0x0fef00ab, 0x01850fcb, 0x0fec00c4,
493 0x016e0fcc, 0x0fe800de, 0x01550fcd, 0x0fe600f8,
494 0x013f0fce, 0x0fe20111, 0x01280fd0, 0x0fdf0129,
495 0x01110fd2, 0x0fdd0140, 0x00f90fd6, 0x0fdb0156,
496 0x00e40fd8, 0x0fd8016c, 0x00cd0fdd, 0x0fd8017e,
497 0x00b80fe0, 0x0fd60192, 0x00a40fe3, 0x0fd601a3,
498 0x00910fe7, 0x0fd501b3, 0x007f0feb, 0x0fd601c0,
499 0x006e0fed, 0x0fd701ce, 0x005d0ff1, 0x0fd701db,
500 0x004f0ff3, 0x0fd901e5, 0x00400ff7, 0x0fdc01ed,
501 0x00330ff9, 0x0fe001f4, 0x00280ffb, 0x0fe301fa,
502 0x001d0ffd, 0x0fe801fe, 0x00140ffe, 0x0fed0201,
503 0x000c0000, 0x0ff20202, 0x00050000, 0x0ff90202,
504 0x02000000, 0x00000000, 0x02040ff7, 0x00000005,
505 0x02070fed, 0x0000000c, 0x02060fe6, 0x0ffe0016,
506 0x02050fdf, 0x0ffc0020, 0x02020fd9, 0x0ff9002c,
507 0x01fe0fd4, 0x0ff60038, 0x01f80fcf, 0x0ff30046,
508 0x01f00fcb, 0x0fef0056, 0x01e70fc8, 0x0feb0066,
509 0x01db0fc7, 0x0fe60078, 0x01cc0fc6, 0x0fe3008b,
510 0x01bf0fc5, 0x0fdd009f, 0x01ae0fc6, 0x0fd800b4,
511 0x019c0fc6, 0x0fd400ca, 0x01880fc9, 0x0fcf00e0,
512 0x01750fc9, 0x0fc900f9, 0x015d0fce, 0x0fc6010f,
513 0x01460fd0, 0x0fc20128, 0x012e0fd3, 0x0fbf0140,
514 0x01140fd8, 0x0fbc0158, 0x00f90fdd, 0x0fbb016f,
515 0x00df0fe0, 0x0fba0187, 0x00c40fe5, 0x0fb9019e,
516 0x00aa0fe9, 0x0fba01b3, 0x008e0fef, 0x0fbd01c6,
517 0x00740ff3, 0x0fc301d6, 0x005d0ff6, 0x0fc801e5,
518 0x00450ffa, 0x0fd001f1, 0x00300ffc, 0x0fda01fa,
519 0x001c0000, 0x0fe40200, 0x000c0000, 0x0ff20202,
520 0x02000000, 0x00000000, 0x02030ff7, 0x00000006,
521 0x02020fee, 0x00000010, 0x02000fe7, 0x0ffe001b,
522 0x01fe0fdf, 0x0ffc0027, 0x01f70fda, 0x0ffa0035,
523 0x01f00fd5, 0x0ff70044, 0x01e70fd0, 0x0ff40055,
524 0x01dd0fcd, 0x0fef0067, 0x01d00fcb, 0x0fec0079,
525 0x01bf0fcb, 0x0fe8008e, 0x01af0fca, 0x0fe500a2,
526 0x019f0fc9, 0x0fe000b8, 0x018c0fca, 0x0fdb00cf,
527 0x01770fcc, 0x0fd800e5, 0x01620fce, 0x0fd400fc,
528 0x014d0fcf, 0x0fcf0115, 0x01350fd3, 0x0fcd012b,
529 0x011d0fd6, 0x0fca0143, 0x01050fd9, 0x0fc8015a,
530 0x00ec0fde, 0x0fc60170, 0x00d30fe2, 0x0fc60185,
531 0x00bb0fe5, 0x0fc5019b, 0x00a30fea, 0x0fc501ae,
532 0x008c0fed, 0x0fc601c1, 0x00740ff2, 0x0fc901d1,
533 0x005e0ff5, 0x0fce01df, 0x004b0ff8, 0x0fd301ea,
534 0x00370ffc, 0x0fda01f3, 0x00260ffd, 0x0fe201fb,
535 0x00170000, 0x0fea01ff, 0x00090000, 0x0ff50202,
536 0x02000000, 0x00000000, 0x02010ff7, 0x00000008,
537 0x01ff0fee, 0x00000013, 0x01fb0fe7, 0x0ffe0020,
538 0x01f60fe0, 0x0ffc002e, 0x01ed0fda, 0x0ffa003f,
539 0x01e40fd6, 0x0ff7004f, 0x01d80fd2, 0x0ff40062,
540 0x01ca0fcf, 0x0ff00077, 0x01bb0fcd, 0x0fed008b,
541 0x01a90fcd, 0x0fe900a1, 0x01960fcd, 0x0fe600b7,
542 0x01830fcd, 0x0fe200ce, 0x016d0fcf, 0x0fde00e6,
543 0x01580fd0, 0x0fdb00fd, 0x01410fd3, 0x0fd80114,
544 0x012c0fd4, 0x0fd4012c, 0x01140fd8, 0x0fd30141,
545 0x00fd0fdb, 0x0fd00158, 0x00e60fde, 0x0fcf016d,
546 0x00ce0fe2, 0x0fcd0183, 0x00b70fe6, 0x0fcd0196,
547 0x00a10fe9, 0x0fcd01a9, 0x008b0fed, 0x0fcd01bb,
548 0x00770ff0, 0x0fcf01ca, 0x00620ff4, 0x0fd201d8,
549 0x004f0ff7, 0x0fd601e4, 0x003f0ffa, 0x0fda01ed,
550 0x002e0ffc, 0x0fe001f6, 0x00200ffe, 0x0fe701fb,
551 0x00130000, 0x0fee01ff, 0x00080000, 0x0ff70201,
552 0x02000000, 0x00000000, 0x01ff0ff7, 0x0000000a,
553 0x01f90fee, 0x00000019, 0x01f10fe7, 0x0ffe002a,
554 0x01e60fe1, 0x0ffd003c, 0x01d90fdc, 0x0ffa0051,
555 0x01cc0fd8, 0x0ff70065, 0x01bb0fd5, 0x0ff5007b,
556 0x01a80fd3, 0x0ff10094, 0x01950fd2, 0x0fef00aa,
557 0x01800fd2, 0x0feb00c3, 0x016a0fd3, 0x0fe900da,
558 0x01540fd3, 0x0fe600f3, 0x013f0fd5, 0x0fe2010a,
559 0x01280fd7, 0x0fe00121, 0x01100fda, 0x0fde0138,
560 0x00fb0fdb, 0x0fdb014f, 0x00e40fdf, 0x0fdb0162,
561 0x00ce0fe2, 0x0fd90177, 0x00b90fe4, 0x0fd8018b,
562 0x00a50fe8, 0x0fd8019b, 0x00910fec, 0x0fd801ab,
563 0x007e0fee, 0x0fd801bc, 0x006c0ff2, 0x0fd901c9,
564 0x005c0ff4, 0x0fda01d6, 0x004b0ff7, 0x0fdd01e1,
565 0x003c0ff9, 0x0fe001eb, 0x002f0ffb, 0x0fe401f2,
566 0x00230ffd, 0x0fe801f8, 0x00180ffe, 0x0fed01fd,
567 0x000e0000, 0x0ff20200, 0x00060000, 0x0ff90201,
568 0x02000000, 0x00000000, 0x02030ff9, 0x00000004,
569 0x02050ff2, 0x00000009, 0x02050fed, 0x0ffe0010,
570 0x02040fe7, 0x0ffd0018, 0x02020fe3, 0x0ffb0020,
571 0x01fe0fdf, 0x0ff9002a, 0x01fa0fdb, 0x0ff70034,
572 0x01f40fd8, 0x0ff30041, 0x01ed0fd6, 0x0ff0004d,
573 0x01e30fd5, 0x0fec005c, 0x01d80fd4, 0x0fea006a,
574 0x01cd0fd3, 0x0fe5007b, 0x01c00fd3, 0x0fe1008c,
575 0x01b10fd3, 0x0fdd009f, 0x01a10fd4, 0x0fd900b2,
576 0x01900fd4, 0x0fd400c8, 0x017b0fd7, 0x0fd100dd,
577 0x01660fd9, 0x0fcd00f4, 0x01500fda, 0x0fca010c,
578 0x01380fde, 0x0fc60124, 0x011e0fe2, 0x0fc5013b,
579 0x01040fe4, 0x0fc30155, 0x00e70fe8, 0x0fc10170,
580 0x00cc0feb, 0x0fc10188, 0x00ad0ff0, 0x0fc301a0,
581 0x00900ff4, 0x0fc701b5, 0x00750ff7, 0x0fcc01c8,
582 0x00580ffb, 0x0fd201db, 0x003e0ffd, 0x0fdb01ea,
583 0x00250000, 0x0fe501f6, 0x000f0000, 0x0ff301fe,
584 0x02000000, 0x00000000, 0x02020ff9, 0x00000005,
585 0x02020ff2, 0x0000000c, 0x02010fed, 0x0ffe0014,
586 0x01fe0fe8, 0x0ffd001d, 0x01fa0fe3, 0x0ffb0028,
587 0x01f40fe0, 0x0ff90033, 0x01ed0fdc, 0x0ff70040,
588 0x01e50fd9, 0x0ff3004f, 0x01db0fd7, 0x0ff1005d,
589 0x01ce0fd7, 0x0fed006e, 0x01c00fd6, 0x0feb007f,
590 0x01b30fd5, 0x0fe70091, 0x01a30fd6, 0x0fe300a4,
591 0x01920fd6, 0x0fe000b8, 0x017e0fd8, 0x0fdd00cd,
592 0x016c0fd8, 0x0fd800e4, 0x01560fdb, 0x0fd600f9,
593 0x01400fdd, 0x0fd20111, 0x01290fdf, 0x0fd00128,
594 0x01110fe2, 0x0fce013f, 0x00f80fe6, 0x0fcd0155,
595 0x00de0fe8, 0x0fcc016e, 0x00c40fec, 0x0fcb0185,
596 0x00ab0fef, 0x0fcb019b, 0x00900ff3, 0x0fcd01b0,
597 0x00770ff6, 0x0fd101c2, 0x005f0ff9, 0x0fd501d3,
598 0x00470ffc, 0x0fdb01e2, 0x00320ffd, 0x0fe201ef,
599 0x001e0000, 0x0fea01f8, 0x000c0000, 0x0ff501ff,
600 0x02000000, 0x00000000, 0x02010ff9, 0x00000006,
601 0x02000ff2, 0x0000000e, 0x01fd0fed, 0x0ffe0018,
602 0x01f80fe8, 0x0ffd0023, 0x01f20fe4, 0x0ffb002f,
603 0x01eb0fe0, 0x0ff9003c, 0x01e10fdd, 0x0ff7004b,
604 0x01d60fda, 0x0ff4005c, 0x01c90fd9, 0x0ff2006c,
605 0x01bc0fd8, 0x0fee007e, 0x01ab0fd8, 0x0fec0091,
606 0x019b0fd8, 0x0fe800a5, 0x018b0fd8, 0x0fe400b9,
607 0x01770fd9, 0x0fe200ce, 0x01620fdb, 0x0fdf00e4,
608 0x014f0fdb, 0x0fdb00fb, 0x01380fde, 0x0fda0110,
609 0x01210fe0, 0x0fd70128, 0x010a0fe2, 0x0fd5013f,
610 0x00f30fe6, 0x0fd30154, 0x00da0fe9, 0x0fd3016a,
611 0x00c30feb, 0x0fd20180, 0x00aa0fef, 0x0fd20195,
612 0x00940ff1, 0x0fd301a8, 0x007b0ff5, 0x0fd501bb,
613 0x00650ff7, 0x0fd801cc, 0x00510ffa, 0x0fdc01d9,
614 0x003c0ffd, 0x0fe101e6, 0x002a0ffe, 0x0fe701f1,
615 0x00190000, 0x0fee01f9, 0x000a0000, 0x0ff701ff,
616 0x02000000, 0x00000000, 0x01ff0ff9, 0x00000008,
617 0x01fb0ff2, 0x00000013, 0x01f50fed, 0x0ffe0020,
618 0x01ed0fe8, 0x0ffd002e, 0x01e30fe4, 0x0ffb003e,
619 0x01d80fe1, 0x0ff9004e, 0x01cb0fde, 0x0ff70060,
620 0x01bc0fdc, 0x0ff40074, 0x01ac0fdb, 0x0ff20087,
621 0x019a0fdb, 0x0fef009c, 0x01870fdb, 0x0fed00b1,
622 0x01740fdb, 0x0fea00c7, 0x01600fdc, 0x0fe700dd,
623 0x014b0fdd, 0x0fe500f3, 0x01350fdf, 0x0fe30109,
624 0x01200fe0, 0x0fe00120, 0x01090fe3, 0x0fdf0135,
625 0x00f30fe5, 0x0fdd014b, 0x00dd0fe7, 0x0fdc0160,
626 0x00c70fea, 0x0fdb0174, 0x00b10fed, 0x0fdb0187,
627 0x009c0fef, 0x0fdb019a, 0x00870ff2, 0x0fdb01ac,
628 0x00740ff4, 0x0fdc01bc, 0x00600ff7, 0x0fde01cb,
629 0x004e0ff9, 0x0fe101d8, 0x003e0ffb, 0x0fe401e3,
630 0x002e0ffd, 0x0fe801ed, 0x00200ffe, 0x0fed01f5,
631 0x00130000, 0x0ff201fb, 0x00080000, 0x0ff901ff,
632 0x02000000, 0x00000000, 0x02060ff2, 0x00000008,
633 0x02090fe4, 0x00000013, 0x020a0fd9, 0x0ffc0021,
634 0x02080fce, 0x0ffa0030, 0x02030fc5, 0x0ff60042,
635 0x01fd0fbe, 0x0ff10054, 0x01f50fb6, 0x0fed0068,
636 0x01e90fb1, 0x0fe60080, 0x01dc0fae, 0x0fe10095,
637 0x01ca0fae, 0x0fda00ae, 0x01b70fad, 0x0fd600c6,
638 0x01a40fad, 0x0fcf00e0, 0x018f0faf, 0x0fc800fa,
639 0x01780fb1, 0x0fc30114, 0x015f0fb5, 0x0fbf012d,
640 0x01490fb7, 0x0fb70149, 0x012d0fbf, 0x0fb5015f,
641 0x01140fc3, 0x0fb10178, 0x00fa0fc8, 0x0faf018f,
642 0x00e00fcf, 0x0fad01a4, 0x00c60fd6, 0x0fad01b7,
643 0x00ae0fda, 0x0fae01ca, 0x00950fe1, 0x0fae01dc,
644 0x00800fe6, 0x0fb101e9, 0x00680fed, 0x0fb601f5,
645 0x00540ff1, 0x0fbe01fd, 0x00420ff6, 0x0fc50203,
646 0x00300ffa, 0x0fce0208, 0x00210ffc, 0x0fd9020a,
647 0x00130000, 0x0fe40209, 0x00080000, 0x0ff20206,
648 0x02000000, 0x00000000, 0x02040ff2, 0x0000000a,
649 0x02040fe4, 0x00000018, 0x02010fda, 0x0ffc0029,
650 0x01fc0fcf, 0x0ffa003b, 0x01f30fc7, 0x0ff60050,
651 0x01e90fc0, 0x0ff20065, 0x01dc0fba, 0x0fee007c,
652 0x01cc0fb6, 0x0fe80096, 0x01ba0fb4, 0x0fe400ae,
653 0x01a70fb4, 0x0fdd00c8, 0x018f0fb5, 0x0fda00e2,
654 0x017a0fb5, 0x0fd400fd, 0x01630fb8, 0x0fce0117,
655 0x014c0fba, 0x0fca0130, 0x01320fbf, 0x0fc70148,
656 0x011b0fc1, 0x0fc10163, 0x01010fc8, 0x0fc00177,
657 0x00e90fcd, 0x0fbd018d, 0x00d10fd1, 0x0fbc01a2,
658 0x00ba0fd7, 0x0fbb01b4, 0x00a30fdd, 0x0fbc01c4,
659 0x008e0fe1, 0x0fbd01d4, 0x00790fe7, 0x0fbe01e2,
660 0x00670feb, 0x0fc001ee, 0x00540ff1, 0x0fc501f6,
661 0x00430ff4, 0x0fcb01fe, 0x00340ff8, 0x0fd10203,
662 0x00260ffb, 0x0fd80207, 0x001a0ffd, 0x0fe10208,
663 0x000f0000, 0x0fea0207, 0x00060000, 0x0ff50205,
664 0x02000000, 0x00000000, 0x02020ff2, 0x0000000c,
665 0x02000fe4, 0x0000001c, 0x01fa0fda, 0x0ffc0030,
666 0x01f10fd0, 0x0ffa0045, 0x01e50fc8, 0x0ff6005d,
667 0x01d60fc3, 0x0ff30074, 0x01c60fbd, 0x0fef008e,
668 0x01b30fba, 0x0fe900aa, 0x019e0fb9, 0x0fe500c4,
669 0x01870fba, 0x0fe000df, 0x016f0fbb, 0x0fdd00f9,
670 0x01580fbc, 0x0fd80114, 0x01400fbf, 0x0fd3012e,
671 0x01280fc2, 0x0fd00146, 0x010f0fc6, 0x0fce015d,
672 0x00f90fc9, 0x0fc90175, 0x00e00fcf, 0x0fc90188,
673 0x00ca0fd4, 0x0fc6019c, 0x00b40fd8, 0x0fc601ae,
674 0x009f0fdd, 0x0fc501bf, 0x008b0fe3, 0x0fc601cc,
675 0x00780fe6, 0x0fc701db, 0x00660feb, 0x0fc801e7,
676 0x00560fef, 0x0fcb01f0, 0x00460ff3, 0x0fcf01f8,
677 0x00380ff6, 0x0fd401fe, 0x002c0ff9, 0x0fd90202,
678 0x00200ffc, 0x0fdf0205, 0x00160ffe, 0x0fe60206,
679 0x000c0000, 0x0fed0207, 0x00050000, 0x0ff70204,
680 0x02000000, 0x00000000, 0x01fe0ff3, 0x0000000f,
681 0x01f60fe5, 0x00000025, 0x01ea0fdb, 0x0ffd003e,
682 0x01db0fd2, 0x0ffb0058, 0x01c80fcc, 0x0ff70075,
683 0x01b50fc7, 0x0ff40090, 0x01a00fc3, 0x0ff000ad,
684 0x01880fc1, 0x0feb00cc, 0x01700fc1, 0x0fe800e7,
685 0x01550fc3, 0x0fe40104, 0x013b0fc5, 0x0fe2011e,
686 0x01240fc6, 0x0fde0138, 0x010c0fca, 0x0fda0150,
687 0x00f40fcd, 0x0fd90166, 0x00dd0fd1, 0x0fd7017b,
688 0x00c80fd4, 0x0fd40190, 0x00b20fd9, 0x0fd401a1,
689 0x009f0fdd, 0x0fd301b1, 0x008c0fe1, 0x0fd301c0,
690 0x007b0fe5, 0x0fd301cd, 0x006a0fea, 0x0fd401d8,
691 0x005c0fec, 0x0fd501e3, 0x004d0ff0, 0x0fd601ed,
692 0x00410ff3, 0x0fd801f4, 0x00340ff7, 0x0fdb01fa,
693 0x002a0ff9, 0x0fdf01fe, 0x00200ffb, 0x0fe30202,
694 0x00180ffd, 0x0fe70204, 0x00100ffe, 0x0fed0205,
695 0x00090000, 0x0ff20205, 0x00040000, 0x0ff90203,
696 0x02000000, 0x00000000, 0x02050ff5, 0x00000006,
697 0x02070fea, 0x0000000f, 0x02080fe1, 0x0ffd001a,
698 0x02070fd8, 0x0ffb0026, 0x02030fd1, 0x0ff80034,
699 0x01fe0fcb, 0x0ff40043, 0x01f60fc5, 0x0ff10054,
700 0x01ee0fc0, 0x0feb0067, 0x01e20fbe, 0x0fe70079,
701 0x01d40fbd, 0x0fe1008e, 0x01c40fbc, 0x0fdd00a3,
702 0x01b40fbb, 0x0fd700ba, 0x01a20fbc, 0x0fd100d1,
703 0x018d0fbd, 0x0fcd00e9, 0x01770fc0, 0x0fc80101,
704 0x01630fc1, 0x0fc1011b, 0x01480fc7, 0x0fbf0132,
705 0x01300fca, 0x0fba014c, 0x01170fce, 0x0fb80163,
706 0x00fd0fd4, 0x0fb5017a, 0x00e20fda, 0x0fb5018f,
707 0x00c80fdd, 0x0fb401a7, 0x00ae0fe4, 0x0fb401ba,
708 0x00960fe8, 0x0fb601cc, 0x007c0fee, 0x0fba01dc,
709 0x00650ff2, 0x0fc001e9, 0x00500ff6, 0x0fc701f3,
710 0x003b0ffa, 0x0fcf01fc, 0x00290ffc, 0x0fda0201,
711 0x00180000, 0x0fe40204, 0x000a0000, 0x0ff20204,
712 0x02000000, 0x00000000, 0x02030ff5, 0x00000008,
713 0x02030fea, 0x00000013, 0x02020fe1, 0x0ffd0020,
714 0x01fc0fd9, 0x0ffc002f, 0x01f60fd2, 0x0ff80040,
715 0x01ed0fcd, 0x0ff50051, 0x01e30fc7, 0x0ff10065,
716 0x01d70fc3, 0x0fec007a, 0x01c60fc2, 0x0fe9008f,
717 0x01b60fc1, 0x0fe300a6, 0x01a20fc1, 0x0fe000bd,
718 0x018f0fc1, 0x0fdb00d5, 0x017b0fc2, 0x0fd500ee,
719 0x01640fc4, 0x0fd20106, 0x014d0fc8, 0x0fce011d,
720 0x01370fc9, 0x0fc90137, 0x011d0fce, 0x0fc8014d,
721 0x01060fd2, 0x0fc40164, 0x00ee0fd5, 0x0fc2017b,
722 0x00d50fdb, 0x0fc1018f, 0x00bd0fe0, 0x0fc101a2,
723 0x00a60fe3, 0x0fc101b6, 0x008f0fe9, 0x0fc201c6,
724 0x007a0fec, 0x0fc301d7, 0x00650ff1, 0x0fc701e3,
725 0x00510ff5, 0x0fcd01ed, 0x00400ff8, 0x0fd201f6,
726 0x002f0ffc, 0x0fd901fc, 0x00200ffd, 0x0fe10202,
727 0x00130000, 0x0fea0203, 0x00080000, 0x0ff50203,
728 0x02000000, 0x00000000, 0x02020ff5, 0x00000009,
729 0x01ff0fea, 0x00000017, 0x01fb0fe2, 0x0ffd0026,
730 0x01f30fda, 0x0ffc0037, 0x01ea0fd3, 0x0ff8004b,
731 0x01df0fce, 0x0ff5005e, 0x01d10fc9, 0x0ff20074,
732 0x01c10fc6, 0x0fed008c, 0x01ae0fc5, 0x0fea00a3,
733 0x019b0fc5, 0x0fe500bb, 0x01850fc6, 0x0fe200d3,
734 0x01700fc6, 0x0fde00ec, 0x015a0fc8, 0x0fd90105,
735 0x01430fca, 0x0fd6011d, 0x012b0fcd, 0x0fd30135,
736 0x01150fcf, 0x0fcf014d, 0x00fc0fd4, 0x0fce0162,
737 0x00e50fd8, 0x0fcc0177, 0x00cf0fdb, 0x0fca018c,
738 0x00b80fe0, 0x0fc9019f, 0x00a20fe5, 0x0fca01af,
739 0x008e0fe8, 0x0fcb01bf, 0x00790fec, 0x0fcb01d0,
740 0x00670fef, 0x0fcd01dd, 0x00550ff4, 0x0fd001e7,
741 0x00440ff7, 0x0fd501f0, 0x00350ffa, 0x0fda01f7,
742 0x00270ffc, 0x0fdf01fe, 0x001b0ffe, 0x0fe70200,
743 0x00100000, 0x0fee0202, 0x00060000, 0x0ff70203,
744 0x02000000, 0x00000000, 0x01ff0ff5, 0x0000000c,
745 0x01f80fea, 0x0000001e, 0x01ef0fe2, 0x0ffd0032,
746 0x01e20fdb, 0x0ffc0047, 0x01d30fd5, 0x0ff9005f,
747 0x01c20fd1, 0x0ff60077, 0x01b00fcd, 0x0ff30090,
748 0x019b0fcb, 0x0fef00ab, 0x01850fcb, 0x0fec00c4,
749 0x016e0fcc, 0x0fe800de, 0x01550fcd, 0x0fe600f8,
750 0x013f0fce, 0x0fe20111, 0x01280fd0, 0x0fdf0129,
751 0x01110fd2, 0x0fdd0140, 0x00f90fd6, 0x0fdb0156,
752 0x00e40fd8, 0x0fd8016c, 0x00cd0fdd, 0x0fd8017e,
753 0x00b80fe0, 0x0fd60192, 0x00a40fe3, 0x0fd601a3,
754 0x00910fe7, 0x0fd501b3, 0x007f0feb, 0x0fd601c0,
755 0x006e0fed, 0x0fd701ce, 0x005d0ff1, 0x0fd701db,
756 0x004f0ff3, 0x0fd901e5, 0x00400ff7, 0x0fdc01ed,
757 0x00330ff9, 0x0fe001f4, 0x00280ffb, 0x0fe301fa,
758 0x001d0ffd, 0x0fe801fe, 0x00140ffe, 0x0fed0201,
759 0x000c0000, 0x0ff20202, 0x00050000, 0x0ff90202,
760 0x02000000, 0x00000000, 0x02040ff7, 0x00000005,
761 0x02070fed, 0x0000000c, 0x02060fe6, 0x0ffe0016,
762 0x02050fdf, 0x0ffc0020, 0x02020fd9, 0x0ff9002c,
763 0x01fe0fd4, 0x0ff60038, 0x01f80fcf, 0x0ff30046,
764 0x01f00fcb, 0x0fef0056, 0x01e70fc8, 0x0feb0066,
765 0x01db0fc7, 0x0fe60078, 0x01cc0fc6, 0x0fe3008b,
766 0x01bf0fc5, 0x0fdd009f, 0x01ae0fc6, 0x0fd800b4,
767 0x019c0fc6, 0x0fd400ca, 0x01880fc9, 0x0fcf00e0,
768 0x01750fc9, 0x0fc900f9, 0x015d0fce, 0x0fc6010f,
769 0x01460fd0, 0x0fc20128, 0x012e0fd3, 0x0fbf0140,
770 0x01140fd8, 0x0fbc0158, 0x00f90fdd, 0x0fbb016f,
771 0x00df0fe0, 0x0fba0187, 0x00c40fe5, 0x0fb9019e,
772 0x00aa0fe9, 0x0fba01b3, 0x008e0fef, 0x0fbd01c6,
773 0x00740ff3, 0x0fc301d6, 0x005d0ff6, 0x0fc801e5,
774 0x00450ffa, 0x0fd001f1, 0x00300ffc, 0x0fda01fa,
775 0x001c0000, 0x0fe40200, 0x000c0000, 0x0ff20202,
776 0x02000000, 0x00000000, 0x02030ff7, 0x00000006,
777 0x02020fee, 0x00000010, 0x02000fe7, 0x0ffe001b,
778 0x01fe0fdf, 0x0ffc0027, 0x01f70fda, 0x0ffa0035,
779 0x01f00fd5, 0x0ff70044, 0x01e70fd0, 0x0ff40055,
780 0x01dd0fcd, 0x0fef0067, 0x01d00fcb, 0x0fec0079,
781 0x01bf0fcb, 0x0fe8008e, 0x01af0fca, 0x0fe500a2,
782 0x019f0fc9, 0x0fe000b8, 0x018c0fca, 0x0fdb00cf,
783 0x01770fcc, 0x0fd800e5, 0x01620fce, 0x0fd400fc,
784 0x014d0fcf, 0x0fcf0115, 0x01350fd3, 0x0fcd012b,
785 0x011d0fd6, 0x0fca0143, 0x01050fd9, 0x0fc8015a,
786 0x00ec0fde, 0x0fc60170, 0x00d30fe2, 0x0fc60185,
787 0x00bb0fe5, 0x0fc5019b, 0x00a30fea, 0x0fc501ae,
788 0x008c0fed, 0x0fc601c1, 0x00740ff2, 0x0fc901d1,
789 0x005e0ff5, 0x0fce01df, 0x004b0ff8, 0x0fd301ea,
790 0x00370ffc, 0x0fda01f3, 0x00260ffd, 0x0fe201fb,
791 0x00170000, 0x0fea01ff, 0x00090000, 0x0ff50202,
792 0x02000000, 0x00000000, 0x02010ff7, 0x00000008,
793 0x01ff0fee, 0x00000013, 0x01fb0fe7, 0x0ffe0020,
794 0x01f60fe0, 0x0ffc002e, 0x01ed0fda, 0x0ffa003f,
795 0x01e40fd6, 0x0ff7004f, 0x01d80fd2, 0x0ff40062,
796 0x01ca0fcf, 0x0ff00077, 0x01bb0fcd, 0x0fed008b,
797 0x01a90fcd, 0x0fe900a1, 0x01960fcd, 0x0fe600b7,
798 0x01830fcd, 0x0fe200ce, 0x016d0fcf, 0x0fde00e6,
799 0x01580fd0, 0x0fdb00fd, 0x01410fd3, 0x0fd80114,
800 0x012c0fd4, 0x0fd4012c, 0x01140fd8, 0x0fd30141,
801 0x00fd0fdb, 0x0fd00158, 0x00e60fde, 0x0fcf016d,
802 0x00ce0fe2, 0x0fcd0183, 0x00b70fe6, 0x0fcd0196,
803 0x00a10fe9, 0x0fcd01a9, 0x008b0fed, 0x0fcd01bb,
804 0x00770ff0, 0x0fcf01ca, 0x00620ff4, 0x0fd201d8,
805 0x004f0ff7, 0x0fd601e4, 0x003f0ffa, 0x0fda01ed,
806 0x002e0ffc, 0x0fe001f6, 0x00200ffe, 0x0fe701fb,
807 0x00130000, 0x0fee01ff, 0x00080000, 0x0ff70201,
808 0x02000000, 0x00000000, 0x01ff0ff7, 0x0000000a,
809 0x01f90fee, 0x00000019, 0x01f10fe7, 0x0ffe002a,
810 0x01e60fe1, 0x0ffd003c, 0x01d90fdc, 0x0ffa0051,
811 0x01cc0fd8, 0x0ff70065, 0x01bb0fd5, 0x0ff5007b,
812 0x01a80fd3, 0x0ff10094, 0x01950fd2, 0x0fef00aa,
813 0x01800fd2, 0x0feb00c3, 0x016a0fd3, 0x0fe900da,
814 0x01540fd3, 0x0fe600f3, 0x013f0fd5, 0x0fe2010a,
815 0x01280fd7, 0x0fe00121, 0x01100fda, 0x0fde0138,
816 0x00fb0fdb, 0x0fdb014f, 0x00e40fdf, 0x0fdb0162,
817 0x00ce0fe2, 0x0fd90177, 0x00b90fe4, 0x0fd8018b,
818 0x00a50fe8, 0x0fd8019b, 0x00910fec, 0x0fd801ab,
819 0x007e0fee, 0x0fd801bc, 0x006c0ff2, 0x0fd901c9,
820 0x005c0ff4, 0x0fda01d6, 0x004b0ff7, 0x0fdd01e1,
821 0x003c0ff9, 0x0fe001eb, 0x002f0ffb, 0x0fe401f2,
822 0x00230ffd, 0x0fe801f8, 0x00180ffe, 0x0fed01fd,
823 0x000e0000, 0x0ff20200, 0x00060000, 0x0ff90201,
824 0x02000000, 0x00000000, 0x02030ff9, 0x00000004,
825 0x02050ff2, 0x00000009, 0x02050fed, 0x0ffe0010,
826 0x02040fe7, 0x0ffd0018, 0x02020fe3, 0x0ffb0020,
827 0x01fe0fdf, 0x0ff9002a, 0x01fa0fdb, 0x0ff70034,
828 0x01f40fd8, 0x0ff30041, 0x01ed0fd6, 0x0ff0004d,
829 0x01e30fd5, 0x0fec005c, 0x01d80fd4, 0x0fea006a,
830 0x01cd0fd3, 0x0fe5007b, 0x01c00fd3, 0x0fe1008c,
831 0x01b10fd3, 0x0fdd009f, 0x01a10fd4, 0x0fd900b2,
832 0x01900fd4, 0x0fd400c8, 0x017b0fd7, 0x0fd100dd,
833 0x01660fd9, 0x0fcd00f4, 0x01500fda, 0x0fca010c,
834 0x01380fde, 0x0fc60124, 0x011e0fe2, 0x0fc5013b,
835 0x01040fe4, 0x0fc30155, 0x00e70fe8, 0x0fc10170,
836 0x00cc0feb, 0x0fc10188, 0x00ad0ff0, 0x0fc301a0,
837 0x00900ff4, 0x0fc701b5, 0x00750ff7, 0x0fcc01c8,
838 0x00580ffb, 0x0fd201db, 0x003e0ffd, 0x0fdb01ea,
839 0x00250000, 0x0fe501f6, 0x000f0000, 0x0ff301fe,
840 0x02000000, 0x00000000, 0x02020ff9, 0x00000005,
841 0x02020ff2, 0x0000000c, 0x02010fed, 0x0ffe0014,
842 0x01fe0fe8, 0x0ffd001d, 0x01fa0fe3, 0x0ffb0028,
843 0x01f40fe0, 0x0ff90033, 0x01ed0fdc, 0x0ff70040,
844 0x01e50fd9, 0x0ff3004f, 0x01db0fd7, 0x0ff1005d,
845 0x01ce0fd7, 0x0fed006e, 0x01c00fd6, 0x0feb007f,
846 0x01b30fd5, 0x0fe70091, 0x01a30fd6, 0x0fe300a4,
847 0x01920fd6, 0x0fe000b8, 0x017e0fd8, 0x0fdd00cd,
848 0x016c0fd8, 0x0fd800e4, 0x01560fdb, 0x0fd600f9,
849 0x01400fdd, 0x0fd20111, 0x01290fdf, 0x0fd00128,
850 0x01110fe2, 0x0fce013f, 0x00f80fe6, 0x0fcd0155,
851 0x00de0fe8, 0x0fcc016e, 0x00c40fec, 0x0fcb0185,
852 0x00ab0fef, 0x0fcb019b, 0x00900ff3, 0x0fcd01b0,
853 0x00770ff6, 0x0fd101c2, 0x005f0ff9, 0x0fd501d3,
854 0x00470ffc, 0x0fdb01e2, 0x00320ffd, 0x0fe201ef,
855 0x001e0000, 0x0fea01f8, 0x000c0000, 0x0ff501ff,
856 0x02000000, 0x00000000, 0x02010ff9, 0x00000006,
857 0x02000ff2, 0x0000000e, 0x01fd0fed, 0x0ffe0018,
858 0x01f80fe8, 0x0ffd0023, 0x01f20fe4, 0x0ffb002f,
859 0x01eb0fe0, 0x0ff9003c, 0x01e10fdd, 0x0ff7004b,
860 0x01d60fda, 0x0ff4005c, 0x01c90fd9, 0x0ff2006c,
861 0x01bc0fd8, 0x0fee007e, 0x01ab0fd8, 0x0fec0091,
862 0x019b0fd8, 0x0fe800a5, 0x018b0fd8, 0x0fe400b9,
863 0x01770fd9, 0x0fe200ce, 0x01620fdb, 0x0fdf00e4,
864 0x014f0fdb, 0x0fdb00fb, 0x01380fde, 0x0fda0110,
865 0x01210fe0, 0x0fd70128, 0x010a0fe2, 0x0fd5013f,
866 0x00f30fe6, 0x0fd30154, 0x00da0fe9, 0x0fd3016a,
867 0x00c30feb, 0x0fd20180, 0x00aa0fef, 0x0fd20195,
868 0x00940ff1, 0x0fd301a8, 0x007b0ff5, 0x0fd501bb,
869 0x00650ff7, 0x0fd801cc, 0x00510ffa, 0x0fdc01d9,
870 0x003c0ffd, 0x0fe101e6, 0x002a0ffe, 0x0fe701f1,
871 0x00190000, 0x0fee01f9, 0x000a0000, 0x0ff701ff,
872 0x02000000, 0x00000000, 0x01ff0ff9, 0x00000008,
873 0x01fb0ff2, 0x00000013, 0x01f50fed, 0x0ffe0020,
874 0x01ed0fe8, 0x0ffd002e, 0x01e30fe4, 0x0ffb003e,
875 0x01d80fe1, 0x0ff9004e, 0x01cb0fde, 0x0ff70060,
876 0x01bc0fdc, 0x0ff40074, 0x01ac0fdb, 0x0ff20087,
877 0x019a0fdb, 0x0fef009c, 0x01870fdb, 0x0fed00b1,
878 0x01740fdb, 0x0fea00c7, 0x01600fdc, 0x0fe700dd,
879 0x014b0fdd, 0x0fe500f3, 0x01350fdf, 0x0fe30109,
880 0x01200fe0, 0x0fe00120, 0x01090fe3, 0x0fdf0135,
881 0x00f30fe5, 0x0fdd014b, 0x00dd0fe7, 0x0fdc0160,
882 0x00c70fea, 0x0fdb0174, 0x00b10fed, 0x0fdb0187,
883 0x009c0fef, 0x0fdb019a, 0x00870ff2, 0x0fdb01ac,
884 0x00740ff4, 0x0fdc01bc, 0x00600ff7, 0x0fde01cb,
885 0x004e0ff9, 0x0fe101d8, 0x003e0ffb, 0x0fe401e3,
886 0x002e0ffd, 0x0fe801ed, 0x00200ffe, 0x0fed01f5,
887 0x00130000, 0x0ff201fb, 0x00080000, 0x0ff901ff
888};
889
890
891#define MDP4_QSEED_TABLE0_OFF 0x8100
892#define MDP4_QSEED_TABLE1_OFF 0x8200
893#define MDP4_QSEED_TABLE2_OFF 0x9000
894
895void mdp4_vg_qseed_init(int vp_num)
896{
897 uint32 *off;
898 int i, voff;
899
900 voff = MDP4_VIDEO_OFF * vp_num;
901 off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
902 MDP4_QSEED_TABLE0_OFF);
903 for (i = 0; i < (sizeof(vg_qseed_table0) / sizeof(uint32)); i++) {
904 outpdw(off, vg_qseed_table0[i]);
905 off++;
906 }
907
908 off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
909 MDP4_QSEED_TABLE1_OFF);
910 for (i = 0; i < (sizeof(vg_qseed_table1) / sizeof(uint32)); i++) {
911 outpdw(off, vg_qseed_table1[i]);
912 off++;
913 }
914
915 off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
916 MDP4_QSEED_TABLE2_OFF);
917 for (i = 0; i < (sizeof(vg_qseed_table2) / sizeof(uint32)); i++) {
918 outpdw(off, vg_qseed_table2[i]);
919 off++;
920 }
921
922}
923
924void mdp4_mixer_blend_init(mixer_num)
925{
926 unsigned char *overlay_base;
927 int off;
928
929 if (mixer_num) /* mixer number, /dev/fb0, /dev/fb1 */
930 overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
931 else
932 overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
933
934 /* stage 0 to stage 2 */
935 off = 0;
936 outpdw(overlay_base + off + 0x104, 0x010);
937 outpdw(overlay_base + off + 0x108, 0xff);/* FG */
938 outpdw(overlay_base + off + 0x10c, 0x00);/* BG */
939
940 off += 0x20;
941 outpdw(overlay_base + off + 0x104, 0x010);
942 outpdw(overlay_base + off + 0x108, 0xff);/* FG */
943 outpdw(overlay_base + off + 0x10c, 0x00);/* BG */
944
945 off += 0x20;
946 outpdw(overlay_base + off + 0x104, 0x010);
947 outpdw(overlay_base + off + 0x108, 0xff);/* FG */
948 outpdw(overlay_base + off + 0x10c, 0x00);/* BG */
949}
950
951
952static uint32 csc_matrix_tab[9] = {
953 0x0254, 0x0000, 0x0331,
954 0x0254, 0xff37, 0xfe60,
955 0x0254, 0x0409, 0x0000
956};
957
958static uint32 csc_pre_bv_tab[3] = {0xfff0, 0xff80, 0xff80 };
959static uint32 csc_post_bv_tab[3] = {0, 0, 0 };
960
961static uint32 csc_pre_lv_tab[6] = {0, 0xff, 0, 0xff, 0, 0xff };
962static uint32 csc_post_lv_tab[6] = {0, 0xff, 0, 0xff, 0, 0xff };
963
964#define MDP4_CSC_MV_OFF 0x4400
965#define MDP4_CSC_PRE_BV_OFF 0x4500
966#define MDP4_CSC_POST_BV_OFF 0x4580
967#define MDP4_CSC_PRE_LV_OFF 0x4600
968#define MDP4_CSC_POST_LV_OFF 0x4680
969
970void mdp4_vg_csc_mv_setup(int vp_num)
971{
972 uint32 *off;
973 int i, voff;
974
975 voff = MDP4_VIDEO_OFF * vp_num;
976 off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
977 MDP4_CSC_MV_OFF);
978 for (i = 0; i < 9; i++) {
979 outpdw(off, csc_matrix_tab[i]);
980 off++;
981 }
982}
983
984void mdp4_vg_csc_pre_bv_setup(int vp_num)
985{
986 uint32 *off;
987 int i, voff;
988
989 voff = MDP4_VIDEO_OFF * vp_num;
990 off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
991 MDP4_CSC_PRE_BV_OFF);
992 for (i = 0; i < 3; i++) {
993 outpdw(off, csc_pre_bv_tab[i]);
994 off++;
995 }
996}
997
998void mdp4_vg_csc_post_bv_setup(int vp_num)
999{
1000 uint32 *off;
1001 int i, voff;
1002
1003 voff = MDP4_VIDEO_OFF * vp_num;
1004 off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
1005 MDP4_CSC_POST_BV_OFF);
1006 for (i = 0; i < 3; i++) {
1007 outpdw(off, csc_post_bv_tab[i]);
1008 off++;
1009 }
1010}
1011
1012void mdp4_vg_csc_pre_lv_setup(int vp_num)
1013{
1014 uint32 *off;
1015 int i, voff;
1016
1017 voff = MDP4_VIDEO_OFF * vp_num;
1018 off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
1019 MDP4_CSC_PRE_LV_OFF);
1020
1021 for (i = 0; i < 6; i++) {
1022 outpdw(off, csc_pre_lv_tab[i]);
1023 off++;
1024 }
1025}
1026
1027void mdp4_vg_csc_post_lv_setup(int vp_num)
1028{
1029 uint32 *off;
1030 int i, voff;
1031
1032 voff = MDP4_VIDEO_OFF * vp_num;
1033 off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
1034 MDP4_CSC_POST_LV_OFF);
1035
1036 for (i = 0; i < 6; i++) {
1037 outpdw(off, csc_post_lv_tab[i]);
1038 off++;
1039 }
1040}
1041
1042char gc_lut[] = {
1043 0x0, 0x1, 0x2, 0x2, 0x3, 0x4, 0x5, 0x6,
1044 0x6, 0x7, 0x8, 0x9, 0xA, 0xA, 0xB, 0xC,
1045 0xD, 0xD, 0xE, 0xF, 0xF, 0x10, 0x10, 0x11,
1046 0x12, 0x12, 0x13, 0x13, 0x14, 0x14, 0x15, 0x15,
1047 0x16, 0x16, 0x17, 0x17, 0x17, 0x18, 0x18, 0x19,
1048 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B, 0x1B, 0x1C,
1049 0x1C, 0x1D, 0x1D, 0x1D, 0x1E, 0x1E, 0x1E, 0x1F,
1050 0x1F, 0x1F, 0x20, 0x20, 0x20, 0x21, 0x21, 0x21,
1051 0x22, 0x22, 0x22, 0x22, 0x23, 0x23, 0x23, 0x24,
1052 0x24, 0x24, 0x25, 0x25, 0x25, 0x25, 0x26, 0x26,
1053 0x26, 0x26, 0x27, 0x27, 0x27, 0x28, 0x28, 0x28,
1054 0x28, 0x29, 0x29, 0x29, 0x29, 0x2A, 0x2A, 0x2A,
1055 0x2A, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2C, 0x2C,
1056 0x2C, 0x2C, 0x2D, 0x2D, 0x2D, 0x2D, 0x2E, 0x2E,
1057 0x2E, 0x2E, 0x2E, 0x2F, 0x2F, 0x2F, 0x2F, 0x30,
1058 0x30, 0x30, 0x30, 0x30, 0x31, 0x31, 0x31, 0x31,
1059 0x31, 0x32, 0x32, 0x32, 0x32, 0x32, 0x33, 0x33,
1060 0x33, 0x33, 0x33, 0x34, 0x34, 0x34, 0x34, 0x34,
1061 0x35, 0x35, 0x35, 0x35, 0x35, 0x36, 0x36, 0x36,
1062 0x36, 0x36, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37,
1063 0x38, 0x38, 0x38, 0x38, 0x38, 0x39, 0x39, 0x39,
1064 0x39, 0x39, 0x39, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A,
1065 0x3A, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3C,
1066 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3D, 0x3D, 0x3D,
1067 0x3D, 0x3D, 0x3D, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E,
1068 0x3E, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x40,
1069 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 0x41,
1070 0x41, 0x41, 0x41, 0x41, 0x42, 0x42, 0x42, 0x42,
1071 0x42, 0x42, 0x42, 0x43, 0x43, 0x43, 0x43, 0x43,
1072 0x43, 0x43, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
1073 0x44, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
1074 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x47,
1075 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x48, 0x48,
1076 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x49, 0x49,
1077 0x49, 0x49, 0x49, 0x49, 0x49, 0x4A, 0x4A, 0x4A,
1078 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4B, 0x4B, 0x4B,
1079 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4C, 0x4C, 0x4C,
1080 0x4C, 0x4C, 0x4C, 0x4C, 0x4D, 0x4D, 0x4D, 0x4D,
1081 0x4D, 0x4D, 0x4D, 0x4D, 0x4E, 0x4E, 0x4E, 0x4E,
1082 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4F, 0x4F, 0x4F,
1083 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x50, 0x50, 0x50,
1084 0x50, 0x50, 0x50, 0x50, 0x50, 0x51, 0x51, 0x51,
1085 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x52, 0x52,
1086 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x53, 0x53,
1087 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x54,
1088 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54,
1089 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1090 0x55, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56,
1091 0x56, 0x56, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
1092 0x57, 0x57, 0x57, 0x58, 0x58, 0x58, 0x58, 0x58,
1093 0x58, 0x58, 0x58, 0x58, 0x58, 0x59, 0x59, 0x59,
1094 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x5A, 0x5A,
1095 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
1096 0x5B, 0x5B, 0x5B, 0x5B, 0x5B, 0x5B, 0x5B, 0x5B,
1097 0x5B, 0x5B, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
1098 0x5C, 0x5C, 0x5C, 0x5C, 0x5D, 0x5D, 0x5D, 0x5D,
1099 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5E, 0x5E,
1100 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E,
1101 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F,
1102 0x5F, 0x5F, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
1103 0x60, 0x60, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61,
1104 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x62,
1105 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62,
1106 0x62, 0x62, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
1107 0x63, 0x63, 0x63, 0x63, 0x63, 0x64, 0x64, 0x64,
1108 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64,
1109 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65,
1110 0x65, 0x65, 0x65, 0x66, 0x66, 0x66, 0x66, 0x66,
1111 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x67, 0x67,
1112 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67,
1113 0x67, 0x67, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68,
1114 0x68, 0x68, 0x68, 0x68, 0x68, 0x69, 0x69, 0x69,
1115 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
1116 0x69, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A,
1117 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6B, 0x6B, 0x6B,
1118 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B,
1119 0x6B, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C,
1120 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6D, 0x6D, 0x6D,
1121 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D,
1122 0x6D, 0x6E, 0x6E, 0x6E, 0x6E, 0x6E, 0x6E, 0x6E,
1123 0x6E, 0x6E, 0x6E, 0x6E, 0x6E, 0x6F, 0x6F, 0x6F,
1124 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F,
1125 0x6F, 0x6F, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
1126 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x71, 0x71,
1127 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71,
1128 0x71, 0x71, 0x71, 0x72, 0x72, 0x72, 0x72, 0x72,
1129 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72,
1130 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
1131 0x73, 0x73, 0x73, 0x73, 0x73, 0x74, 0x74, 0x74,
1132 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74,
1133 0x74, 0x74, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75,
1134 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75,
1135 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76,
1136 0x76, 0x76, 0x76, 0x76, 0x76, 0x77, 0x77, 0x77,
1137 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
1138 0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x78, 0x78,
1139 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
1140 0x78, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79,
1141 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x7A, 0x7A,
1142 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A,
1143 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7B, 0x7B, 0x7B,
1144 0x7B, 0x7B, 0x7B, 0x7B, 0x7B, 0x7B, 0x7B, 0x7B,
1145 0x7B, 0x7B, 0x7B, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C,
1146 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C,
1147 0x7C, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D,
1148 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D,
1149 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E,
1150 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7F, 0x7F,
1151 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
1152 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x80, 0x80, 0x80,
1153 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
1154 0x80, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81, 0x81,
1155 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
1156 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82, 0x82,
1157 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
1158 0x82, 0x82, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
1159 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
1160 0x83, 0x83, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
1161 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
1162 0x84, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
1163 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
1164 0x85, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
1165 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
1166 0x86, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
1167 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
1168 0x87, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
1169 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
1170 0x88, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
1171 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
1172 0x89, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A,
1173 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A,
1174 0x8A, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B,
1175 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B,
1176 0x8B, 0x8B, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C,
1177 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C,
1178 0x8C, 0x8C, 0x8C, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D,
1179 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D,
1180 0x8D, 0x8D, 0x8D, 0x8D, 0x8E, 0x8E, 0x8E, 0x8E,
1181 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E,
1182 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8F, 0x8F, 0x8F,
1183 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F,
1184 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x90, 0x90,
1185 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
1186 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x91,
1187 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
1188 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
1189 0x91, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92,
1190 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92,
1191 0x92, 0x92, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
1192 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
1193 0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x94,
1194 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
1195 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x95, 0x95,
1196 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95,
1197 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95,
1198 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96,
1199 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96,
1200 0x96, 0x96, 0x96, 0x97, 0x97, 0x97, 0x97, 0x97,
1201 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97,
1202 0x97, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98,
1203 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
1204 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
1205 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
1206 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
1207 0x99, 0x99, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
1208 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
1209 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9B, 0x9B, 0x9B,
1210 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B,
1211 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B,
1212 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C,
1213 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C,
1214 0x9C, 0x9C, 0x9C, 0x9C, 0x9D, 0x9D, 0x9D, 0x9D,
1215 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D,
1216 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9E,
1217 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E,
1218 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E,
1219 0x9E, 0x9E, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F,
1220 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F,
1221 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0xA0, 0xA0,
1222 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,
1223 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,
1224 0xA0, 0xA0, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1,
1225 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1,
1226 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA2, 0xA2,
1227 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2,
1228 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2,
1229 0xA2, 0xA2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3,
1230 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3,
1231 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA4, 0xA4,
1232 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4,
1233 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4,
1234 0xA4, 0xA4, 0xA4, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5,
1235 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5,
1236 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5,
1237 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6,
1238 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6,
1239 0xA6, 0xA6, 0xA6, 0xA6, 0xA7, 0xA7, 0xA7, 0xA7,
1240 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7,
1241 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7,
1242 0xA7, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8,
1243 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8,
1244 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA9,
1245 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9,
1246 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9,
1247 0xA9, 0xA9, 0xA9, 0xA9, 0xAA, 0xAA, 0xAA, 0xAA,
1248 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
1249 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
1250 0xAA, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB,
1251 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB,
1252 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAC,
1253 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC,
1254 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC,
1255 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAD, 0xAD, 0xAD,
1256 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD,
1257 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD,
1258 0xAD, 0xAD, 0xAD, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE,
1259 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE,
1260 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE,
1261 0xAE, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF,
1262 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF,
1263 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xB0,
1264 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0,
1265 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0,
1266 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB1, 0xB1,
1267 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1,
1268 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1,
1269 0xB1, 0xB1, 0xB1, 0xB1, 0xB2, 0xB2, 0xB2, 0xB2,
1270 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2,
1271 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2,
1272 0xB2, 0xB2, 0xB2, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3,
1273 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3,
1274 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3,
1275 0xB3, 0xB3, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4,
1276 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4,
1277 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4,
1278 0xB4, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5,
1279 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5,
1280 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5,
1281 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6,
1282 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6,
1283 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6,
1284 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7,
1285 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7,
1286 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB8,
1287 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8,
1288 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8,
1289 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB9,
1290 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9,
1291 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9,
1292 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xBA,
1293 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA,
1294 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA,
1295 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBB,
1296 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB,
1297 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB,
1298 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB,
1299 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC,
1300 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC,
1301 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC,
1302 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD,
1303 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD,
1304 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD,
1305 0xBD, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE,
1306 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE,
1307 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE,
1308 0xBE, 0xBE, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF,
1309 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF,
1310 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF,
1311 0xBF, 0xBF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
1312 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
1313 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
1314 0xC0, 0xC0, 0xC0, 0xC0, 0xC1, 0xC1, 0xC1, 0xC1,
1315 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1,
1316 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1,
1317 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC2, 0xC2, 0xC2,
1318 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2,
1319 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2,
1320 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC3, 0xC3,
1321 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3,
1322 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3,
1323 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3,
1324 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4,
1325 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4,
1326 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4,
1327 0xC4, 0xC4, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5,
1328 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5,
1329 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5,
1330 0xC5, 0xC5, 0xC5, 0xC5, 0xC6, 0xC6, 0xC6, 0xC6,
1331 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6,
1332 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6,
1333 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC7, 0xC7,
1334 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7,
1335 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7,
1336 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7,
1337 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
1338 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
1339 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
1340 0xC8, 0xC8, 0xC8, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9,
1341 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9,
1342 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9,
1343 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xCA, 0xCA,
1344 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA,
1345 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA,
1346 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA,
1347 0xCA, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB,
1348 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB,
1349 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB,
1350 0xCB, 0xCB, 0xCB, 0xCB, 0xCC, 0xCC, 0xCC, 0xCC,
1351 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
1352 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
1353 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCD,
1354 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD,
1355 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD,
1356 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD,
1357 0xCD, 0xCD, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE,
1358 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE,
1359 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE,
1360 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCF, 0xCF,
1361 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF,
1362 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF,
1363 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF,
1364 0xCF, 0xCF, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0,
1365 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0,
1366 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0,
1367 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD1, 0xD1, 0xD1,
1368 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1,
1369 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1,
1370 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1,
1371 0xD1, 0xD1, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
1372 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
1373 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
1374 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD3, 0xD3,
1375 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3,
1376 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3,
1377 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3,
1378 0xD3, 0xD3, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4,
1379 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4,
1380 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4,
1381 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD5,
1382 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5,
1383 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5,
1384 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5,
1385 0xD5, 0xD5, 0xD5, 0xD5, 0xD6, 0xD6, 0xD6, 0xD6,
1386 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6,
1387 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6,
1388 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6,
1389 0xD6, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7,
1390 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7,
1391 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7,
1392 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD8, 0xD8,
1393 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8,
1394 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8,
1395 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8,
1396 0xD8, 0xD8, 0xD8, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9,
1397 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9,
1398 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9,
1399 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9,
1400 0xD9, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA,
1401 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA,
1402 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA,
1403 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDB, 0xDB,
1404 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB,
1405 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB,
1406 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB,
1407 0xDB, 0xDB, 0xDB, 0xDB, 0xDC, 0xDC, 0xDC, 0xDC,
1408 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC,
1409 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC,
1410 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC,
1411 0xDC, 0xDC, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
1412 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
1413 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
1414 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
1415 0xDD, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE,
1416 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE,
1417 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE,
1418 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDF,
1419 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF,
1420 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF,
1421 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF,
1422 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xE0, 0xE0,
1423 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
1424 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
1425 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
1426 0xE0, 0xE0, 0xE0, 0xE0, 0xE1, 0xE1, 0xE1, 0xE1,
1427 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1,
1428 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1,
1429 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1,
1430 0xE1, 0xE1, 0xE1, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2,
1431 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2,
1432 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2,
1433 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2,
1434 0xE2, 0xE2, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
1435 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
1436 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
1437 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
1438 0xE3, 0xE3, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4,
1439 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4,
1440 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4,
1441 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4,
1442 0xE4, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
1443 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
1444 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
1445 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
1446 0xE5, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6,
1447 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6,
1448 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6,
1449 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6,
1450 0xE6, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7,
1451 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7,
1452 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7,
1453 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7,
1454 0xE7, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8,
1455 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8,
1456 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8,
1457 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8,
1458 0xE8, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9,
1459 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9,
1460 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9,
1461 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9,
1462 0xE9, 0xE9, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA,
1463 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA,
1464 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA,
1465 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA,
1466 0xEA, 0xEA, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB,
1467 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB,
1468 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB,
1469 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB,
1470 0xEB, 0xEB, 0xEB, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC,
1471 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC,
1472 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC,
1473 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC,
1474 0xEC, 0xEC, 0xEC, 0xEC, 0xED, 0xED, 0xED, 0xED,
1475 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED,
1476 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED,
1477 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED,
1478 0xED, 0xED, 0xED, 0xED, 0xED, 0xEE, 0xEE, 0xEE,
1479 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
1480 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
1481 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
1482 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEF, 0xEF,
1483 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF,
1484 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF,
1485 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF,
1486 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF,
1487 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
1488 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
1489 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
1490 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
1491 0xF0, 0xF0, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1,
1492 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1,
1493 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1,
1494 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1,
1495 0xF1, 0xF1, 0xF1, 0xF1, 0xF2, 0xF2, 0xF2, 0xF2,
1496 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
1497 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
1498 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
1499 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF3, 0xF3,
1500 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3,
1501 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3,
1502 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3,
1503 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3,
1504 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4,
1505 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4,
1506 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4,
1507 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4,
1508 0xF4, 0xF4, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5,
1509 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5,
1510 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5,
1511 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5,
1512 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF6, 0xF6, 0xF6,
1513 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6,
1514 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6,
1515 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6,
1516 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6,
1517 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7,
1518 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7,
1519 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7,
1520 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7,
1521 0xF7, 0xF7, 0xF7, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
1522 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
1523 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
1524 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
1525 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF9, 0xF9,
1526 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9,
1527 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9,
1528 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9,
1529 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9,
1530 0xF9, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
1531 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
1532 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
1533 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
1534 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFB, 0xFB, 0xFB,
1535 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB,
1536 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB,
1537 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB,
1538 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB,
1539 0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
1540 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
1541 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
1542 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
1543 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFD, 0xFD, 0xFD,
1544 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD,
1545 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD,
1546 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD,
1547 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD,
1548 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
1549 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
1550 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
1551 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
1552 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF,
1553 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1554 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1555};
1556
1557void mdp4_mixer_gc_lut_setup(int mixer_num)
1558{
1559 unsigned char *base;
1560 uint32 data;
1561 char val;
1562 int i, off;
1563
1564 if (mixer_num) /* mixer number, /dev/fb0, /dev/fb1 */
1565 base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
1566 else
1567 base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
1568
1569 base += 0x4000; /* GC_LUT offset */
1570
1571 off = 0;
1572 for (i = 0; i < 4096; i++) {
1573 val = gc_lut[i];
1574 data = (val << 16 | val << 8 | val); /* R, B, and G are same */
1575 outpdw(base + off, data);
1576 off += 4;
1577 }
1578}
1579
1580uint32 igc_video_lut[] = { /* non linear */
1581 0x0, 0x1, 0x2, 0x4, 0x5, 0x6, 0x7, 0x9,
1582 0xA, 0xB, 0xC, 0xE, 0xF, 0x10, 0x12, 0x14,
1583 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F, 0x21, 0x23,
1584 0x25, 0x28, 0x2A, 0x2D, 0x30, 0x32, 0x35, 0x38,
1585 0x3B, 0x3E, 0x42, 0x45, 0x48, 0x4C, 0x4F, 0x53,
1586 0x57, 0x5B, 0x5F, 0x63, 0x67, 0x6B, 0x70, 0x74,
1587 0x79, 0x7E, 0x83, 0x88, 0x8D, 0x92, 0x97, 0x9C,
1588 0xA2, 0xA8, 0xAD, 0xB3, 0xB9, 0xBF, 0xC5, 0xCC,
1589 0xD2, 0xD8, 0xDF, 0xE6, 0xED, 0xF4, 0xFB, 0x102,
1590 0x109, 0x111, 0x118, 0x120, 0x128, 0x130, 0x138, 0x140,
1591 0x149, 0x151, 0x15A, 0x162, 0x16B, 0x174, 0x17D, 0x186,
1592 0x190, 0x199, 0x1A3, 0x1AC, 0x1B6, 0x1C0, 0x1CA, 0x1D5,
1593 0x1DF, 0x1EA, 0x1F4, 0x1FF, 0x20A, 0x215, 0x220, 0x22B,
1594 0x237, 0x242, 0x24E, 0x25A, 0x266, 0x272, 0x27F, 0x28B,
1595 0x298, 0x2A4, 0x2B1, 0x2BE, 0x2CB, 0x2D8, 0x2E6, 0x2F3,
1596 0x301, 0x30F, 0x31D, 0x32B, 0x339, 0x348, 0x356, 0x365,
1597 0x374, 0x383, 0x392, 0x3A1, 0x3B1, 0x3C0, 0x3D0, 0x3E0,
1598 0x3F0, 0x400, 0x411, 0x421, 0x432, 0x443, 0x454, 0x465,
1599 0x476, 0x487, 0x499, 0x4AB, 0x4BD, 0x4CF, 0x4E1, 0x4F3,
1600 0x506, 0x518, 0x52B, 0x53E, 0x551, 0x565, 0x578, 0x58C,
1601 0x5A0, 0x5B3, 0x5C8, 0x5DC, 0x5F0, 0x605, 0x61A, 0x62E,
1602 0x643, 0x659, 0x66E, 0x684, 0x699, 0x6AF, 0x6C5, 0x6DB,
1603 0x6F2, 0x708, 0x71F, 0x736, 0x74D, 0x764, 0x77C, 0x793,
1604 0x7AB, 0x7C3, 0x7DB, 0x7F3, 0x80B, 0x824, 0x83D, 0x855,
1605 0x86F, 0x888, 0x8A1, 0x8BB, 0x8D4, 0x8EE, 0x908, 0x923,
1606 0x93D, 0x958, 0x973, 0x98E, 0x9A9, 0x9C4, 0x9DF, 0x9FB,
1607 0xA17, 0xA33, 0xA4F, 0xA6C, 0xA88, 0xAA5, 0xAC2, 0xADF,
1608 0xAFC, 0xB19, 0xB37, 0xB55, 0xB73, 0xB91, 0xBAF, 0xBCE,
1609 0xBEC, 0xC0B, 0xC2A, 0xC4A, 0xC69, 0xC89, 0xCA8, 0xCC8,
1610 0xCE8, 0xD09, 0xD29, 0xD4A, 0xD6B, 0xD8C, 0xDAD, 0xDCF,
1611 0xDF0, 0xE12, 0xE34, 0xE56, 0xE79, 0xE9B, 0xEBE, 0xEE1,
1612 0xF04, 0xF27, 0xF4B, 0xF6E, 0xF92, 0xFB6, 0xFDB, 0xFFF,
1613};
1614
1615void mdp4_vg_igc_lut_setup(int vp_num)
1616{
1617 unsigned char *base;
1618 int i, voff, off;
1619 uint32 data, val;
1620
1621 voff = MDP4_VIDEO_OFF * vp_num;
1622 base = MDP_BASE + MDP4_VIDEO_BASE + voff + 0x5000;
1623
1624 off = 0;
1625 for (i = 0; i < 256; i++) {
1626 val = igc_video_lut[i];
1627 data = (val << 16 | val); /* color 0 and 1 */
1628 outpdw(base + off, data);
1629 outpdw(base + off + 0x800, val); /* color 2 */
1630 off += 4;
1631 }
1632}
1633
1634uint32 igc_rgb_lut[] = { /* linear */
1635 0x0, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
1636 0x80, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1,
1637 0x101, 0x111, 0x121, 0x131, 0x141, 0x151, 0x161, 0x171,
1638 0x181, 0x191, 0x1A2, 0x1B2, 0x1C2, 0x1D2, 0x1E2, 0x1F2,
1639 0x202, 0x212, 0x222, 0x232, 0x242, 0x252, 0x262, 0x272,
1640 0x282, 0x292, 0x2A2, 0x2B3, 0x2C3, 0x2D3, 0x2E3, 0x2F3,
1641 0x303, 0x313, 0x323, 0x333, 0x343, 0x353, 0x363, 0x373,
1642 0x383, 0x393, 0x3A3, 0x3B3, 0x3C4, 0x3D4, 0x3E4, 0x3F4,
1643 0x404, 0x414, 0x424, 0x434, 0x444, 0x454, 0x464, 0x474,
1644 0x484, 0x494, 0x4A4, 0x4B4, 0x4C4, 0x4D5, 0x4E5, 0x4F5,
1645 0x505, 0x515, 0x525, 0x535, 0x545, 0x555, 0x565, 0x575,
1646 0x585, 0x595, 0x5A5, 0x5B5, 0x5C5, 0x5D5, 0x5E6, 0x5F6,
1647 0x606, 0x616, 0x626, 0x636, 0x646, 0x656, 0x666, 0x676,
1648 0x686, 0x696, 0x6A6, 0x6B6, 0x6C6, 0x6D6, 0x6E6, 0x6F7,
1649 0x707, 0x717, 0x727, 0x737, 0x747, 0x757, 0x767, 0x777,
1650 0x787, 0x797, 0x7A7, 0x7B7, 0x7C7, 0x7D7, 0x7E7, 0x7F7,
1651 0x808, 0x818, 0x828, 0x838, 0x848, 0x858, 0x868, 0x878,
1652 0x888, 0x898, 0x8A8, 0x8B8, 0x8C8, 0x8D8, 0x8E8, 0x8F8,
1653 0x908, 0x919, 0x929, 0x939, 0x949, 0x959, 0x969, 0x979,
1654 0x989, 0x999, 0x9A9, 0x9B9, 0x9C9, 0x9D9, 0x9E9, 0x9F9,
1655 0xA09, 0xA19, 0xA2A, 0xA3A, 0xA4A, 0xA5A, 0xA6A, 0xA7A,
1656 0xA8A, 0xA9A, 0xAAA, 0xABA, 0xACA, 0xADA, 0xAEA, 0xAFA,
1657 0xB0A, 0xB1A, 0xB2A, 0xB3B, 0xB4B, 0xB5B, 0xB6B, 0xB7B,
1658 0xB8B, 0xB9B, 0xBAB, 0xBBB, 0xBCB, 0xBDB, 0xBEB, 0xBFB,
1659 0xC0B, 0xC1B, 0xC2B, 0xC3B, 0xC4C, 0xC5C, 0xC6C, 0xC7C,
1660 0xC8C, 0xC9C, 0xCAC, 0xCBC, 0xCCC, 0xCDC, 0xCEC, 0xCFC,
1661 0xD0C, 0xD1C, 0xD2C, 0xD3C, 0xD4C, 0xD5D, 0xD6D, 0xD7D,
1662 0xD8D, 0xD9D, 0xDAD, 0xDBD, 0xDCD, 0xDDD, 0xDED, 0xDFD,
1663 0xE0D, 0xE1D, 0xE2D, 0xE3D, 0xE4D, 0xE5D, 0xE6E, 0xE7E,
1664 0xE8E, 0xE9E, 0xEAE, 0xEBE, 0xECE, 0xEDE, 0xEEE, 0xEFE,
1665 0xF0E, 0xF1E, 0xF2E, 0xF3E, 0xF4E, 0xF5E, 0xF6E, 0xF7F,
1666 0xF8F, 0xF9F, 0xFAF, 0xFBF, 0xFCF, 0xFDF, 0xFEF, 0xFFF,
1667};
1668
1669void mdp4_rgb_igc_lut_setup(int num)
1670{
1671 unsigned char *base;
1672 int i, voff, off;
1673 uint32 data, val;
1674
1675 voff = MDP4_RGB_OFF * num;
1676 base = MDP_BASE + MDP4_RGB_BASE + voff + 0x5000;
1677
1678 off = 0;
1679 for (i = 0; i < 256; i++) {
1680 val = igc_rgb_lut[i];
1681 data = (val << 16 | val); /* color 0 and 1 */
1682 outpdw(base + off, data);
1683 outpdw(base + off + 0x800, val); /* color 2 */
1684 off += 4;
1685 }
1686}
diff --git a/drivers/staging/msm/mdp_cursor.c b/drivers/staging/msm/mdp_cursor.c
new file mode 100644
index 000000000000..7d28f30d9313
--- /dev/null
+++ b/drivers/staging/msm/mdp_cursor.c
@@ -0,0 +1,104 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/sched.h>
21#include <linux/time.h>
22#include <linux/init.h>
23#include <linux/interrupt.h>
24#include <linux/hrtimer.h>
25
26#include <mach/hardware.h>
27#include <asm/io.h>
28
29#include <asm/system.h>
30#include <asm/mach-types.h>
31#include <linux/semaphore.h>
32#include <linux/spinlock.h>
33
34#include <linux/fb.h>
35
36#include "mdp.h"
37#include "msm_fb.h"
38
39static int cursor_enabled;
40
41int mdp_hw_cursor_update(struct fb_info *info, struct fb_cursor *cursor)
42{
43 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
44 struct fb_image *img = &cursor->image;
45 int calpha_en, transp_en;
46 int alpha;
47 int ret = 0;
48
49 if ((img->width > MDP_CURSOR_WIDTH) ||
50 (img->height > MDP_CURSOR_HEIGHT) ||
51 (img->depth != 32))
52 return -EINVAL;
53
54 if (cursor->set & FB_CUR_SETPOS)
55 MDP_OUTP(MDP_BASE + 0x9004c, (img->dy << 16) | img->dx);
56
57 if (cursor->set & FB_CUR_SETIMAGE) {
58 ret = copy_from_user(mfd->cursor_buf, img->data,
59 img->width*img->height*4);
60 if (ret)
61 return ret;
62
63 if (img->bg_color == 0xffffffff)
64 transp_en = 0;
65 else
66 transp_en = 1;
67
68 alpha = (img->fg_color & 0xff000000) >> 24;
69
70 if (alpha)
71 calpha_en = 0x2; /* xrgb */
72 else
73 calpha_en = 0x1; /* argb */
74
75 MDP_OUTP(MDP_BASE + 0x90044, (img->height << 16) | img->width);
76 MDP_OUTP(MDP_BASE + 0x90048, mfd->cursor_buf_phys);
77 /* order the writes the cursor_buf before updating the
78 * hardware */
79// dma_coherent_pre_ops();
80 MDP_OUTP(MDP_BASE + 0x90060,
81 (transp_en << 3) | (calpha_en << 1) |
82 (inp32(MDP_BASE + 0x90060) & 0x1));
83#ifdef CONFIG_FB_MSM_MDP40
84 MDP_OUTP(MDP_BASE + 0x90064, (alpha << 24));
85 MDP_OUTP(MDP_BASE + 0x90068, (0xffffff & img->bg_color));
86 MDP_OUTP(MDP_BASE + 0x9006C, (0xffffff & img->bg_color));
87#else
88 MDP_OUTP(MDP_BASE + 0x90064,
89 (alpha << 24) | (0xffffff & img->bg_color));
90 MDP_OUTP(MDP_BASE + 0x90068, 0);
91#endif
92 }
93
94 if ((cursor->enable) && (!cursor_enabled)) {
95 cursor_enabled = 1;
96 MDP_OUTP(MDP_BASE + 0x90060, inp32(MDP_BASE + 0x90060) | 0x1);
97 } else if ((!cursor->enable) && (cursor_enabled)) {
98 cursor_enabled = 0;
99 MDP_OUTP(MDP_BASE + 0x90060,
100 inp32(MDP_BASE + 0x90060) & (~0x1));
101 }
102
103 return 0;
104}
diff --git a/drivers/staging/msm/mdp_dma.c b/drivers/staging/msm/mdp_dma.c
new file mode 100644
index 000000000000..639918b143b4
--- /dev/null
+++ b/drivers/staging/msm/mdp_dma.c
@@ -0,0 +1,561 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/sched.h>
21#include <linux/time.h>
22#include <linux/init.h>
23#include <linux/interrupt.h>
24#include <linux/hrtimer.h>
25
26#include <mach/hardware.h>
27#include <linux/io.h>
28
29#include <asm/system.h>
30#include <asm/mach-types.h>
31#include <linux/semaphore.h>
32#include <linux/spinlock.h>
33
34#include <linux/fb.h>
35
36#include "mdp.h"
37#include "msm_fb.h"
38#include "mddihost.h"
39
40static uint32 mdp_last_dma2_update_width;
41static uint32 mdp_last_dma2_update_height;
42static uint32 mdp_curr_dma2_update_width;
43static uint32 mdp_curr_dma2_update_height;
44
45ktime_t mdp_dma2_last_update_time = { 0 };
46
47int mdp_lcd_rd_cnt_offset_slow = 20;
48int mdp_lcd_rd_cnt_offset_fast = 20;
49int mdp_vsync_usec_wait_line_too_short = 5;
50uint32 mdp_dma2_update_time_in_usec;
51uint32 mdp_total_vdopkts;
52
53extern u32 msm_fb_debug_enabled;
54extern struct workqueue_struct *mdp_dma_wq;
55
56int vsync_start_y_adjust = 4;
57
58static void mdp_dma2_update_lcd(struct msm_fb_data_type *mfd)
59{
60 MDPIBUF *iBuf = &mfd->ibuf;
61 int mddi_dest = FALSE;
62 uint32 outBpp = iBuf->bpp;
63 uint32 dma2_cfg_reg;
64 uint8 *src;
65 uint32 mddi_ld_param;
66 uint16 mddi_vdo_packet_reg;
67 struct msm_fb_panel_data *pdata =
68 (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
69 uint32 ystride = mfd->fbi->fix.line_length;
70
71 dma2_cfg_reg = DMA_PACK_TIGHT | DMA_PACK_ALIGN_LSB |
72 DMA_OUT_SEL_AHB | DMA_IBUF_NONCONTIGUOUS;
73
74#ifdef CONFIG_FB_MSM_MDP30
75 /*
76 * Software workaround: On 7x25/7x27, the MDP will not
77 * respond if dma_w is 1 pixel. Set the update width to
78 * 2 pixels and adjust the x offset if needed.
79 */
80 if (iBuf->dma_w == 1) {
81 iBuf->dma_w = 2;
82 if (iBuf->dma_x == (iBuf->ibuf_width - 2))
83 iBuf->dma_x--;
84 }
85#endif
86
87 if (mfd->fb_imgType == MDP_BGR_565)
88 dma2_cfg_reg |= DMA_PACK_PATTERN_BGR;
89 else
90 dma2_cfg_reg |= DMA_PACK_PATTERN_RGB;
91
92 if (outBpp == 4)
93 dma2_cfg_reg |= DMA_IBUF_C3ALPHA_EN;
94
95 if (outBpp == 2)
96 dma2_cfg_reg |= DMA_IBUF_FORMAT_RGB565;
97
98 mddi_ld_param = 0;
99 mddi_vdo_packet_reg = mfd->panel_info.mddi.vdopkt;
100
101 if ((mfd->panel_info.type == MDDI_PANEL) ||
102 (mfd->panel_info.type == EXT_MDDI_PANEL)) {
103 dma2_cfg_reg |= DMA_OUT_SEL_MDDI;
104 mddi_dest = TRUE;
105
106 if (mfd->panel_info.type == MDDI_PANEL) {
107 mdp_total_vdopkts++;
108 if (mfd->panel_info.pdest == DISPLAY_1) {
109 dma2_cfg_reg |= DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY;
110 mddi_ld_param = 0;
111#ifdef MDDI_HOST_WINDOW_WORKAROUND
112 mddi_window_adjust(mfd, iBuf->dma_x,
113 iBuf->dma_w - 1, iBuf->dma_y,
114 iBuf->dma_h - 1);
115#endif
116 } else {
117 dma2_cfg_reg |=
118 DMA_MDDI_DMAOUT_LCD_SEL_SECONDARY;
119 mddi_ld_param = 1;
120#ifdef MDDI_HOST_WINDOW_WORKAROUND
121 mddi_window_adjust(mfd, iBuf->dma_x,
122 iBuf->dma_w - 1, iBuf->dma_y,
123 iBuf->dma_h - 1);
124#endif
125 }
126 } else {
127 dma2_cfg_reg |= DMA_MDDI_DMAOUT_LCD_SEL_EXTERNAL;
128 mddi_ld_param = 2;
129 }
130 } else {
131 if (mfd->panel_info.pdest == DISPLAY_1) {
132 dma2_cfg_reg |= DMA_AHBM_LCD_SEL_PRIMARY;
133 outp32(MDP_EBI2_LCD0, mfd->data_port_phys);
134 } else {
135 dma2_cfg_reg |= DMA_AHBM_LCD_SEL_SECONDARY;
136 outp32(MDP_EBI2_LCD1, mfd->data_port_phys);
137 }
138 }
139
140 dma2_cfg_reg |= DMA_DITHER_EN;
141
142 src = (uint8 *) iBuf->buf;
143 /* starting input address */
144 src += iBuf->dma_x * outBpp + iBuf->dma_y * ystride;
145
146 mdp_curr_dma2_update_width = iBuf->dma_w;
147 mdp_curr_dma2_update_height = iBuf->dma_h;
148
149 /* MDP cmd block enable */
150 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
151
152#ifdef CONFIG_FB_MSM_MDP22
153 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0184,
154 (iBuf->dma_h << 16 | iBuf->dma_w));
155 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0188, src);
156 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x018C, ystride);
157#else
158 MDP_OUTP(MDP_BASE + 0x90004, (iBuf->dma_h << 16 | iBuf->dma_w));
159 MDP_OUTP(MDP_BASE + 0x90008, src);
160 MDP_OUTP(MDP_BASE + 0x9000c, ystride);
161#endif
162
163 if (mfd->panel_info.bpp == 18) {
164 dma2_cfg_reg |= DMA_DSTC0G_6BITS | /* 666 18BPP */
165 DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
166 } else {
167 dma2_cfg_reg |= DMA_DSTC0G_6BITS | /* 565 16BPP */
168 DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
169 }
170
171 if (mddi_dest) {
172#ifdef CONFIG_FB_MSM_MDP22
173 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0194,
174 (iBuf->dma_y << 16) | iBuf->dma_x);
175 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01a0, mddi_ld_param);
176 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01a4,
177 (MDDI_VDO_PACKET_DESC << 16) | mddi_vdo_packet_reg);
178#else
179 MDP_OUTP(MDP_BASE + 0x90010, (iBuf->dma_y << 16) | iBuf->dma_x);
180 MDP_OUTP(MDP_BASE + 0x00090, mddi_ld_param);
181 MDP_OUTP(MDP_BASE + 0x00094,
182 (MDDI_VDO_PACKET_DESC << 16) | mddi_vdo_packet_reg);
183#endif
184 } else {
185 /* setting EBI2 LCDC write window */
186 pdata->set_rect(iBuf->dma_x, iBuf->dma_y, iBuf->dma_w,
187 iBuf->dma_h);
188 }
189
190 /* dma2 config register */
191#ifdef MDP_HW_VSYNC
192 MDP_OUTP(MDP_BASE + 0x90000, dma2_cfg_reg);
193
194 if ((mfd->use_mdp_vsync) &&
195 (mfd->ibuf.vsync_enable) && (mfd->panel_info.lcd.vsync_enable)) {
196 uint32 start_y;
197
198 if (vsync_start_y_adjust <= iBuf->dma_y)
199 start_y = iBuf->dma_y - vsync_start_y_adjust;
200 else
201 start_y =
202 (mfd->total_lcd_lines - 1) - (vsync_start_y_adjust -
203 iBuf->dma_y);
204
205 /*
206 * MDP VSYNC clock must be On by now so, we don't have to
207 * re-enable it
208 */
209 MDP_OUTP(MDP_BASE + 0x210, start_y);
210 MDP_OUTP(MDP_BASE + 0x20c, 1); /* enable prim vsync */
211 } else {
212 MDP_OUTP(MDP_BASE + 0x20c, 0); /* disable prim vsync */
213 }
214#else
215#ifdef CONFIG_FB_MSM_MDP22
216 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0180, dma2_cfg_reg);
217#else
218 MDP_OUTP(MDP_BASE + 0x90000, dma2_cfg_reg);
219#endif
220#endif /* MDP_HW_VSYNC */
221
222 /* MDP cmd block disable */
223 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
224}
225
226static ktime_t vt = { 0 };
227int mdp_usec_diff_threshold = 100;
228int mdp_expected_usec_wait;
229
230enum hrtimer_restart mdp_dma2_vsync_hrtimer_handler(struct hrtimer *ht)
231{
232 struct msm_fb_data_type *mfd = NULL;
233
234 mfd = container_of(ht, struct msm_fb_data_type, dma_hrtimer);
235
236 mdp_pipe_kickoff(MDP_DMA2_TERM, mfd);
237
238 if (msm_fb_debug_enabled) {
239 ktime_t t;
240 int usec_diff;
241 int actual_wait;
242
243 t = ktime_get_real();
244
245 actual_wait =
246 (t.tv.sec - vt.tv.sec) * 1000000 + (t.tv.nsec -
247 vt.tv.nsec) / 1000;
248 usec_diff = actual_wait - mdp_expected_usec_wait;
249
250 if ((mdp_usec_diff_threshold < usec_diff) || (usec_diff < 0))
251 MSM_FB_DEBUG
252 ("HRT Diff = %d usec Exp=%d usec Act=%d usec\n",
253 usec_diff, mdp_expected_usec_wait, actual_wait);
254 }
255
256 return HRTIMER_NORESTART;
257}
258
259static void mdp_dma_schedule(struct msm_fb_data_type *mfd, uint32 term)
260{
261 /*
262 * dma2 configure VSYNC block
263 * vsync supported on Primary LCD only for now
264 */
265 int32 mdp_lcd_rd_cnt;
266 uint32 usec_wait_time;
267 uint32 start_y;
268
269 /*
270 * ToDo: if we can move HRT timer callback to workqueue, we can
271 * move DMA2 power on under mdp_pipe_kickoff().
272 * This will save a power for hrt time wait.
273 * However if the latency for context switch (hrt irq -> workqueue)
274 * is too big, we will miss the vsync timing.
275 */
276 if (term == MDP_DMA2_TERM)
277 mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
278
279 mdp_dma2_update_time_in_usec =
280 MDP_KTIME2USEC(mdp_dma2_last_update_time);
281
282 if ((!mfd->ibuf.vsync_enable) || (!mfd->panel_info.lcd.vsync_enable)
283 || (mfd->use_mdp_vsync)) {
284 mdp_pipe_kickoff(term, mfd);
285 return;
286 }
287 /* SW vsync logic starts here */
288
289 /* get current rd counter */
290 mdp_lcd_rd_cnt = mdp_get_lcd_line_counter(mfd);
291 if (mdp_dma2_update_time_in_usec != 0) {
292 uint32 num, den;
293
294 /*
295 * roi width boundary calculation to know the size of pixel
296 * width that MDP can send faster or slower than LCD read
297 * pointer
298 */
299
300 num = mdp_last_dma2_update_width * mdp_last_dma2_update_height;
301 den =
302 (((mfd->panel_info.lcd.refx100 * mfd->total_lcd_lines) /
303 1000) * (mdp_dma2_update_time_in_usec / 100)) / 1000;
304
305 if (den == 0)
306 mfd->vsync_width_boundary[mdp_last_dma2_update_width] =
307 mfd->panel_info.xres + 1;
308 else
309 mfd->vsync_width_boundary[mdp_last_dma2_update_width] =
310 (int)(num / den);
311 }
312
313 if (mfd->vsync_width_boundary[mdp_last_dma2_update_width] >
314 mdp_curr_dma2_update_width) {
315 /* MDP wrp is faster than LCD rdp */
316 mdp_lcd_rd_cnt += mdp_lcd_rd_cnt_offset_fast;
317 } else {
318 /* MDP wrp is slower than LCD rdp */
319 mdp_lcd_rd_cnt -= mdp_lcd_rd_cnt_offset_slow;
320 }
321
322 if (mdp_lcd_rd_cnt < 0)
323 mdp_lcd_rd_cnt = mfd->total_lcd_lines + mdp_lcd_rd_cnt;
324 else if (mdp_lcd_rd_cnt > mfd->total_lcd_lines)
325 mdp_lcd_rd_cnt = mdp_lcd_rd_cnt - mfd->total_lcd_lines - 1;
326
327 /* get wrt pointer position */
328 start_y = mfd->ibuf.dma_y;
329
330 /* measure line difference between start_y and rd counter */
331 if (start_y > mdp_lcd_rd_cnt) {
332 /*
333 * *100 for lcd_ref_hzx100 was already multiplied by 100
334 * *1000000 is for usec conversion
335 */
336
337 if ((start_y - mdp_lcd_rd_cnt) <=
338 mdp_vsync_usec_wait_line_too_short)
339 usec_wait_time = 0;
340 else
341 usec_wait_time =
342 ((start_y -
343 mdp_lcd_rd_cnt) * 1000000) /
344 ((mfd->total_lcd_lines *
345 mfd->panel_info.lcd.refx100) / 100);
346 } else {
347 if ((start_y + (mfd->total_lcd_lines - mdp_lcd_rd_cnt)) <=
348 mdp_vsync_usec_wait_line_too_short)
349 usec_wait_time = 0;
350 else
351 usec_wait_time =
352 ((start_y +
353 (mfd->total_lcd_lines -
354 mdp_lcd_rd_cnt)) * 1000000) /
355 ((mfd->total_lcd_lines *
356 mfd->panel_info.lcd.refx100) / 100);
357 }
358
359 mdp_last_dma2_update_width = mdp_curr_dma2_update_width;
360 mdp_last_dma2_update_height = mdp_curr_dma2_update_height;
361
362 if (usec_wait_time == 0) {
363 mdp_pipe_kickoff(term, mfd);
364 } else {
365 ktime_t wait_time;
366
367 wait_time.tv.sec = 0;
368 wait_time.tv.nsec = usec_wait_time * 1000;
369
370 if (msm_fb_debug_enabled) {
371 vt = ktime_get_real();
372 mdp_expected_usec_wait = usec_wait_time;
373 }
374 hrtimer_start(&mfd->dma_hrtimer, wait_time, HRTIMER_MODE_REL);
375 }
376}
377
378#ifdef MDDI_HOST_WINDOW_WORKAROUND
379void mdp_dma2_update(struct msm_fb_data_type *mfd)
380{
381 MDPIBUF *iBuf;
382 uint32 upper_height;
383
384 if (mfd->panel.type == EXT_MDDI_PANEL) {
385 mdp_dma2_update_sub(mfd);
386 return;
387 }
388
389 iBuf = &mfd->ibuf;
390
391 upper_height =
392 (uint32) mddi_assign_pkt_height((uint16) iBuf->dma_w,
393 (uint16) iBuf->dma_h, 18);
394
395 if (upper_height >= iBuf->dma_h) {
396 mdp_dma2_update_sub(mfd);
397 } else {
398 MDPIBUF lower_height;
399
400 /* sending the upper region first */
401 lower_height = iBuf->dma_h - upper_height;
402 iBuf->dma_h = upper_height;
403 mdp_dma2_update_sub(mfd);
404
405 /* sending the lower region second */
406 iBuf->dma_h = lower_height;
407 iBuf->dma_y += lower_height;
408 iBuf->vsync_enable = FALSE;
409 mdp_dma2_update_sub(mfd);
410 }
411}
412
413void mdp_dma2_update_sub(struct msm_fb_data_type *mfd)
414#else
415void mdp_dma2_update(struct msm_fb_data_type *mfd)
416#endif
417{
418 down(&mfd->dma->mutex);
419 if ((mfd) && (!mfd->dma->busy) && (mfd->panel_power_on)) {
420 down(&mfd->sem);
421 mfd->ibuf_flushed = TRUE;
422 mdp_dma2_update_lcd(mfd);
423
424 mdp_enable_irq(MDP_DMA2_TERM);
425 mfd->dma->busy = TRUE;
426 INIT_COMPLETION(mfd->dma->comp);
427
428 /* schedule DMA to start */
429 mdp_dma_schedule(mfd, MDP_DMA2_TERM);
430 up(&mfd->sem);
431
432 /* wait until DMA finishes the current job */
433 wait_for_completion_killable(&mfd->dma->comp);
434 mdp_disable_irq(MDP_DMA2_TERM);
435
436 /* signal if pan function is waiting for the update completion */
437 if (mfd->pan_waiting) {
438 mfd->pan_waiting = FALSE;
439 complete(&mfd->pan_comp);
440 }
441 }
442 up(&mfd->dma->mutex);
443}
444
445void mdp_lcd_update_workqueue_handler(struct work_struct *work)
446{
447 struct msm_fb_data_type *mfd = NULL;
448
449 mfd = container_of(work, struct msm_fb_data_type, dma_update_worker);
450 if (mfd)
451 mfd->dma_fnc(mfd);
452}
453
454void mdp_set_dma_pan_info(struct fb_info *info, struct mdp_dirty_region *dirty,
455 boolean sync)
456{
457 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
458 MDPIBUF *iBuf;
459 int bpp = info->var.bits_per_pixel / 8;
460
461 down(&mfd->sem);
462 iBuf = &mfd->ibuf;
463 iBuf->buf = (uint8 *) info->fix.smem_start;
464 iBuf->buf += info->var.xoffset * bpp +
465 info->var.yoffset * info->fix.line_length;
466
467 iBuf->ibuf_width = info->var.xres_virtual;
468 iBuf->bpp = bpp;
469
470 iBuf->vsync_enable = sync;
471
472 if (dirty) {
473 /*
474 * ToDo: dirty region check inside var.xoffset+xres
475 * <-> var.yoffset+yres
476 */
477 iBuf->dma_x = dirty->xoffset % info->var.xres;
478 iBuf->dma_y = dirty->yoffset % info->var.yres;
479 iBuf->dma_w = dirty->width;
480 iBuf->dma_h = dirty->height;
481 } else {
482 iBuf->dma_x = 0;
483 iBuf->dma_y = 0;
484 iBuf->dma_w = info->var.xres;
485 iBuf->dma_h = info->var.yres;
486 }
487 mfd->ibuf_flushed = FALSE;
488 up(&mfd->sem);
489}
490
491void mdp_set_offset_info(struct fb_info *info, uint32 addr, uint32 sync)
492{
493 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
494 MDPIBUF *iBuf;
495
496 int bpp = info->var.bits_per_pixel / 8;
497
498 down(&mfd->sem);
499 iBuf = &mfd->ibuf;
500 iBuf->ibuf_width = info->var.xres_virtual;
501 iBuf->bpp = bpp;
502 iBuf->vsync_enable = sync;
503 iBuf->dma_x = 0;
504 iBuf->dma_y = 0;
505 iBuf->dma_w = info->var.xres;
506 iBuf->dma_h = info->var.yres;
507 iBuf->buf = (uint8 *) addr;
508
509 mfd->ibuf_flushed = FALSE;
510 up(&mfd->sem);
511}
512
513void mdp_dma_pan_update(struct fb_info *info)
514{
515 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
516 MDPIBUF *iBuf;
517
518 iBuf = &mfd->ibuf;
519
520 if (mfd->sw_currently_refreshing) {
521 /* we need to wait for the pending update */
522 mfd->pan_waiting = TRUE;
523 if (!mfd->ibuf_flushed) {
524 wait_for_completion_killable(&mfd->pan_comp);
525 }
526 /* waiting for this update to complete */
527 mfd->pan_waiting = TRUE;
528 wait_for_completion_killable(&mfd->pan_comp);
529 } else
530 mfd->dma_fnc(mfd);
531}
532
533void mdp_refresh_screen(unsigned long data)
534{
535 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)data;
536
537 if ((mfd->sw_currently_refreshing) && (mfd->sw_refreshing_enable)) {
538 init_timer(&mfd->refresh_timer);
539 mfd->refresh_timer.function = mdp_refresh_screen;
540 mfd->refresh_timer.data = data;
541
542 if (mfd->dma->busy)
543 /* come back in 1 msec */
544 mfd->refresh_timer.expires = jiffies + (HZ / 1000);
545 else
546 mfd->refresh_timer.expires =
547 jiffies + mfd->refresh_timer_duration;
548
549 add_timer(&mfd->refresh_timer);
550
551 if (!mfd->dma->busy) {
552 if (!queue_work(mdp_dma_wq, &mfd->dma_update_worker)) {
553 MSM_FB_DEBUG("mdp_dma: can't queue_work! -> \
554 MDP/MDDI/LCD clock speed needs to be increased\n");
555 }
556 }
557 } else {
558 if (!mfd->hw_refresh)
559 complete(&mfd->refresher_comp);
560 }
561}
diff --git a/drivers/staging/msm/mdp_dma_lcdc.c b/drivers/staging/msm/mdp_dma_lcdc.c
new file mode 100644
index 000000000000..b57fa1a0ceb0
--- /dev/null
+++ b/drivers/staging/msm/mdp_dma_lcdc.c
@@ -0,0 +1,379 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/sched.h>
21#include <linux/time.h>
22#include <linux/init.h>
23#include <linux/interrupt.h>
24#include <linux/hrtimer.h>
25#include <linux/delay.h>
26#include <mach/hardware.h>
27#include <linux/io.h>
28
29#include <asm/system.h>
30#include <asm/mach-types.h>
31#include <linux/semaphore.h>
32#include <linux/spinlock.h>
33
34#include <linux/fb.h>
35
36#include "mdp.h"
37#include "msm_fb.h"
38#include "mdp4.h"
39
40#ifdef CONFIG_FB_MSM_MDP40
41#define LCDC_BASE 0xC0000
42#define DTV_BASE 0xD0000
43#define DMA_E_BASE 0xB0000
44#else
45#define LCDC_BASE 0xE0000
46#endif
47
48#define DMA_P_BASE 0x90000
49
50extern spinlock_t mdp_spin_lock;
51#ifndef CONFIG_FB_MSM_MDP40
52extern uint32 mdp_intr_mask;
53#endif
54
55int first_pixel_start_x;
56int first_pixel_start_y;
57
58int mdp_lcdc_on(struct platform_device *pdev)
59{
60 int lcdc_width;
61 int lcdc_height;
62 int lcdc_bpp;
63 int lcdc_border_clr;
64 int lcdc_underflow_clr;
65 int lcdc_hsync_skew;
66
67 int hsync_period;
68 int hsync_ctrl;
69 int vsync_period;
70 int display_hctl;
71 int display_v_start;
72 int display_v_end;
73 int active_hctl;
74 int active_h_start;
75 int active_h_end;
76 int active_v_start;
77 int active_v_end;
78 int ctrl_polarity;
79 int h_back_porch;
80 int h_front_porch;
81 int v_back_porch;
82 int v_front_porch;
83 int hsync_pulse_width;
84 int vsync_pulse_width;
85 int hsync_polarity;
86 int vsync_polarity;
87 int data_en_polarity;
88 int hsync_start_x;
89 int hsync_end_x;
90 uint8 *buf;
91 int bpp;
92 uint32 dma2_cfg_reg;
93 struct fb_info *fbi;
94 struct fb_var_screeninfo *var;
95 struct msm_fb_data_type *mfd;
96 uint32 dma_base;
97 uint32 timer_base = LCDC_BASE;
98 uint32 block = MDP_DMA2_BLOCK;
99 int ret;
100
101 mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
102
103 if (!mfd)
104 return -ENODEV;
105
106 if (mfd->key != MFD_KEY)
107 return -EINVAL;
108
109 fbi = mfd->fbi;
110 var = &fbi->var;
111
112 /* MDP cmd block enable */
113 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
114
115 bpp = fbi->var.bits_per_pixel / 8;
116 buf = (uint8 *) fbi->fix.smem_start;
117 buf += fbi->var.xoffset * bpp + fbi->var.yoffset * fbi->fix.line_length;
118
119 dma2_cfg_reg = DMA_PACK_ALIGN_LSB | DMA_DITHER_EN | DMA_OUT_SEL_LCDC;
120
121 if (mfd->fb_imgType == MDP_BGR_565)
122 dma2_cfg_reg |= DMA_PACK_PATTERN_BGR;
123 else
124 dma2_cfg_reg |= DMA_PACK_PATTERN_RGB;
125
126 if (bpp == 2)
127 dma2_cfg_reg |= DMA_IBUF_FORMAT_RGB565;
128 else if (bpp == 3)
129 dma2_cfg_reg |= DMA_IBUF_FORMAT_RGB888;
130 else
131 dma2_cfg_reg |= DMA_IBUF_FORMAT_xRGB8888_OR_ARGB8888;
132
133 switch (mfd->panel_info.bpp) {
134 case 24:
135 dma2_cfg_reg |= DMA_DSTC0G_8BITS |
136 DMA_DSTC1B_8BITS | DMA_DSTC2R_8BITS;
137 break;
138
139 case 18:
140 dma2_cfg_reg |= DMA_DSTC0G_6BITS |
141 DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
142 break;
143
144 case 16:
145 dma2_cfg_reg |= DMA_DSTC0G_6BITS |
146 DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
147 break;
148
149 default:
150 printk(KERN_ERR "mdp lcdc can't support format %d bpp!\n",
151 mfd->panel_info.bpp);
152 return -ENODEV;
153 }
154
155 /* DMA register config */
156
157 dma_base = DMA_P_BASE;
158
159#ifdef CONFIG_FB_MSM_MDP40
160 if (mfd->panel.type == HDMI_PANEL)
161 dma_base = DMA_E_BASE;
162#endif
163
164 /* starting address */
165 MDP_OUTP(MDP_BASE + dma_base + 0x8, (uint32) buf);
166 /* active window width and height */
167 MDP_OUTP(MDP_BASE + dma_base + 0x4, ((fbi->var.yres) << 16) |
168 (fbi->var.xres));
169 /* buffer ystride */
170 MDP_OUTP(MDP_BASE + dma_base + 0xc, fbi->fix.line_length);
171 /* x/y coordinate = always 0 for lcdc */
172 MDP_OUTP(MDP_BASE + dma_base + 0x10, 0);
173 /* dma config */
174 MDP_OUTP(MDP_BASE + dma_base, dma2_cfg_reg);
175
176 /*
177 * LCDC timing setting
178 */
179 h_back_porch = var->left_margin;
180 h_front_porch = var->right_margin;
181 v_back_porch = var->upper_margin;
182 v_front_porch = var->lower_margin;
183 hsync_pulse_width = var->hsync_len;
184 vsync_pulse_width = var->vsync_len;
185 lcdc_border_clr = mfd->panel_info.lcdc.border_clr;
186 lcdc_underflow_clr = mfd->panel_info.lcdc.underflow_clr;
187 lcdc_hsync_skew = mfd->panel_info.lcdc.hsync_skew;
188
189 lcdc_width = mfd->panel_info.xres;
190 lcdc_height = mfd->panel_info.yres;
191 lcdc_bpp = mfd->panel_info.bpp;
192
193 hsync_period =
194 hsync_pulse_width + h_back_porch + lcdc_width + h_front_porch;
195 hsync_ctrl = (hsync_period << 16) | hsync_pulse_width;
196 hsync_start_x = hsync_pulse_width + h_back_porch;
197 hsync_end_x = hsync_period - h_front_porch - 1;
198 display_hctl = (hsync_end_x << 16) | hsync_start_x;
199
200 vsync_period =
201 (vsync_pulse_width + v_back_porch + lcdc_height +
202 v_front_porch) * hsync_period;
203 display_v_start =
204 (vsync_pulse_width + v_back_porch) * hsync_period + lcdc_hsync_skew;
205 display_v_end =
206 vsync_period - (v_front_porch * hsync_period) + lcdc_hsync_skew - 1;
207
208 if (lcdc_width != var->xres) {
209 active_h_start = hsync_start_x + first_pixel_start_x;
210 active_h_end = active_h_start + var->xres - 1;
211 active_hctl =
212 ACTIVE_START_X_EN | (active_h_end << 16) | active_h_start;
213 } else {
214 active_hctl = 0;
215 }
216
217 if (lcdc_height != var->yres) {
218 active_v_start =
219 display_v_start + first_pixel_start_y * hsync_period;
220 active_v_end = active_v_start + (var->yres) * hsync_period - 1;
221 active_v_start |= ACTIVE_START_Y_EN;
222 } else {
223 active_v_start = 0;
224 active_v_end = 0;
225 }
226
227
228#ifdef CONFIG_FB_MSM_MDP40
229 if (mfd->panel.type == HDMI_PANEL) {
230 block = MDP_DMA_E_BLOCK;
231 timer_base = DTV_BASE;
232 hsync_polarity = 0;
233 vsync_polarity = 0;
234 } else {
235 hsync_polarity = 1;
236 vsync_polarity = 1;
237 }
238
239 lcdc_underflow_clr |= 0x80000000; /* enable recovery */
240#else
241 hsync_polarity = 0;
242 vsync_polarity = 0;
243#endif
244 data_en_polarity = 0;
245
246 ctrl_polarity =
247 (data_en_polarity << 2) | (vsync_polarity << 1) | (hsync_polarity);
248
249 MDP_OUTP(MDP_BASE + timer_base + 0x4, hsync_ctrl);
250 MDP_OUTP(MDP_BASE + timer_base + 0x8, vsync_period);
251 MDP_OUTP(MDP_BASE + timer_base + 0xc, vsync_pulse_width * hsync_period);
252 if (timer_base == LCDC_BASE) {
253 MDP_OUTP(MDP_BASE + timer_base + 0x10, display_hctl);
254 MDP_OUTP(MDP_BASE + timer_base + 0x14, display_v_start);
255 MDP_OUTP(MDP_BASE + timer_base + 0x18, display_v_end);
256 MDP_OUTP(MDP_BASE + timer_base + 0x28, lcdc_border_clr);
257 MDP_OUTP(MDP_BASE + timer_base + 0x2c, lcdc_underflow_clr);
258 MDP_OUTP(MDP_BASE + timer_base + 0x30, lcdc_hsync_skew);
259 MDP_OUTP(MDP_BASE + timer_base + 0x38, ctrl_polarity);
260 MDP_OUTP(MDP_BASE + timer_base + 0x1c, active_hctl);
261 MDP_OUTP(MDP_BASE + timer_base + 0x20, active_v_start);
262 MDP_OUTP(MDP_BASE + timer_base + 0x24, active_v_end);
263 } else {
264 MDP_OUTP(MDP_BASE + timer_base + 0x18, display_hctl);
265 MDP_OUTP(MDP_BASE + timer_base + 0x1c, display_v_start);
266 MDP_OUTP(MDP_BASE + timer_base + 0x20, display_v_end);
267 MDP_OUTP(MDP_BASE + timer_base + 0x40, lcdc_border_clr);
268 MDP_OUTP(MDP_BASE + timer_base + 0x44, lcdc_underflow_clr);
269 MDP_OUTP(MDP_BASE + timer_base + 0x48, lcdc_hsync_skew);
270 MDP_OUTP(MDP_BASE + timer_base + 0x50, ctrl_polarity);
271 MDP_OUTP(MDP_BASE + timer_base + 0x2c, active_hctl);
272 MDP_OUTP(MDP_BASE + timer_base + 0x30, active_v_start);
273 MDP_OUTP(MDP_BASE + timer_base + 0x38, active_v_end);
274 }
275
276 ret = panel_next_on(pdev);
277 if (ret == 0) {
278 /* enable LCDC block */
279 MDP_OUTP(MDP_BASE + timer_base, 1);
280 mdp_pipe_ctrl(block, MDP_BLOCK_POWER_ON, FALSE);
281 }
282 /* MDP cmd block disable */
283 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
284
285 return ret;
286}
287
288int mdp_lcdc_off(struct platform_device *pdev)
289{
290 int ret = 0;
291 struct msm_fb_data_type *mfd;
292 uint32 timer_base = LCDC_BASE;
293 uint32 block = MDP_DMA2_BLOCK;
294
295 mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
296
297#ifdef CONFIG_FB_MSM_MDP40
298 if (mfd->panel.type == HDMI_PANEL) {
299 block = MDP_DMA_E_BLOCK;
300 timer_base = DTV_BASE;
301 }
302#endif
303
304 /* MDP cmd block enable */
305 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
306 MDP_OUTP(MDP_BASE + timer_base, 0);
307 /* MDP cmd block disable */
308 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
309 mdp_pipe_ctrl(block, MDP_BLOCK_POWER_OFF, FALSE);
310
311 ret = panel_next_off(pdev);
312
313 /* delay to make sure the last frame finishes */
314 mdelay(100);
315
316 return ret;
317}
318
319void mdp_lcdc_update(struct msm_fb_data_type *mfd)
320{
321 struct fb_info *fbi = mfd->fbi;
322 uint8 *buf;
323 int bpp;
324 unsigned long flag;
325 uint32 dma_base;
326 int irq_block = MDP_DMA2_TERM;
327#ifdef CONFIG_FB_MSM_MDP40
328 int intr = INTR_DMA_P_DONE;
329#endif
330
331 if (!mfd->panel_power_on)
332 return;
333
334 /* no need to power on cmd block since it's lcdc mode */
335
336 if (!mfd->ibuf.visible_swapped) {
337 bpp = fbi->var.bits_per_pixel / 8;
338 buf = (uint8 *) fbi->fix.smem_start;
339 buf += fbi->var.xoffset * bpp +
340 fbi->var.yoffset * fbi->fix.line_length;
341 } else {
342 /* we've done something to update the pointer. */
343 bpp = mfd->ibuf.bpp;
344 buf = mfd->ibuf.buf;
345 }
346
347 dma_base = DMA_P_BASE;
348
349#ifdef CONFIG_FB_MSM_MDP40
350 if (mfd->panel.type == HDMI_PANEL) {
351 intr = INTR_DMA_E_DONE;
352 irq_block = MDP_DMA_E_TERM;
353 dma_base = DMA_E_BASE;
354 }
355#endif
356
357 /* starting address */
358 MDP_OUTP(MDP_BASE + dma_base + 0x8, (uint32) buf);
359
360 /* enable LCDC irq */
361 spin_lock_irqsave(&mdp_spin_lock, flag);
362 mdp_enable_irq(irq_block);
363 INIT_COMPLETION(mfd->dma->comp);
364 mfd->dma->waiting = TRUE;
365#ifdef CONFIG_FB_MSM_MDP40
366 outp32(MDP_INTR_CLEAR, intr);
367 mdp_intr_mask |= intr;
368 outp32(MDP_INTR_ENABLE, mdp_intr_mask);
369#else
370 outp32(MDP_INTR_CLEAR, LCDC_FRAME_START);
371 mdp_intr_mask |= LCDC_FRAME_START;
372 outp32(MDP_INTR_ENABLE, mdp_intr_mask);
373#endif
374 spin_unlock_irqrestore(&mdp_spin_lock, flag);
375
376 if (mfd->ibuf.vsync_enable)
377 wait_for_completion_killable(&mfd->dma->comp);
378 mdp_disable_irq(irq_block);
379}
diff --git a/drivers/staging/msm/mdp_dma_s.c b/drivers/staging/msm/mdp_dma_s.c
new file mode 100644
index 000000000000..0c34a1010f17
--- /dev/null
+++ b/drivers/staging/msm/mdp_dma_s.c
@@ -0,0 +1,139 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/sched.h>
21#include <linux/time.h>
22#include <linux/init.h>
23#include <linux/interrupt.h>
24#include <linux/hrtimer.h>
25
26#include <mach/hardware.h>
27#include <linux/io.h>
28
29#include <asm/system.h>
30#include <asm/mach-types.h>
31#include <linux/semaphore.h>
32#include <linux/spinlock.h>
33
34#include <linux/fb.h>
35
36#include "mdp.h"
37#include "msm_fb.h"
38
39static void mdp_dma_s_update_lcd(struct msm_fb_data_type *mfd)
40{
41 MDPIBUF *iBuf = &mfd->ibuf;
42 int mddi_dest = FALSE;
43 uint32 outBpp = iBuf->bpp;
44 uint32 dma_s_cfg_reg;
45 uint8 *src;
46 struct msm_fb_panel_data *pdata =
47 (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
48
49 dma_s_cfg_reg = DMA_PACK_TIGHT | DMA_PACK_ALIGN_LSB |
50 DMA_OUT_SEL_AHB | DMA_IBUF_NONCONTIGUOUS;
51
52 if (mfd->fb_imgType == MDP_BGR_565)
53 dma_s_cfg_reg |= DMA_PACK_PATTERN_BGR;
54 else
55 dma_s_cfg_reg |= DMA_PACK_PATTERN_RGB;
56
57 if (outBpp == 4)
58 dma_s_cfg_reg |= DMA_IBUF_C3ALPHA_EN;
59
60 if (outBpp == 2)
61 dma_s_cfg_reg |= DMA_IBUF_FORMAT_RGB565;
62
63 if (mfd->panel_info.pdest != DISPLAY_2) {
64 printk(KERN_ERR "error: non-secondary type through dma_s!\n");
65 return;
66 }
67
68 if (mfd->panel_info.type == MDDI_PANEL) {
69 dma_s_cfg_reg |= DMA_OUT_SEL_MDDI;
70 mddi_dest = TRUE;
71 } else {
72 dma_s_cfg_reg |= DMA_AHBM_LCD_SEL_SECONDARY;
73 outp32(MDP_EBI2_LCD1, mfd->data_port_phys);
74 }
75
76 dma_s_cfg_reg |= DMA_DITHER_EN;
77
78 src = (uint8 *) iBuf->buf;
79 /* starting input address */
80 src += (iBuf->dma_x + iBuf->dma_y * iBuf->ibuf_width) * outBpp;
81
82 /* MDP cmd block enable */
83 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
84 /* PIXELSIZE */
85 MDP_OUTP(MDP_BASE + 0xa0004, (iBuf->dma_h << 16 | iBuf->dma_w));
86 MDP_OUTP(MDP_BASE + 0xa0008, src); /* ibuf address */
87 MDP_OUTP(MDP_BASE + 0xa000c, iBuf->ibuf_width * outBpp);/* ystride */
88
89 if (mfd->panel_info.bpp == 18) {
90 dma_s_cfg_reg |= DMA_DSTC0G_6BITS | /* 666 18BPP */
91 DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
92 } else {
93 dma_s_cfg_reg |= DMA_DSTC0G_6BITS | /* 565 16BPP */
94 DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
95 }
96
97 if (mddi_dest) {
98 MDP_OUTP(MDP_BASE + 0xa0010, (iBuf->dma_y << 16) | iBuf->dma_x);
99 MDP_OUTP(MDP_BASE + 0x00090, 1);
100 MDP_OUTP(MDP_BASE + 0x00094,
101 (MDDI_VDO_PACKET_DESC << 16) |
102 mfd->panel_info.mddi.vdopkt);
103 } else {
104 /* setting LCDC write window */
105 pdata->set_rect(iBuf->dma_x, iBuf->dma_y, iBuf->dma_w,
106 iBuf->dma_h);
107 }
108
109 MDP_OUTP(MDP_BASE + 0xa0000, dma_s_cfg_reg);
110
111 /* MDP cmd block disable */
112 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
113 mdp_pipe_kickoff(MDP_DMA_S_TERM, mfd);
114}
115
116void mdp_dma_s_update(struct msm_fb_data_type *mfd)
117{
118 down(&mfd->dma->mutex);
119 if ((mfd) && (!mfd->dma->busy) && (mfd->panel_power_on)) {
120 down(&mfd->sem);
121 mdp_enable_irq(MDP_DMA_S_TERM);
122 mfd->dma->busy = TRUE;
123 INIT_COMPLETION(mfd->dma->comp);
124 mfd->ibuf_flushed = TRUE;
125 mdp_dma_s_update_lcd(mfd);
126 up(&mfd->sem);
127
128 /* wait until DMA finishes the current job */
129 wait_for_completion_killable(&mfd->dma->comp);
130 mdp_disable_irq(MDP_DMA_S_TERM);
131
132 /* signal if pan function is waiting for the update completion */
133 if (mfd->pan_waiting) {
134 mfd->pan_waiting = FALSE;
135 complete(&mfd->pan_comp);
136 }
137 }
138 up(&mfd->dma->mutex);
139}
diff --git a/drivers/staging/msm/mdp_dma_tv.c b/drivers/staging/msm/mdp_dma_tv.c
new file mode 100644
index 000000000000..70989fb32c1d
--- /dev/null
+++ b/drivers/staging/msm/mdp_dma_tv.c
@@ -0,0 +1,142 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/sched.h>
21#include <linux/time.h>
22#include <linux/init.h>
23#include <linux/interrupt.h>
24#include <linux/hrtimer.h>
25#include <linux/delay.h>
26
27#include <mach/hardware.h>
28#include <linux/io.h>
29
30#include <asm/system.h>
31#include <asm/mach-types.h>
32#include <linux/semaphore.h>
33#include <linux/spinlock.h>
34
35#include <linux/fb.h>
36
37#include "mdp.h"
38#include "msm_fb.h"
39
40extern spinlock_t mdp_spin_lock;
41extern uint32 mdp_intr_mask;
42
43int mdp_dma3_on(struct platform_device *pdev)
44{
45 struct msm_fb_data_type *mfd;
46 struct fb_info *fbi;
47 uint8 *buf;
48 int bpp;
49 int ret = 0;
50
51 mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
52
53 if (!mfd)
54 return -ENODEV;
55
56 if (mfd->key != MFD_KEY)
57 return -EINVAL;
58
59 fbi = mfd->fbi;
60 /* MDP cmd block enable */
61 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
62
63 bpp = fbi->var.bits_per_pixel / 8;
64 buf = (uint8 *) fbi->fix.smem_start;
65 buf += fbi->var.xoffset * bpp +
66 fbi->var.yoffset * fbi->fix.line_length;
67
68 /* starting address[31..8] of Video frame buffer is CS0 */
69 MDP_OUTP(MDP_BASE + 0xC0008, (uint32) buf >> 3);
70
71 mdp_pipe_ctrl(MDP_DMA3_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
72
73 MDP_OUTP(MDP_BASE + 0xC0004, 0x4c60674); /* flicker filter enabled */
74 MDP_OUTP(MDP_BASE + 0xC0010, 0x20); /* sobel treshold */
75
76 MDP_OUTP(MDP_BASE + 0xC0018, 0xeb0010); /* Y Max, Y min */
77 MDP_OUTP(MDP_BASE + 0xC001C, 0xf00010); /* Cb Max, Cb min */
78 MDP_OUTP(MDP_BASE + 0xC0020, 0xf00010); /* Cb Max, Cb min */
79
80 MDP_OUTP(MDP_BASE + 0xC000C, 0x67686970); /* add a few chars for CC */
81 MDP_OUTP(MDP_BASE + 0xC0000, 0x1); /* MDP tv out enable */
82
83 /* MDP cmd block disable */
84 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
85
86 ret = panel_next_on(pdev);
87
88 return ret;
89}
90
91int mdp_dma3_off(struct platform_device *pdev)
92{
93 int ret = 0;
94
95 ret = panel_next_off(pdev);
96 if (ret)
97 return ret;
98
99 /* MDP cmd block enable */
100 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
101 MDP_OUTP(MDP_BASE + 0xC0000, 0x0);
102 /* MDP cmd block disable */
103 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
104
105 mdp_pipe_ctrl(MDP_DMA3_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
106
107 /* delay to make sure the last frame finishes */
108 mdelay(100);
109
110 return ret;
111}
112
113void mdp_dma3_update(struct msm_fb_data_type *mfd)
114{
115 struct fb_info *fbi = mfd->fbi;
116 uint8 *buf;
117 int bpp;
118 unsigned long flag;
119
120 if (!mfd->panel_power_on)
121 return;
122
123 /* no need to power on cmd block since dma3 is running */
124 bpp = fbi->var.bits_per_pixel / 8;
125 buf = (uint8 *) fbi->fix.smem_start;
126 buf += fbi->var.xoffset * bpp +
127 fbi->var.yoffset * fbi->fix.line_length;
128 MDP_OUTP(MDP_BASE + 0xC0008, (uint32) buf >> 3);
129
130 spin_lock_irqsave(&mdp_spin_lock, flag);
131 mdp_enable_irq(MDP_DMA3_TERM);
132 INIT_COMPLETION(mfd->dma->comp);
133 mfd->dma->waiting = TRUE;
134
135 outp32(MDP_INTR_CLEAR, TV_OUT_DMA3_START);
136 mdp_intr_mask |= TV_OUT_DMA3_START;
137 outp32(MDP_INTR_ENABLE, mdp_intr_mask);
138 spin_unlock_irqrestore(&mdp_spin_lock, flag);
139
140 wait_for_completion_killable(&mfd->dma->comp);
141 mdp_disable_irq(MDP_DMA3_TERM);
142}
diff --git a/drivers/staging/msm/mdp_hw_init.c b/drivers/staging/msm/mdp_hw_init.c
new file mode 100644
index 000000000000..807362ac592c
--- /dev/null
+++ b/drivers/staging/msm/mdp_hw_init.c
@@ -0,0 +1,720 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include "mdp.h"
19
20/* mdp primary csc limit vector */
21uint32 mdp_plv[] = { 0x10, 0xeb, 0x10, 0xf0 };
22
23/* Color Coefficient matrix for YUV -> RGB */
24struct mdp_ccs mdp_ccs_yuv2rgb = {
25 MDP_CCS_YUV2RGB,
26 {
27 0x254,
28 0x000,
29 0x331,
30 0x254,
31 0xff38,
32 0xfe61,
33 0x254,
34 0x409,
35 0x000,
36 },
37 {
38#ifdef CONFIG_FB_MSM_MDP31
39 0x1f0,
40 0x180,
41 0x180
42#else
43 0x10,
44 0x80,
45 0x80
46#endif
47 }
48};
49
50/* Color Coefficient matrix for RGB -> YUV */
51struct mdp_ccs mdp_ccs_rgb2yuv = {
52 MDP_CCS_RGB2YUV,
53 {
54 0x83,
55 0x102,
56 0x32,
57 0xffb5,
58 0xff6c,
59 0xe1,
60 0xe1,
61 0xff45,
62 0xffdc,
63 },
64#ifdef CONFIG_FB_MSM_MDP31
65 {
66 0x10,
67 0x80,
68 0x80
69 }
70#endif
71};
72
73static void mdp_load_lut_param(void)
74{
75 outpdw(MDP_BASE + 0x40800, 0x0);
76 outpdw(MDP_BASE + 0x40804, 0x151515);
77 outpdw(MDP_BASE + 0x40808, 0x1d1d1d);
78 outpdw(MDP_BASE + 0x4080c, 0x232323);
79 outpdw(MDP_BASE + 0x40810, 0x272727);
80 outpdw(MDP_BASE + 0x40814, 0x2b2b2b);
81 outpdw(MDP_BASE + 0x40818, 0x2f2f2f);
82 outpdw(MDP_BASE + 0x4081c, 0x333333);
83 outpdw(MDP_BASE + 0x40820, 0x363636);
84 outpdw(MDP_BASE + 0x40824, 0x393939);
85 outpdw(MDP_BASE + 0x40828, 0x3b3b3b);
86 outpdw(MDP_BASE + 0x4082c, 0x3e3e3e);
87 outpdw(MDP_BASE + 0x40830, 0x404040);
88 outpdw(MDP_BASE + 0x40834, 0x434343);
89 outpdw(MDP_BASE + 0x40838, 0x454545);
90 outpdw(MDP_BASE + 0x4083c, 0x474747);
91 outpdw(MDP_BASE + 0x40840, 0x494949);
92 outpdw(MDP_BASE + 0x40844, 0x4b4b4b);
93 outpdw(MDP_BASE + 0x40848, 0x4d4d4d);
94 outpdw(MDP_BASE + 0x4084c, 0x4f4f4f);
95 outpdw(MDP_BASE + 0x40850, 0x515151);
96 outpdw(MDP_BASE + 0x40854, 0x535353);
97 outpdw(MDP_BASE + 0x40858, 0x555555);
98 outpdw(MDP_BASE + 0x4085c, 0x565656);
99 outpdw(MDP_BASE + 0x40860, 0x585858);
100 outpdw(MDP_BASE + 0x40864, 0x5a5a5a);
101 outpdw(MDP_BASE + 0x40868, 0x5b5b5b);
102 outpdw(MDP_BASE + 0x4086c, 0x5d5d5d);
103 outpdw(MDP_BASE + 0x40870, 0x5e5e5e);
104 outpdw(MDP_BASE + 0x40874, 0x606060);
105 outpdw(MDP_BASE + 0x40878, 0x616161);
106 outpdw(MDP_BASE + 0x4087c, 0x636363);
107 outpdw(MDP_BASE + 0x40880, 0x646464);
108 outpdw(MDP_BASE + 0x40884, 0x666666);
109 outpdw(MDP_BASE + 0x40888, 0x676767);
110 outpdw(MDP_BASE + 0x4088c, 0x686868);
111 outpdw(MDP_BASE + 0x40890, 0x6a6a6a);
112 outpdw(MDP_BASE + 0x40894, 0x6b6b6b);
113 outpdw(MDP_BASE + 0x40898, 0x6c6c6c);
114 outpdw(MDP_BASE + 0x4089c, 0x6e6e6e);
115 outpdw(MDP_BASE + 0x408a0, 0x6f6f6f);
116 outpdw(MDP_BASE + 0x408a4, 0x707070);
117 outpdw(MDP_BASE + 0x408a8, 0x717171);
118 outpdw(MDP_BASE + 0x408ac, 0x727272);
119 outpdw(MDP_BASE + 0x408b0, 0x747474);
120 outpdw(MDP_BASE + 0x408b4, 0x757575);
121 outpdw(MDP_BASE + 0x408b8, 0x767676);
122 outpdw(MDP_BASE + 0x408bc, 0x777777);
123 outpdw(MDP_BASE + 0x408c0, 0x787878);
124 outpdw(MDP_BASE + 0x408c4, 0x797979);
125 outpdw(MDP_BASE + 0x408c8, 0x7a7a7a);
126 outpdw(MDP_BASE + 0x408cc, 0x7c7c7c);
127 outpdw(MDP_BASE + 0x408d0, 0x7d7d7d);
128 outpdw(MDP_BASE + 0x408d4, 0x7e7e7e);
129 outpdw(MDP_BASE + 0x408d8, 0x7f7f7f);
130 outpdw(MDP_BASE + 0x408dc, 0x808080);
131 outpdw(MDP_BASE + 0x408e0, 0x818181);
132 outpdw(MDP_BASE + 0x408e4, 0x828282);
133 outpdw(MDP_BASE + 0x408e8, 0x838383);
134 outpdw(MDP_BASE + 0x408ec, 0x848484);
135 outpdw(MDP_BASE + 0x408f0, 0x858585);
136 outpdw(MDP_BASE + 0x408f4, 0x868686);
137 outpdw(MDP_BASE + 0x408f8, 0x878787);
138 outpdw(MDP_BASE + 0x408fc, 0x888888);
139 outpdw(MDP_BASE + 0x40900, 0x898989);
140 outpdw(MDP_BASE + 0x40904, 0x8a8a8a);
141 outpdw(MDP_BASE + 0x40908, 0x8b8b8b);
142 outpdw(MDP_BASE + 0x4090c, 0x8c8c8c);
143 outpdw(MDP_BASE + 0x40910, 0x8d8d8d);
144 outpdw(MDP_BASE + 0x40914, 0x8e8e8e);
145 outpdw(MDP_BASE + 0x40918, 0x8f8f8f);
146 outpdw(MDP_BASE + 0x4091c, 0x8f8f8f);
147 outpdw(MDP_BASE + 0x40920, 0x909090);
148 outpdw(MDP_BASE + 0x40924, 0x919191);
149 outpdw(MDP_BASE + 0x40928, 0x929292);
150 outpdw(MDP_BASE + 0x4092c, 0x939393);
151 outpdw(MDP_BASE + 0x40930, 0x949494);
152 outpdw(MDP_BASE + 0x40934, 0x959595);
153 outpdw(MDP_BASE + 0x40938, 0x969696);
154 outpdw(MDP_BASE + 0x4093c, 0x969696);
155 outpdw(MDP_BASE + 0x40940, 0x979797);
156 outpdw(MDP_BASE + 0x40944, 0x989898);
157 outpdw(MDP_BASE + 0x40948, 0x999999);
158 outpdw(MDP_BASE + 0x4094c, 0x9a9a9a);
159 outpdw(MDP_BASE + 0x40950, 0x9b9b9b);
160 outpdw(MDP_BASE + 0x40954, 0x9c9c9c);
161 outpdw(MDP_BASE + 0x40958, 0x9c9c9c);
162 outpdw(MDP_BASE + 0x4095c, 0x9d9d9d);
163 outpdw(MDP_BASE + 0x40960, 0x9e9e9e);
164 outpdw(MDP_BASE + 0x40964, 0x9f9f9f);
165 outpdw(MDP_BASE + 0x40968, 0xa0a0a0);
166 outpdw(MDP_BASE + 0x4096c, 0xa0a0a0);
167 outpdw(MDP_BASE + 0x40970, 0xa1a1a1);
168 outpdw(MDP_BASE + 0x40974, 0xa2a2a2);
169 outpdw(MDP_BASE + 0x40978, 0xa3a3a3);
170 outpdw(MDP_BASE + 0x4097c, 0xa4a4a4);
171 outpdw(MDP_BASE + 0x40980, 0xa4a4a4);
172 outpdw(MDP_BASE + 0x40984, 0xa5a5a5);
173 outpdw(MDP_BASE + 0x40988, 0xa6a6a6);
174 outpdw(MDP_BASE + 0x4098c, 0xa7a7a7);
175 outpdw(MDP_BASE + 0x40990, 0xa7a7a7);
176 outpdw(MDP_BASE + 0x40994, 0xa8a8a8);
177 outpdw(MDP_BASE + 0x40998, 0xa9a9a9);
178 outpdw(MDP_BASE + 0x4099c, 0xaaaaaa);
179 outpdw(MDP_BASE + 0x409a0, 0xaaaaaa);
180 outpdw(MDP_BASE + 0x409a4, 0xababab);
181 outpdw(MDP_BASE + 0x409a8, 0xacacac);
182 outpdw(MDP_BASE + 0x409ac, 0xadadad);
183 outpdw(MDP_BASE + 0x409b0, 0xadadad);
184 outpdw(MDP_BASE + 0x409b4, 0xaeaeae);
185 outpdw(MDP_BASE + 0x409b8, 0xafafaf);
186 outpdw(MDP_BASE + 0x409bc, 0xafafaf);
187 outpdw(MDP_BASE + 0x409c0, 0xb0b0b0);
188 outpdw(MDP_BASE + 0x409c4, 0xb1b1b1);
189 outpdw(MDP_BASE + 0x409c8, 0xb2b2b2);
190 outpdw(MDP_BASE + 0x409cc, 0xb2b2b2);
191 outpdw(MDP_BASE + 0x409d0, 0xb3b3b3);
192 outpdw(MDP_BASE + 0x409d4, 0xb4b4b4);
193 outpdw(MDP_BASE + 0x409d8, 0xb4b4b4);
194 outpdw(MDP_BASE + 0x409dc, 0xb5b5b5);
195 outpdw(MDP_BASE + 0x409e0, 0xb6b6b6);
196 outpdw(MDP_BASE + 0x409e4, 0xb6b6b6);
197 outpdw(MDP_BASE + 0x409e8, 0xb7b7b7);
198 outpdw(MDP_BASE + 0x409ec, 0xb8b8b8);
199 outpdw(MDP_BASE + 0x409f0, 0xb8b8b8);
200 outpdw(MDP_BASE + 0x409f4, 0xb9b9b9);
201 outpdw(MDP_BASE + 0x409f8, 0xbababa);
202 outpdw(MDP_BASE + 0x409fc, 0xbababa);
203 outpdw(MDP_BASE + 0x40a00, 0xbbbbbb);
204 outpdw(MDP_BASE + 0x40a04, 0xbcbcbc);
205 outpdw(MDP_BASE + 0x40a08, 0xbcbcbc);
206 outpdw(MDP_BASE + 0x40a0c, 0xbdbdbd);
207 outpdw(MDP_BASE + 0x40a10, 0xbebebe);
208 outpdw(MDP_BASE + 0x40a14, 0xbebebe);
209 outpdw(MDP_BASE + 0x40a18, 0xbfbfbf);
210 outpdw(MDP_BASE + 0x40a1c, 0xc0c0c0);
211 outpdw(MDP_BASE + 0x40a20, 0xc0c0c0);
212 outpdw(MDP_BASE + 0x40a24, 0xc1c1c1);
213 outpdw(MDP_BASE + 0x40a28, 0xc1c1c1);
214 outpdw(MDP_BASE + 0x40a2c, 0xc2c2c2);
215 outpdw(MDP_BASE + 0x40a30, 0xc3c3c3);
216 outpdw(MDP_BASE + 0x40a34, 0xc3c3c3);
217 outpdw(MDP_BASE + 0x40a38, 0xc4c4c4);
218 outpdw(MDP_BASE + 0x40a3c, 0xc5c5c5);
219 outpdw(MDP_BASE + 0x40a40, 0xc5c5c5);
220 outpdw(MDP_BASE + 0x40a44, 0xc6c6c6);
221 outpdw(MDP_BASE + 0x40a48, 0xc6c6c6);
222 outpdw(MDP_BASE + 0x40a4c, 0xc7c7c7);
223 outpdw(MDP_BASE + 0x40a50, 0xc8c8c8);
224 outpdw(MDP_BASE + 0x40a54, 0xc8c8c8);
225 outpdw(MDP_BASE + 0x40a58, 0xc9c9c9);
226 outpdw(MDP_BASE + 0x40a5c, 0xc9c9c9);
227 outpdw(MDP_BASE + 0x40a60, 0xcacaca);
228 outpdw(MDP_BASE + 0x40a64, 0xcbcbcb);
229 outpdw(MDP_BASE + 0x40a68, 0xcbcbcb);
230 outpdw(MDP_BASE + 0x40a6c, 0xcccccc);
231 outpdw(MDP_BASE + 0x40a70, 0xcccccc);
232 outpdw(MDP_BASE + 0x40a74, 0xcdcdcd);
233 outpdw(MDP_BASE + 0x40a78, 0xcecece);
234 outpdw(MDP_BASE + 0x40a7c, 0xcecece);
235 outpdw(MDP_BASE + 0x40a80, 0xcfcfcf);
236 outpdw(MDP_BASE + 0x40a84, 0xcfcfcf);
237 outpdw(MDP_BASE + 0x40a88, 0xd0d0d0);
238 outpdw(MDP_BASE + 0x40a8c, 0xd0d0d0);
239 outpdw(MDP_BASE + 0x40a90, 0xd1d1d1);
240 outpdw(MDP_BASE + 0x40a94, 0xd2d2d2);
241 outpdw(MDP_BASE + 0x40a98, 0xd2d2d2);
242 outpdw(MDP_BASE + 0x40a9c, 0xd3d3d3);
243 outpdw(MDP_BASE + 0x40aa0, 0xd3d3d3);
244 outpdw(MDP_BASE + 0x40aa4, 0xd4d4d4);
245 outpdw(MDP_BASE + 0x40aa8, 0xd4d4d4);
246 outpdw(MDP_BASE + 0x40aac, 0xd5d5d5);
247 outpdw(MDP_BASE + 0x40ab0, 0xd6d6d6);
248 outpdw(MDP_BASE + 0x40ab4, 0xd6d6d6);
249 outpdw(MDP_BASE + 0x40ab8, 0xd7d7d7);
250 outpdw(MDP_BASE + 0x40abc, 0xd7d7d7);
251 outpdw(MDP_BASE + 0x40ac0, 0xd8d8d8);
252 outpdw(MDP_BASE + 0x40ac4, 0xd8d8d8);
253 outpdw(MDP_BASE + 0x40ac8, 0xd9d9d9);
254 outpdw(MDP_BASE + 0x40acc, 0xd9d9d9);
255 outpdw(MDP_BASE + 0x40ad0, 0xdadada);
256 outpdw(MDP_BASE + 0x40ad4, 0xdbdbdb);
257 outpdw(MDP_BASE + 0x40ad8, 0xdbdbdb);
258 outpdw(MDP_BASE + 0x40adc, 0xdcdcdc);
259 outpdw(MDP_BASE + 0x40ae0, 0xdcdcdc);
260 outpdw(MDP_BASE + 0x40ae4, 0xdddddd);
261 outpdw(MDP_BASE + 0x40ae8, 0xdddddd);
262 outpdw(MDP_BASE + 0x40aec, 0xdedede);
263 outpdw(MDP_BASE + 0x40af0, 0xdedede);
264 outpdw(MDP_BASE + 0x40af4, 0xdfdfdf);
265 outpdw(MDP_BASE + 0x40af8, 0xdfdfdf);
266 outpdw(MDP_BASE + 0x40afc, 0xe0e0e0);
267 outpdw(MDP_BASE + 0x40b00, 0xe0e0e0);
268 outpdw(MDP_BASE + 0x40b04, 0xe1e1e1);
269 outpdw(MDP_BASE + 0x40b08, 0xe1e1e1);
270 outpdw(MDP_BASE + 0x40b0c, 0xe2e2e2);
271 outpdw(MDP_BASE + 0x40b10, 0xe3e3e3);
272 outpdw(MDP_BASE + 0x40b14, 0xe3e3e3);
273 outpdw(MDP_BASE + 0x40b18, 0xe4e4e4);
274 outpdw(MDP_BASE + 0x40b1c, 0xe4e4e4);
275 outpdw(MDP_BASE + 0x40b20, 0xe5e5e5);
276 outpdw(MDP_BASE + 0x40b24, 0xe5e5e5);
277 outpdw(MDP_BASE + 0x40b28, 0xe6e6e6);
278 outpdw(MDP_BASE + 0x40b2c, 0xe6e6e6);
279 outpdw(MDP_BASE + 0x40b30, 0xe7e7e7);
280 outpdw(MDP_BASE + 0x40b34, 0xe7e7e7);
281 outpdw(MDP_BASE + 0x40b38, 0xe8e8e8);
282 outpdw(MDP_BASE + 0x40b3c, 0xe8e8e8);
283 outpdw(MDP_BASE + 0x40b40, 0xe9e9e9);
284 outpdw(MDP_BASE + 0x40b44, 0xe9e9e9);
285 outpdw(MDP_BASE + 0x40b48, 0xeaeaea);
286 outpdw(MDP_BASE + 0x40b4c, 0xeaeaea);
287 outpdw(MDP_BASE + 0x40b50, 0xebebeb);
288 outpdw(MDP_BASE + 0x40b54, 0xebebeb);
289 outpdw(MDP_BASE + 0x40b58, 0xececec);
290 outpdw(MDP_BASE + 0x40b5c, 0xececec);
291 outpdw(MDP_BASE + 0x40b60, 0xededed);
292 outpdw(MDP_BASE + 0x40b64, 0xededed);
293 outpdw(MDP_BASE + 0x40b68, 0xeeeeee);
294 outpdw(MDP_BASE + 0x40b6c, 0xeeeeee);
295 outpdw(MDP_BASE + 0x40b70, 0xefefef);
296 outpdw(MDP_BASE + 0x40b74, 0xefefef);
297 outpdw(MDP_BASE + 0x40b78, 0xf0f0f0);
298 outpdw(MDP_BASE + 0x40b7c, 0xf0f0f0);
299 outpdw(MDP_BASE + 0x40b80, 0xf1f1f1);
300 outpdw(MDP_BASE + 0x40b84, 0xf1f1f1);
301 outpdw(MDP_BASE + 0x40b88, 0xf2f2f2);
302 outpdw(MDP_BASE + 0x40b8c, 0xf2f2f2);
303 outpdw(MDP_BASE + 0x40b90, 0xf2f2f2);
304 outpdw(MDP_BASE + 0x40b94, 0xf3f3f3);
305 outpdw(MDP_BASE + 0x40b98, 0xf3f3f3);
306 outpdw(MDP_BASE + 0x40b9c, 0xf4f4f4);
307 outpdw(MDP_BASE + 0x40ba0, 0xf4f4f4);
308 outpdw(MDP_BASE + 0x40ba4, 0xf5f5f5);
309 outpdw(MDP_BASE + 0x40ba8, 0xf5f5f5);
310 outpdw(MDP_BASE + 0x40bac, 0xf6f6f6);
311 outpdw(MDP_BASE + 0x40bb0, 0xf6f6f6);
312 outpdw(MDP_BASE + 0x40bb4, 0xf7f7f7);
313 outpdw(MDP_BASE + 0x40bb8, 0xf7f7f7);
314 outpdw(MDP_BASE + 0x40bbc, 0xf8f8f8);
315 outpdw(MDP_BASE + 0x40bc0, 0xf8f8f8);
316 outpdw(MDP_BASE + 0x40bc4, 0xf9f9f9);
317 outpdw(MDP_BASE + 0x40bc8, 0xf9f9f9);
318 outpdw(MDP_BASE + 0x40bcc, 0xfafafa);
319 outpdw(MDP_BASE + 0x40bd0, 0xfafafa);
320 outpdw(MDP_BASE + 0x40bd4, 0xfafafa);
321 outpdw(MDP_BASE + 0x40bd8, 0xfbfbfb);
322 outpdw(MDP_BASE + 0x40bdc, 0xfbfbfb);
323 outpdw(MDP_BASE + 0x40be0, 0xfcfcfc);
324 outpdw(MDP_BASE + 0x40be4, 0xfcfcfc);
325 outpdw(MDP_BASE + 0x40be8, 0xfdfdfd);
326 outpdw(MDP_BASE + 0x40bec, 0xfdfdfd);
327 outpdw(MDP_BASE + 0x40bf0, 0xfefefe);
328 outpdw(MDP_BASE + 0x40bf4, 0xfefefe);
329 outpdw(MDP_BASE + 0x40bf8, 0xffffff);
330 outpdw(MDP_BASE + 0x40bfc, 0xffffff);
331 outpdw(MDP_BASE + 0x40c00, 0x0);
332 outpdw(MDP_BASE + 0x40c04, 0x0);
333 outpdw(MDP_BASE + 0x40c08, 0x0);
334 outpdw(MDP_BASE + 0x40c0c, 0x0);
335 outpdw(MDP_BASE + 0x40c10, 0x0);
336 outpdw(MDP_BASE + 0x40c14, 0x0);
337 outpdw(MDP_BASE + 0x40c18, 0x0);
338 outpdw(MDP_BASE + 0x40c1c, 0x0);
339 outpdw(MDP_BASE + 0x40c20, 0x0);
340 outpdw(MDP_BASE + 0x40c24, 0x0);
341 outpdw(MDP_BASE + 0x40c28, 0x0);
342 outpdw(MDP_BASE + 0x40c2c, 0x0);
343 outpdw(MDP_BASE + 0x40c30, 0x0);
344 outpdw(MDP_BASE + 0x40c34, 0x0);
345 outpdw(MDP_BASE + 0x40c38, 0x0);
346 outpdw(MDP_BASE + 0x40c3c, 0x0);
347 outpdw(MDP_BASE + 0x40c40, 0x10101);
348 outpdw(MDP_BASE + 0x40c44, 0x10101);
349 outpdw(MDP_BASE + 0x40c48, 0x10101);
350 outpdw(MDP_BASE + 0x40c4c, 0x10101);
351 outpdw(MDP_BASE + 0x40c50, 0x10101);
352 outpdw(MDP_BASE + 0x40c54, 0x10101);
353 outpdw(MDP_BASE + 0x40c58, 0x10101);
354 outpdw(MDP_BASE + 0x40c5c, 0x10101);
355 outpdw(MDP_BASE + 0x40c60, 0x10101);
356 outpdw(MDP_BASE + 0x40c64, 0x10101);
357 outpdw(MDP_BASE + 0x40c68, 0x20202);
358 outpdw(MDP_BASE + 0x40c6c, 0x20202);
359 outpdw(MDP_BASE + 0x40c70, 0x20202);
360 outpdw(MDP_BASE + 0x40c74, 0x20202);
361 outpdw(MDP_BASE + 0x40c78, 0x20202);
362 outpdw(MDP_BASE + 0x40c7c, 0x20202);
363 outpdw(MDP_BASE + 0x40c80, 0x30303);
364 outpdw(MDP_BASE + 0x40c84, 0x30303);
365 outpdw(MDP_BASE + 0x40c88, 0x30303);
366 outpdw(MDP_BASE + 0x40c8c, 0x30303);
367 outpdw(MDP_BASE + 0x40c90, 0x30303);
368 outpdw(MDP_BASE + 0x40c94, 0x40404);
369 outpdw(MDP_BASE + 0x40c98, 0x40404);
370 outpdw(MDP_BASE + 0x40c9c, 0x40404);
371 outpdw(MDP_BASE + 0x40ca0, 0x40404);
372 outpdw(MDP_BASE + 0x40ca4, 0x40404);
373 outpdw(MDP_BASE + 0x40ca8, 0x50505);
374 outpdw(MDP_BASE + 0x40cac, 0x50505);
375 outpdw(MDP_BASE + 0x40cb0, 0x50505);
376 outpdw(MDP_BASE + 0x40cb4, 0x50505);
377 outpdw(MDP_BASE + 0x40cb8, 0x60606);
378 outpdw(MDP_BASE + 0x40cbc, 0x60606);
379 outpdw(MDP_BASE + 0x40cc0, 0x60606);
380 outpdw(MDP_BASE + 0x40cc4, 0x70707);
381 outpdw(MDP_BASE + 0x40cc8, 0x70707);
382 outpdw(MDP_BASE + 0x40ccc, 0x70707);
383 outpdw(MDP_BASE + 0x40cd0, 0x70707);
384 outpdw(MDP_BASE + 0x40cd4, 0x80808);
385 outpdw(MDP_BASE + 0x40cd8, 0x80808);
386 outpdw(MDP_BASE + 0x40cdc, 0x80808);
387 outpdw(MDP_BASE + 0x40ce0, 0x90909);
388 outpdw(MDP_BASE + 0x40ce4, 0x90909);
389 outpdw(MDP_BASE + 0x40ce8, 0xa0a0a);
390 outpdw(MDP_BASE + 0x40cec, 0xa0a0a);
391 outpdw(MDP_BASE + 0x40cf0, 0xa0a0a);
392 outpdw(MDP_BASE + 0x40cf4, 0xb0b0b);
393 outpdw(MDP_BASE + 0x40cf8, 0xb0b0b);
394 outpdw(MDP_BASE + 0x40cfc, 0xb0b0b);
395 outpdw(MDP_BASE + 0x40d00, 0xc0c0c);
396 outpdw(MDP_BASE + 0x40d04, 0xc0c0c);
397 outpdw(MDP_BASE + 0x40d08, 0xd0d0d);
398 outpdw(MDP_BASE + 0x40d0c, 0xd0d0d);
399 outpdw(MDP_BASE + 0x40d10, 0xe0e0e);
400 outpdw(MDP_BASE + 0x40d14, 0xe0e0e);
401 outpdw(MDP_BASE + 0x40d18, 0xe0e0e);
402 outpdw(MDP_BASE + 0x40d1c, 0xf0f0f);
403 outpdw(MDP_BASE + 0x40d20, 0xf0f0f);
404 outpdw(MDP_BASE + 0x40d24, 0x101010);
405 outpdw(MDP_BASE + 0x40d28, 0x101010);
406 outpdw(MDP_BASE + 0x40d2c, 0x111111);
407 outpdw(MDP_BASE + 0x40d30, 0x111111);
408 outpdw(MDP_BASE + 0x40d34, 0x121212);
409 outpdw(MDP_BASE + 0x40d38, 0x121212);
410 outpdw(MDP_BASE + 0x40d3c, 0x131313);
411 outpdw(MDP_BASE + 0x40d40, 0x131313);
412 outpdw(MDP_BASE + 0x40d44, 0x141414);
413 outpdw(MDP_BASE + 0x40d48, 0x151515);
414 outpdw(MDP_BASE + 0x40d4c, 0x151515);
415 outpdw(MDP_BASE + 0x40d50, 0x161616);
416 outpdw(MDP_BASE + 0x40d54, 0x161616);
417 outpdw(MDP_BASE + 0x40d58, 0x171717);
418 outpdw(MDP_BASE + 0x40d5c, 0x171717);
419 outpdw(MDP_BASE + 0x40d60, 0x181818);
420 outpdw(MDP_BASE + 0x40d64, 0x191919);
421 outpdw(MDP_BASE + 0x40d68, 0x191919);
422 outpdw(MDP_BASE + 0x40d6c, 0x1a1a1a);
423 outpdw(MDP_BASE + 0x40d70, 0x1b1b1b);
424 outpdw(MDP_BASE + 0x40d74, 0x1b1b1b);
425 outpdw(MDP_BASE + 0x40d78, 0x1c1c1c);
426 outpdw(MDP_BASE + 0x40d7c, 0x1c1c1c);
427 outpdw(MDP_BASE + 0x40d80, 0x1d1d1d);
428 outpdw(MDP_BASE + 0x40d84, 0x1e1e1e);
429 outpdw(MDP_BASE + 0x40d88, 0x1f1f1f);
430 outpdw(MDP_BASE + 0x40d8c, 0x1f1f1f);
431 outpdw(MDP_BASE + 0x40d90, 0x202020);
432 outpdw(MDP_BASE + 0x40d94, 0x212121);
433 outpdw(MDP_BASE + 0x40d98, 0x212121);
434 outpdw(MDP_BASE + 0x40d9c, 0x222222);
435 outpdw(MDP_BASE + 0x40da0, 0x232323);
436 outpdw(MDP_BASE + 0x40da4, 0x242424);
437 outpdw(MDP_BASE + 0x40da8, 0x242424);
438 outpdw(MDP_BASE + 0x40dac, 0x252525);
439 outpdw(MDP_BASE + 0x40db0, 0x262626);
440 outpdw(MDP_BASE + 0x40db4, 0x272727);
441 outpdw(MDP_BASE + 0x40db8, 0x272727);
442 outpdw(MDP_BASE + 0x40dbc, 0x282828);
443 outpdw(MDP_BASE + 0x40dc0, 0x292929);
444 outpdw(MDP_BASE + 0x40dc4, 0x2a2a2a);
445 outpdw(MDP_BASE + 0x40dc8, 0x2b2b2b);
446 outpdw(MDP_BASE + 0x40dcc, 0x2c2c2c);
447 outpdw(MDP_BASE + 0x40dd0, 0x2c2c2c);
448 outpdw(MDP_BASE + 0x40dd4, 0x2d2d2d);
449 outpdw(MDP_BASE + 0x40dd8, 0x2e2e2e);
450 outpdw(MDP_BASE + 0x40ddc, 0x2f2f2f);
451 outpdw(MDP_BASE + 0x40de0, 0x303030);
452 outpdw(MDP_BASE + 0x40de4, 0x313131);
453 outpdw(MDP_BASE + 0x40de8, 0x323232);
454 outpdw(MDP_BASE + 0x40dec, 0x333333);
455 outpdw(MDP_BASE + 0x40df0, 0x333333);
456 outpdw(MDP_BASE + 0x40df4, 0x343434);
457 outpdw(MDP_BASE + 0x40df8, 0x353535);
458 outpdw(MDP_BASE + 0x40dfc, 0x363636);
459 outpdw(MDP_BASE + 0x40e00, 0x373737);
460 outpdw(MDP_BASE + 0x40e04, 0x383838);
461 outpdw(MDP_BASE + 0x40e08, 0x393939);
462 outpdw(MDP_BASE + 0x40e0c, 0x3a3a3a);
463 outpdw(MDP_BASE + 0x40e10, 0x3b3b3b);
464 outpdw(MDP_BASE + 0x40e14, 0x3c3c3c);
465 outpdw(MDP_BASE + 0x40e18, 0x3d3d3d);
466 outpdw(MDP_BASE + 0x40e1c, 0x3e3e3e);
467 outpdw(MDP_BASE + 0x40e20, 0x3f3f3f);
468 outpdw(MDP_BASE + 0x40e24, 0x404040);
469 outpdw(MDP_BASE + 0x40e28, 0x414141);
470 outpdw(MDP_BASE + 0x40e2c, 0x424242);
471 outpdw(MDP_BASE + 0x40e30, 0x434343);
472 outpdw(MDP_BASE + 0x40e34, 0x444444);
473 outpdw(MDP_BASE + 0x40e38, 0x464646);
474 outpdw(MDP_BASE + 0x40e3c, 0x474747);
475 outpdw(MDP_BASE + 0x40e40, 0x484848);
476 outpdw(MDP_BASE + 0x40e44, 0x494949);
477 outpdw(MDP_BASE + 0x40e48, 0x4a4a4a);
478 outpdw(MDP_BASE + 0x40e4c, 0x4b4b4b);
479 outpdw(MDP_BASE + 0x40e50, 0x4c4c4c);
480 outpdw(MDP_BASE + 0x40e54, 0x4d4d4d);
481 outpdw(MDP_BASE + 0x40e58, 0x4f4f4f);
482 outpdw(MDP_BASE + 0x40e5c, 0x505050);
483 outpdw(MDP_BASE + 0x40e60, 0x515151);
484 outpdw(MDP_BASE + 0x40e64, 0x525252);
485 outpdw(MDP_BASE + 0x40e68, 0x535353);
486 outpdw(MDP_BASE + 0x40e6c, 0x545454);
487 outpdw(MDP_BASE + 0x40e70, 0x565656);
488 outpdw(MDP_BASE + 0x40e74, 0x575757);
489 outpdw(MDP_BASE + 0x40e78, 0x585858);
490 outpdw(MDP_BASE + 0x40e7c, 0x595959);
491 outpdw(MDP_BASE + 0x40e80, 0x5b5b5b);
492 outpdw(MDP_BASE + 0x40e84, 0x5c5c5c);
493 outpdw(MDP_BASE + 0x40e88, 0x5d5d5d);
494 outpdw(MDP_BASE + 0x40e8c, 0x5e5e5e);
495 outpdw(MDP_BASE + 0x40e90, 0x606060);
496 outpdw(MDP_BASE + 0x40e94, 0x616161);
497 outpdw(MDP_BASE + 0x40e98, 0x626262);
498 outpdw(MDP_BASE + 0x40e9c, 0x646464);
499 outpdw(MDP_BASE + 0x40ea0, 0x656565);
500 outpdw(MDP_BASE + 0x40ea4, 0x666666);
501 outpdw(MDP_BASE + 0x40ea8, 0x686868);
502 outpdw(MDP_BASE + 0x40eac, 0x696969);
503 outpdw(MDP_BASE + 0x40eb0, 0x6a6a6a);
504 outpdw(MDP_BASE + 0x40eb4, 0x6c6c6c);
505 outpdw(MDP_BASE + 0x40eb8, 0x6d6d6d);
506 outpdw(MDP_BASE + 0x40ebc, 0x6f6f6f);
507 outpdw(MDP_BASE + 0x40ec0, 0x707070);
508 outpdw(MDP_BASE + 0x40ec4, 0x717171);
509 outpdw(MDP_BASE + 0x40ec8, 0x737373);
510 outpdw(MDP_BASE + 0x40ecc, 0x747474);
511 outpdw(MDP_BASE + 0x40ed0, 0x767676);
512 outpdw(MDP_BASE + 0x40ed4, 0x777777);
513 outpdw(MDP_BASE + 0x40ed8, 0x797979);
514 outpdw(MDP_BASE + 0x40edc, 0x7a7a7a);
515 outpdw(MDP_BASE + 0x40ee0, 0x7c7c7c);
516 outpdw(MDP_BASE + 0x40ee4, 0x7d7d7d);
517 outpdw(MDP_BASE + 0x40ee8, 0x7f7f7f);
518 outpdw(MDP_BASE + 0x40eec, 0x808080);
519 outpdw(MDP_BASE + 0x40ef0, 0x828282);
520 outpdw(MDP_BASE + 0x40ef4, 0x838383);
521 outpdw(MDP_BASE + 0x40ef8, 0x858585);
522 outpdw(MDP_BASE + 0x40efc, 0x868686);
523 outpdw(MDP_BASE + 0x40f00, 0x888888);
524 outpdw(MDP_BASE + 0x40f04, 0x898989);
525 outpdw(MDP_BASE + 0x40f08, 0x8b8b8b);
526 outpdw(MDP_BASE + 0x40f0c, 0x8d8d8d);
527 outpdw(MDP_BASE + 0x40f10, 0x8e8e8e);
528 outpdw(MDP_BASE + 0x40f14, 0x909090);
529 outpdw(MDP_BASE + 0x40f18, 0x919191);
530 outpdw(MDP_BASE + 0x40f1c, 0x939393);
531 outpdw(MDP_BASE + 0x40f20, 0x959595);
532 outpdw(MDP_BASE + 0x40f24, 0x969696);
533 outpdw(MDP_BASE + 0x40f28, 0x989898);
534 outpdw(MDP_BASE + 0x40f2c, 0x9a9a9a);
535 outpdw(MDP_BASE + 0x40f30, 0x9b9b9b);
536 outpdw(MDP_BASE + 0x40f34, 0x9d9d9d);
537 outpdw(MDP_BASE + 0x40f38, 0x9f9f9f);
538 outpdw(MDP_BASE + 0x40f3c, 0xa1a1a1);
539 outpdw(MDP_BASE + 0x40f40, 0xa2a2a2);
540 outpdw(MDP_BASE + 0x40f44, 0xa4a4a4);
541 outpdw(MDP_BASE + 0x40f48, 0xa6a6a6);
542 outpdw(MDP_BASE + 0x40f4c, 0xa7a7a7);
543 outpdw(MDP_BASE + 0x40f50, 0xa9a9a9);
544 outpdw(MDP_BASE + 0x40f54, 0xababab);
545 outpdw(MDP_BASE + 0x40f58, 0xadadad);
546 outpdw(MDP_BASE + 0x40f5c, 0xafafaf);
547 outpdw(MDP_BASE + 0x40f60, 0xb0b0b0);
548 outpdw(MDP_BASE + 0x40f64, 0xb2b2b2);
549 outpdw(MDP_BASE + 0x40f68, 0xb4b4b4);
550 outpdw(MDP_BASE + 0x40f6c, 0xb6b6b6);
551 outpdw(MDP_BASE + 0x40f70, 0xb8b8b8);
552 outpdw(MDP_BASE + 0x40f74, 0xbababa);
553 outpdw(MDP_BASE + 0x40f78, 0xbbbbbb);
554 outpdw(MDP_BASE + 0x40f7c, 0xbdbdbd);
555 outpdw(MDP_BASE + 0x40f80, 0xbfbfbf);
556 outpdw(MDP_BASE + 0x40f84, 0xc1c1c1);
557 outpdw(MDP_BASE + 0x40f88, 0xc3c3c3);
558 outpdw(MDP_BASE + 0x40f8c, 0xc5c5c5);
559 outpdw(MDP_BASE + 0x40f90, 0xc7c7c7);
560 outpdw(MDP_BASE + 0x40f94, 0xc9c9c9);
561 outpdw(MDP_BASE + 0x40f98, 0xcbcbcb);
562 outpdw(MDP_BASE + 0x40f9c, 0xcdcdcd);
563 outpdw(MDP_BASE + 0x40fa0, 0xcfcfcf);
564 outpdw(MDP_BASE + 0x40fa4, 0xd1d1d1);
565 outpdw(MDP_BASE + 0x40fa8, 0xd3d3d3);
566 outpdw(MDP_BASE + 0x40fac, 0xd5d5d5);
567 outpdw(MDP_BASE + 0x40fb0, 0xd7d7d7);
568 outpdw(MDP_BASE + 0x40fb4, 0xd9d9d9);
569 outpdw(MDP_BASE + 0x40fb8, 0xdbdbdb);
570 outpdw(MDP_BASE + 0x40fbc, 0xdddddd);
571 outpdw(MDP_BASE + 0x40fc0, 0xdfdfdf);
572 outpdw(MDP_BASE + 0x40fc4, 0xe1e1e1);
573 outpdw(MDP_BASE + 0x40fc8, 0xe3e3e3);
574 outpdw(MDP_BASE + 0x40fcc, 0xe5e5e5);
575 outpdw(MDP_BASE + 0x40fd0, 0xe7e7e7);
576 outpdw(MDP_BASE + 0x40fd4, 0xe9e9e9);
577 outpdw(MDP_BASE + 0x40fd8, 0xebebeb);
578 outpdw(MDP_BASE + 0x40fdc, 0xeeeeee);
579 outpdw(MDP_BASE + 0x40fe0, 0xf0f0f0);
580 outpdw(MDP_BASE + 0x40fe4, 0xf2f2f2);
581 outpdw(MDP_BASE + 0x40fe8, 0xf4f4f4);
582 outpdw(MDP_BASE + 0x40fec, 0xf6f6f6);
583 outpdw(MDP_BASE + 0x40ff0, 0xf8f8f8);
584 outpdw(MDP_BASE + 0x40ff4, 0xfbfbfb);
585 outpdw(MDP_BASE + 0x40ff8, 0xfdfdfd);
586 outpdw(MDP_BASE + 0x40ffc, 0xffffff);
587}
588
589#define IRQ_EN_1__MDP_IRQ___M 0x00000800
590
591void mdp_hw_init(void)
592{
593 int i;
594
595 /* MDP cmd block enable */
596 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
597
598 /* debug interface write access */
599 outpdw(MDP_BASE + 0x60, 1);
600
601 outp32(MDP_INTR_ENABLE, MDP_ANY_INTR_MASK);
602 outp32(MDP_EBI2_PORTMAP_MODE, 0x3);
603 outpdw(MDP_CMD_DEBUG_ACCESS_BASE + 0x01f8, 0x0);
604 outpdw(MDP_CMD_DEBUG_ACCESS_BASE + 0x01fc, 0x0);
605 outpdw(MDP_BASE + 0x60, 0x1);
606 mdp_load_lut_param();
607
608 /*
609 * clear up unused fg/main registers
610 */
611 /* comp.plane 2&3 ystride */
612 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0120, 0x0);
613 /* unpacked pattern */
614 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x012c, 0x0);
615 /* unpacked pattern */
616 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0130, 0x0);
617 /* unpacked pattern */
618 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0134, 0x0);
619 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0158, 0x0);
620 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x15c, 0x0);
621 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0160, 0x0);
622 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0170, 0x0);
623 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0174, 0x0);
624 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x017c, 0x0);
625
626 /* comp.plane 2 */
627 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0114, 0x0);
628 /* comp.plane 3 */
629 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0118, 0x0);
630
631 /* clear up unused bg registers */
632 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01c8, 0);
633 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01d0, 0);
634 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01dc, 0);
635 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01e0, 0);
636 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01e4, 0);
637
638#ifndef CONFIG_FB_MSM_MDP22
639 MDP_OUTP(MDP_BASE + 0xE0000, 0);
640 MDP_OUTP(MDP_BASE + 0x100, 0xffffffff);
641 MDP_OUTP(MDP_BASE + 0x90070, 0);
642 MDP_OUTP(MDP_BASE + 0x94010, 1);
643 MDP_OUTP(MDP_BASE + 0x9401c, 2);
644#endif
645
646 /*
647 * limit vector
648 * pre gets applied before color matrix conversion
649 * post is after ccs
650 */
651 writel(mdp_plv[0], MDP_CSC_PRE_LV1n(0));
652 writel(mdp_plv[1], MDP_CSC_PRE_LV1n(1));
653 writel(mdp_plv[2], MDP_CSC_PRE_LV1n(2));
654 writel(mdp_plv[3], MDP_CSC_PRE_LV1n(3));
655
656#ifdef CONFIG_FB_MSM_MDP31
657 writel(mdp_plv[2], MDP_CSC_PRE_LV1n(4));
658 writel(mdp_plv[3], MDP_CSC_PRE_LV1n(5));
659
660 writel(0, MDP_CSC_POST_LV1n(0));
661 writel(0xff, MDP_CSC_POST_LV1n(1));
662 writel(0, MDP_CSC_POST_LV1n(2));
663 writel(0xff, MDP_CSC_POST_LV1n(3));
664 writel(0, MDP_CSC_POST_LV1n(4));
665 writel(0xff, MDP_CSC_POST_LV1n(5));
666
667 writel(0, MDP_CSC_PRE_LV2n(0));
668 writel(0xff, MDP_CSC_PRE_LV2n(1));
669 writel(0, MDP_CSC_PRE_LV2n(2));
670 writel(0xff, MDP_CSC_PRE_LV2n(3));
671 writel(0, MDP_CSC_PRE_LV2n(4));
672 writel(0xff, MDP_CSC_PRE_LV2n(5));
673
674 writel(mdp_plv[0], MDP_CSC_POST_LV2n(0));
675 writel(mdp_plv[1], MDP_CSC_POST_LV2n(1));
676 writel(mdp_plv[2], MDP_CSC_POST_LV2n(2));
677 writel(mdp_plv[3], MDP_CSC_POST_LV2n(3));
678 writel(mdp_plv[2], MDP_CSC_POST_LV2n(4));
679 writel(mdp_plv[3], MDP_CSC_POST_LV2n(5));
680#endif
681
682 /* primary forward matrix */
683 for (i = 0; i < MDP_CCS_SIZE; i++)
684 writel(mdp_ccs_rgb2yuv.ccs[i], MDP_CSC_PFMVn(i));
685
686#ifdef CONFIG_FB_MSM_MDP31
687 for (i = 0; i < MDP_BV_SIZE; i++)
688 writel(mdp_ccs_rgb2yuv.bv[i], MDP_CSC_POST_BV2n(i));
689
690 writel(0, MDP_CSC_PRE_BV2n(0));
691 writel(0, MDP_CSC_PRE_BV2n(1));
692 writel(0, MDP_CSC_PRE_BV2n(2));
693#endif
694 /* primary reverse matrix */
695 for (i = 0; i < MDP_CCS_SIZE; i++)
696 writel(mdp_ccs_yuv2rgb.ccs[i], MDP_CSC_PRMVn(i));
697
698 for (i = 0; i < MDP_BV_SIZE; i++)
699 writel(mdp_ccs_yuv2rgb.bv[i], MDP_CSC_PRE_BV1n(i));
700
701#ifdef CONFIG_FB_MSM_MDP31
702 writel(0, MDP_CSC_POST_BV1n(0));
703 writel(0, MDP_CSC_POST_BV1n(1));
704 writel(0, MDP_CSC_POST_BV1n(2));
705
706 outpdw(MDP_BASE + 0x30010, 0x03e0);
707 outpdw(MDP_BASE + 0x30014, 0x0360);
708 outpdw(MDP_BASE + 0x30018, 0x0120);
709 outpdw(MDP_BASE + 0x3001c, 0x0140);
710#endif
711 mdp_init_scale_table();
712
713#ifndef CONFIG_FB_MSM_MDP31
714 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0104,
715 ((16 << 6) << 16) | (16) << 6);
716#endif
717
718 /* MDP cmd block disable */
719 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
720} \ 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
index 000000000000..c35a6aebca14
--- /dev/null
+++ b/drivers/staging/msm/mdp_ppp.c
@@ -0,0 +1,1502 @@
1/* drivers/video/msm/src/drv/mdp/mdp_ppp.c
2 *
3 * Copyright (C) 2007 Google Incorporated
4 * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16#include <linux/module.h>
17#include <linux/kernel.h>
18#include <linux/sched.h>
19#include <linux/time.h>
20#include <linux/init.h>
21#include <linux/interrupt.h>
22#include <linux/fb.h>
23#include <msm_mdp.h>
24#include <linux/file.h>
25#include <linux/major.h>
26
27#include "linux/proc_fs.h"
28
29#include <mach/hardware.h>
30#include <linux/io.h>
31
32#include <asm/system.h>
33#include <asm/mach-types.h>
34#include <linux/semaphore.h>
35
36#include "mdp.h"
37#include "msm_fb.h"
38
39#define MDP_IS_IMGTYPE_BAD(x) (((x) >= MDP_IMGTYPE_LIMIT) && \
40 (((x) < MDP_IMGTYPE2_START) || \
41 ((x) >= MDP_IMGTYPE_LIMIT2)))
42
43static uint32_t bytes_per_pixel[] = {
44 [MDP_RGB_565] = 2,
45 [MDP_RGB_888] = 3,
46 [MDP_XRGB_8888] = 4,
47 [MDP_ARGB_8888] = 4,
48 [MDP_RGBA_8888] = 4,
49 [MDP_BGRA_8888] = 4,
50 [MDP_Y_CBCR_H2V1] = 1,
51 [MDP_Y_CBCR_H2V2] = 1,
52 [MDP_Y_CRCB_H2V1] = 1,
53 [MDP_Y_CRCB_H2V2] = 1,
54 [MDP_YCRYCB_H2V1] = 2,
55 [MDP_BGR_565] = 2
56};
57
58extern uint32 mdp_plv[];
59extern struct semaphore mdp_ppp_mutex;
60
61uint32_t mdp_get_bytes_per_pixel(uint32_t format)
62{
63 uint32_t bpp = 0;
64 if (format < ARRAY_SIZE(bytes_per_pixel))
65 bpp = bytes_per_pixel[format];
66
67 BUG_ON(!bpp);
68 return bpp;
69}
70
71static uint32 mdp_conv_matx_rgb2yuv(uint32 input_pixel,
72 uint16 *matrix_and_bias_vector,
73 uint32 *clamp_vector,
74 uint32 *look_up_table)
75{
76 uint8 input_C2, input_C0, input_C1;
77 uint32 output;
78 int32 comp_C2, comp_C1, comp_C0, temp;
79 int32 temp1, temp2, temp3;
80 int32 matrix[9];
81 int32 bias_vector[3];
82 int32 Y_low_limit, Y_high_limit, C_low_limit, C_high_limit;
83 int32 i;
84 uint32 _is_lookup_table_enabled;
85
86 input_C2 = (input_pixel >> 16) & 0xFF;
87 input_C1 = (input_pixel >> 8) & 0xFF;
88 input_C0 = (input_pixel >> 0) & 0xFF;
89
90 comp_C0 = input_C0;
91 comp_C1 = input_C1;
92 comp_C2 = input_C2;
93
94 for (i = 0; i < 9; i++)
95 matrix[i] =
96 ((int32) (((int32) matrix_and_bias_vector[i]) << 20)) >> 20;
97
98 bias_vector[0] = (int32) (matrix_and_bias_vector[9] & 0xFF);
99 bias_vector[1] = (int32) (matrix_and_bias_vector[10] & 0xFF);
100 bias_vector[2] = (int32) (matrix_and_bias_vector[11] & 0xFF);
101
102 Y_low_limit = (int32) clamp_vector[0];
103 Y_high_limit = (int32) clamp_vector[1];
104 C_low_limit = (int32) clamp_vector[2];
105 C_high_limit = (int32) clamp_vector[3];
106
107 if (look_up_table == 0) /* check for NULL point */
108 _is_lookup_table_enabled = 0;
109 else
110 _is_lookup_table_enabled = 1;
111
112 if (_is_lookup_table_enabled == 1) {
113 comp_C2 = (look_up_table[comp_C2] >> 16) & 0xFF;
114 comp_C1 = (look_up_table[comp_C1] >> 8) & 0xFF;
115 comp_C0 = (look_up_table[comp_C0] >> 0) & 0xFF;
116 }
117 /*
118 * Color Conversion
119 * reorder input colors
120 */
121 temp = comp_C2;
122 comp_C2 = comp_C1;
123 comp_C1 = comp_C0;
124 comp_C0 = temp;
125
126 /* matrix multiplication */
127 temp1 = comp_C0 * matrix[0] + comp_C1 * matrix[1] + comp_C2 * matrix[2];
128 temp2 = comp_C0 * matrix[3] + comp_C1 * matrix[4] + comp_C2 * matrix[5];
129 temp3 = comp_C0 * matrix[6] + comp_C1 * matrix[7] + comp_C2 * matrix[8];
130
131 comp_C0 = temp1 + 0x100;
132 comp_C1 = temp2 + 0x100;
133 comp_C2 = temp3 + 0x100;
134
135 /* take interger part */
136 comp_C0 >>= 9;
137 comp_C1 >>= 9;
138 comp_C2 >>= 9;
139
140 /* post bias (+) */
141 comp_C0 += bias_vector[0];
142 comp_C1 += bias_vector[1];
143 comp_C2 += bias_vector[2];
144
145 /* limit pixel to 8-bit */
146 if (comp_C0 < 0)
147 comp_C0 = 0;
148
149 if (comp_C0 > 255)
150 comp_C0 = 255;
151
152 if (comp_C1 < 0)
153 comp_C1 = 0;
154
155 if (comp_C1 > 255)
156 comp_C1 = 255;
157
158 if (comp_C2 < 0)
159 comp_C2 = 0;
160
161 if (comp_C2 > 255)
162 comp_C2 = 255;
163
164 /* clamp */
165 if (comp_C0 < Y_low_limit)
166 comp_C0 = Y_low_limit;
167
168 if (comp_C0 > Y_high_limit)
169 comp_C0 = Y_high_limit;
170
171 if (comp_C1 < C_low_limit)
172 comp_C1 = C_low_limit;
173
174 if (comp_C1 > C_high_limit)
175 comp_C1 = C_high_limit;
176
177 if (comp_C2 < C_low_limit)
178 comp_C2 = C_low_limit;
179
180 if (comp_C2 > C_high_limit)
181 comp_C2 = C_high_limit;
182
183 output = (comp_C2 << 16) | (comp_C1 << 8) | comp_C0;
184 return output;
185}
186
187uint32 mdp_conv_matx_yuv2rgb(uint32 input_pixel,
188 uint16 *matrix_and_bias_vector,
189 uint32 *clamp_vector, uint32 *look_up_table)
190{
191 uint8 input_C2, input_C0, input_C1;
192 uint32 output;
193 int32 comp_C2, comp_C1, comp_C0, temp;
194 int32 temp1, temp2, temp3;
195 int32 matrix[9];
196 int32 bias_vector[3];
197 int32 Y_low_limit, Y_high_limit, C_low_limit, C_high_limit;
198 int32 i;
199 uint32 _is_lookup_table_enabled;
200
201 input_C2 = (input_pixel >> 16) & 0xFF;
202 input_C1 = (input_pixel >> 8) & 0xFF;
203 input_C0 = (input_pixel >> 0) & 0xFF;
204
205 comp_C0 = input_C0;
206 comp_C1 = input_C1;
207 comp_C2 = input_C2;
208
209 for (i = 0; i < 9; i++)
210 matrix[i] =
211 ((int32) (((int32) matrix_and_bias_vector[i]) << 20)) >> 20;
212
213 bias_vector[0] = (int32) (matrix_and_bias_vector[9] & 0xFF);
214 bias_vector[1] = (int32) (matrix_and_bias_vector[10] & 0xFF);
215 bias_vector[2] = (int32) (matrix_and_bias_vector[11] & 0xFF);
216
217 Y_low_limit = (int32) clamp_vector[0];
218 Y_high_limit = (int32) clamp_vector[1];
219 C_low_limit = (int32) clamp_vector[2];
220 C_high_limit = (int32) clamp_vector[3];
221
222 if (look_up_table == 0) /* check for NULL point */
223 _is_lookup_table_enabled = 0;
224 else
225 _is_lookup_table_enabled = 1;
226
227 /* clamp */
228 if (comp_C0 < Y_low_limit)
229 comp_C0 = Y_low_limit;
230
231 if (comp_C0 > Y_high_limit)
232 comp_C0 = Y_high_limit;
233
234 if (comp_C1 < C_low_limit)
235 comp_C1 = C_low_limit;
236
237 if (comp_C1 > C_high_limit)
238 comp_C1 = C_high_limit;
239
240 if (comp_C2 < C_low_limit)
241 comp_C2 = C_low_limit;
242
243 if (comp_C2 > C_high_limit)
244 comp_C2 = C_high_limit;
245
246 /*
247 * Color Conversion
248 * pre bias (-)
249 */
250 comp_C0 -= bias_vector[0];
251 comp_C1 -= bias_vector[1];
252 comp_C2 -= bias_vector[2];
253
254 /* matrix multiplication */
255 temp1 = comp_C0 * matrix[0] + comp_C1 * matrix[1] + comp_C2 * matrix[2];
256 temp2 = comp_C0 * matrix[3] + comp_C1 * matrix[4] + comp_C2 * matrix[5];
257 temp3 = comp_C0 * matrix[6] + comp_C1 * matrix[7] + comp_C2 * matrix[8];
258
259 comp_C0 = temp1 + 0x100;
260 comp_C1 = temp2 + 0x100;
261 comp_C2 = temp3 + 0x100;
262
263 /* take interger part */
264 comp_C0 >>= 9;
265 comp_C1 >>= 9;
266 comp_C2 >>= 9;
267
268 /* reorder output colors */
269 temp = comp_C0;
270 comp_C0 = comp_C1;
271 comp_C1 = comp_C2;
272 comp_C2 = temp;
273
274 /* limit pixel to 8-bit */
275 if (comp_C0 < 0)
276 comp_C0 = 0;
277
278 if (comp_C0 > 255)
279 comp_C0 = 255;
280
281 if (comp_C1 < 0)
282 comp_C1 = 0;
283
284 if (comp_C1 > 255)
285 comp_C1 = 255;
286
287 if (comp_C2 < 0)
288 comp_C2 = 0;
289
290 if (comp_C2 > 255)
291 comp_C2 = 255;
292
293 /* Look-up table */
294 if (_is_lookup_table_enabled == 1) {
295 comp_C2 = (look_up_table[comp_C2] >> 16) & 0xFF;
296 comp_C1 = (look_up_table[comp_C1] >> 8) & 0xFF;
297 comp_C0 = (look_up_table[comp_C0] >> 0) & 0xFF;
298 }
299
300 output = (comp_C2 << 16) | (comp_C1 << 8) | comp_C0;
301 return output;
302}
303
304static uint32 mdp_calc_tpval(MDPIMG *mdpImg)
305{
306 uint32 tpVal;
307 uint8 plane_tp;
308
309 tpVal = 0;
310 if ((mdpImg->imgType == MDP_RGB_565)
311 || (mdpImg->imgType == MDP_BGR_565)) {
312 /*
313 * transparent color conversion into 24 bpp
314 *
315 * C2R_8BIT
316 * left shift the entire bit and or it with the upper most bits
317 */
318 plane_tp = (uint8) ((mdpImg->tpVal & 0xF800) >> 11);
319 tpVal |= ((plane_tp << 3) | ((plane_tp & 0x1C) >> 2)) << 16;
320
321 /* C1B_8BIT */
322 plane_tp = (uint8) (mdpImg->tpVal & 0x1F);
323 tpVal |= ((plane_tp << 3) | ((plane_tp & 0x1C) >> 2)) << 8;
324
325 /* C0G_8BIT */
326 plane_tp = (uint8) ((mdpImg->tpVal & 0x7E0) >> 5);
327 tpVal |= ((plane_tp << 2) | ((plane_tp & 0x30) >> 4));
328 } else {
329 /* 24bit RGB to RBG conversion */
330
331 tpVal = (mdpImg->tpVal & 0xFF00) >> 8;
332 tpVal |= (mdpImg->tpVal & 0xFF) << 8;
333 tpVal |= (mdpImg->tpVal & 0xFF0000);
334 }
335
336 return tpVal;
337}
338
339static uint8 *mdp_get_chroma_addr(MDPIBUF *iBuf)
340{
341 uint8 *dest1;
342
343 dest1 = NULL;
344 switch (iBuf->ibuf_type) {
345 case MDP_Y_CBCR_H2V2:
346 case MDP_Y_CRCB_H2V2:
347 case MDP_Y_CBCR_H2V1:
348 case MDP_Y_CRCB_H2V1:
349 dest1 = (uint8 *) iBuf->buf;
350 dest1 += iBuf->ibuf_width * iBuf->ibuf_height * iBuf->bpp;
351 break;
352
353 default:
354 break;
355 }
356
357 return dest1;
358}
359
360static void mdp_ppp_setbg(MDPIBUF *iBuf)
361{
362 uint8 *bg0_addr;
363 uint8 *bg1_addr;
364 uint32 bg0_ystride, bg1_ystride;
365 uint32 ppp_src_cfg_reg, unpack_pattern;
366 int v_slice, h_slice;
367
368 v_slice = h_slice = 1;
369 bg0_addr = (uint8 *) iBuf->buf;
370 bg1_addr = mdp_get_chroma_addr(iBuf);
371
372 bg0_ystride = iBuf->ibuf_width * iBuf->bpp;
373 bg1_ystride = iBuf->ibuf_width * iBuf->bpp;
374
375 switch (iBuf->ibuf_type) {
376 case MDP_BGR_565:
377 case MDP_RGB_565:
378 /* 888 = 3bytes
379 * RGB = 3Components
380 * RGB interleaved
381 */
382 ppp_src_cfg_reg = PPP_SRC_C2R_5BITS | PPP_SRC_C0G_6BITS |
383 PPP_SRC_C1B_5BITS | PPP_SRC_BPP_INTERLVD_2BYTES |
384 PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT |
385 PPP_SRC_UNPACK_ALIGN_LSB |
386 PPP_SRC_FETCH_PLANES_INTERLVD;
387
388 if (iBuf->ibuf_type == MDP_RGB_565)
389 unpack_pattern =
390 MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
391 else
392 unpack_pattern =
393 MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8);
394 break;
395
396 case MDP_RGB_888:
397 /*
398 * 888 = 3bytes
399 * RGB = 3Components
400 * RGB interleaved
401 */
402 ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
403 PPP_SRC_C1B_8BITS | PPP_SRC_BPP_INTERLVD_3BYTES |
404 PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT |
405 PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_INTERLVD;
406
407 unpack_pattern =
408 MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
409 break;
410
411 case MDP_BGRA_8888:
412 case MDP_RGBA_8888:
413 case MDP_ARGB_8888:
414 case MDP_XRGB_8888:
415 /*
416 * 8888 = 4bytes
417 * ARGB = 4Components
418 * ARGB interleaved
419 */
420 ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
421 PPP_SRC_C1B_8BITS | PPP_SRC_C3A_8BITS | PPP_SRC_C3_ALPHA_EN |
422 PPP_SRC_BPP_INTERLVD_4BYTES | PPP_SRC_INTERLVD_4COMPONENTS |
423 PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB |
424 PPP_SRC_FETCH_PLANES_INTERLVD;
425
426 if (iBuf->ibuf_type == MDP_BGRA_8888)
427 unpack_pattern =
428 MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
429 8);
430 else if (iBuf->ibuf_type == MDP_RGBA_8888)
431 unpack_pattern =
432 MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R,
433 8);
434 else
435 unpack_pattern =
436 MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
437 8);
438 break;
439
440 case MDP_Y_CBCR_H2V2:
441 case MDP_Y_CRCB_H2V2:
442 ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
443 PPP_SRC_C0G_8BITS |
444 PPP_SRC_C1B_8BITS |
445 PPP_SRC_C3A_8BITS |
446 PPP_SRC_BPP_INTERLVD_2BYTES |
447 PPP_SRC_INTERLVD_2COMPONENTS |
448 PPP_SRC_UNPACK_TIGHT |
449 PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_PSEUDOPLNR;
450
451 if (iBuf->ibuf_type == MDP_Y_CBCR_H2V1)
452 unpack_pattern =
453 MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
454 else
455 unpack_pattern =
456 MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
457 v_slice = h_slice = 2;
458 break;
459
460 case MDP_YCRYCB_H2V1:
461 ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
462 PPP_SRC_C0G_8BITS |
463 PPP_SRC_C1B_8BITS |
464 PPP_SRC_C3A_8BITS |
465 PPP_SRC_BPP_INTERLVD_2BYTES |
466 PPP_SRC_INTERLVD_4COMPONENTS |
467 PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB;
468
469 unpack_pattern =
470 MDP_GET_PACK_PATTERN(CLR_Y, CLR_CR, CLR_Y, CLR_CB, 8);
471 h_slice = 2;
472 break;
473
474 case MDP_Y_CBCR_H2V1:
475 case MDP_Y_CRCB_H2V1:
476 ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
477 PPP_SRC_C0G_8BITS |
478 PPP_SRC_C1B_8BITS |
479 PPP_SRC_C3A_8BITS |
480 PPP_SRC_BPP_INTERLVD_2BYTES |
481 PPP_SRC_INTERLVD_2COMPONENTS |
482 PPP_SRC_UNPACK_TIGHT |
483 PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_PSEUDOPLNR;
484
485 if (iBuf->ibuf_type == MDP_Y_CBCR_H2V1)
486 unpack_pattern =
487 MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
488 else
489 unpack_pattern =
490 MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
491 h_slice = 2;
492 break;
493
494 default:
495 return;
496 }
497
498 /* starting input address adjustment */
499 mdp_adjust_start_addr(&bg0_addr, &bg1_addr, v_slice, h_slice,
500 iBuf->roi.lcd_x, iBuf->roi.lcd_y,
501 iBuf->ibuf_width, iBuf->ibuf_height, iBuf->bpp,
502 iBuf, 1);
503
504 /*
505 * 0x01c0: background plane 0 addr
506 * 0x01c4: background plane 1 addr
507 * 0x01c8: background plane 2 addr
508 * 0x01cc: bg y stride for plane 0 and 1
509 * 0x01d0: bg y stride for plane 2
510 * 0x01d4: bg src PPP config
511 * 0x01d8: unpack pattern
512 */
513 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01c0, bg0_addr);
514 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01c4, bg1_addr);
515
516 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01cc,
517 (bg1_ystride << 16) | bg0_ystride);
518 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01d4, ppp_src_cfg_reg);
519
520 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01d8, unpack_pattern);
521}
522
523#define IS_PSEUDOPLNR(img) ((img == MDP_Y_CRCB_H2V2) | \
524 (img == MDP_Y_CBCR_H2V2) | \
525 (img == MDP_Y_CRCB_H2V1) | \
526 (img == MDP_Y_CBCR_H2V1))
527
528#define IMG_LEN(rect_h, w, rect_w, bpp) (((rect_h) * w) * bpp)
529
530#define Y_TO_CRCB_RATIO(format) \
531 ((format == MDP_Y_CBCR_H2V2 || format == MDP_Y_CRCB_H2V2) ? 2 :\
532 (format == MDP_Y_CBCR_H2V1 || format == MDP_Y_CRCB_H2V1) ? 1 : 1)
533
534static void get_len(struct mdp_img *img, struct mdp_rect *rect, uint32_t bpp,
535 uint32_t *len0, uint32_t *len1)
536{
537 *len0 = IMG_LEN(rect->h, img->width, rect->w, bpp);
538 if (IS_PSEUDOPLNR(img->format))
539 *len1 = *len0/Y_TO_CRCB_RATIO(img->format);
540 else
541 *len1 = 0;
542}
543
544static void flush_imgs(struct mdp_blit_req *req, int src_bpp, int dst_bpp,
545 struct file *p_src_file, struct file *p_dst_file)
546{
547#ifdef CONFIG_ANDROID_PMEM
548 uint32_t src0_len, src1_len, dst0_len, dst1_len;
549
550 /* flush src images to memory before dma to mdp */
551 get_len(&req->src, &req->src_rect, src_bpp,
552 &src0_len, &src1_len);
553
554 flush_pmem_file(p_src_file,
555 req->src.offset, src0_len);
556
557 if (IS_PSEUDOPLNR(req->src.format))
558 flush_pmem_file(p_src_file,
559 req->src.offset + src0_len, src1_len);
560
561 get_len(&req->dst, &req->dst_rect, dst_bpp, &dst0_len, &dst1_len);
562 flush_pmem_file(p_dst_file, req->dst.offset, dst0_len);
563
564 if (IS_PSEUDOPLNR(req->dst.format))
565 flush_pmem_file(p_dst_file,
566 req->dst.offset + dst0_len, dst1_len);
567#endif
568}
569
570static void mdp_start_ppp(struct msm_fb_data_type *mfd, MDPIBUF *iBuf,
571struct mdp_blit_req *req, struct file *p_src_file, struct file *p_dst_file)
572{
573 uint8 *src0, *src1;
574 uint8 *dest0, *dest1;
575 uint16 inpBpp;
576 uint32 dest0_ystride;
577 uint32 src_width;
578 uint32 src_height;
579 uint32 src0_ystride;
580 uint32 dst_roi_width;
581 uint32 dst_roi_height;
582 uint32 ppp_src_cfg_reg, ppp_operation_reg, ppp_dst_cfg_reg;
583 uint32 alpha, tpVal;
584 uint32 packPattern;
585 uint32 dst_packPattern;
586 boolean inputRGB, outputRGB, pseudoplanr_output;
587 int sv_slice, sh_slice;
588 int dv_slice, dh_slice;
589 boolean perPixelAlpha = FALSE;
590 boolean ppp_lookUp_enable = FALSE;
591
592 sv_slice = sh_slice = dv_slice = dh_slice = 1;
593 alpha = tpVal = 0;
594 src_width = iBuf->mdpImg.width;
595 src_height = iBuf->roi.y + iBuf->roi.height;
596 src1 = NULL;
597 dest1 = NULL;
598
599 inputRGB = outputRGB = TRUE;
600 pseudoplanr_output = FALSE;
601 ppp_operation_reg = 0;
602 ppp_dst_cfg_reg = 0;
603 ppp_src_cfg_reg = 0;
604
605 /* Wait for the pipe to clear */
606 do { } while (mdp_ppp_pipe_wait() <= 0);
607
608 /*
609 * destination config
610 */
611 switch (iBuf->ibuf_type) {
612 case MDP_RGB_888:
613 dst_packPattern =
614 MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
615 ppp_dst_cfg_reg =
616 PPP_DST_C0G_8BIT | PPP_DST_C1B_8BIT | PPP_DST_C2R_8BIT |
617 PPP_DST_PACKET_CNT_INTERLVD_3ELEM | PPP_DST_PACK_TIGHT |
618 PPP_DST_PACK_ALIGN_LSB | PPP_DST_OUT_SEL_AXI |
619 PPP_DST_BPP_3BYTES | PPP_DST_PLANE_INTERLVD;
620 break;
621
622 case MDP_XRGB_8888:
623 case MDP_ARGB_8888:
624 case MDP_RGBA_8888:
625 if (iBuf->ibuf_type == MDP_BGRA_8888)
626 dst_packPattern =
627 MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
628 8);
629 else if (iBuf->ibuf_type == MDP_RGBA_8888)
630 dst_packPattern =
631 MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R,
632 8);
633 else
634 dst_packPattern =
635 MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
636 8);
637
638 ppp_dst_cfg_reg = PPP_DST_C0G_8BIT |
639 PPP_DST_C1B_8BIT |
640 PPP_DST_C2R_8BIT |
641 PPP_DST_C3A_8BIT |
642 PPP_DST_C3ALPHA_EN |
643 PPP_DST_PACKET_CNT_INTERLVD_4ELEM |
644 PPP_DST_PACK_TIGHT |
645 PPP_DST_PACK_ALIGN_LSB |
646 PPP_DST_OUT_SEL_AXI |
647 PPP_DST_BPP_4BYTES | PPP_DST_PLANE_INTERLVD;
648 break;
649
650 case MDP_Y_CBCR_H2V2:
651 case MDP_Y_CRCB_H2V2:
652 if (iBuf->ibuf_type == MDP_Y_CBCR_H2V2)
653 dst_packPattern =
654 MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
655 else
656 dst_packPattern =
657 MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
658
659 ppp_dst_cfg_reg = PPP_DST_C2R_8BIT |
660 PPP_DST_C0G_8BIT |
661 PPP_DST_C1B_8BIT |
662 PPP_DST_C3A_8BIT |
663 PPP_DST_PACKET_CNT_INTERLVD_2ELEM |
664 PPP_DST_PACK_TIGHT |
665 PPP_DST_PACK_ALIGN_LSB |
666 PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES;
667
668 ppp_operation_reg |= PPP_OP_DST_CHROMA_420;
669 outputRGB = FALSE;
670 pseudoplanr_output = TRUE;
671 /*
672 * vertically (y direction) and horizontally (x direction)
673 * sample reduction by 2
674 */
675
676 /*
677 * H2V2(YUV420) Cosite
678 *
679 * Y Y Y Y
680 * CbCr CbCr
681 * Y Y Y Y
682 * Y Y Y Y
683 * CbCr CbCr
684 * Y Y Y Y
685 */
686 dv_slice = dh_slice = 2;
687
688 /* (x,y) and (width,height) must be even numbern */
689 iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2;
690 iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2;
691 iBuf->roi.x = (iBuf->roi.x / 2) * 2;
692 iBuf->roi.width = (iBuf->roi.width / 2) * 2;
693
694 iBuf->roi.lcd_y = (iBuf->roi.lcd_y / 2) * 2;
695 iBuf->roi.dst_height = (iBuf->roi.dst_height / 2) * 2;
696 iBuf->roi.y = (iBuf->roi.y / 2) * 2;
697 iBuf->roi.height = (iBuf->roi.height / 2) * 2;
698 break;
699
700 case MDP_YCRYCB_H2V1:
701 dst_packPattern =
702 MDP_GET_PACK_PATTERN(CLR_Y, CLR_CR, CLR_Y, CLR_CB, 8);
703 ppp_dst_cfg_reg =
704 PPP_DST_C2R_8BIT | PPP_DST_C0G_8BIT | PPP_DST_C1B_8BIT |
705 PPP_DST_C3A_8BIT | PPP_DST_PACKET_CNT_INTERLVD_4ELEM |
706 PPP_DST_PACK_TIGHT | PPP_DST_PACK_ALIGN_LSB |
707 PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES |
708 PPP_DST_PLANE_INTERLVD;
709
710 ppp_operation_reg |= PPP_OP_DST_CHROMA_H2V1;
711 outputRGB = FALSE;
712 /*
713 * horizontally (x direction) sample reduction by 2
714 *
715 * H2V1(YUV422) Cosite
716 *
717 * YCbCr Y YCbCr Y
718 * YCbCr Y YCbCr Y
719 * YCbCr Y YCbCr Y
720 * YCbCr Y YCbCr Y
721 */
722 dh_slice = 2;
723
724 /*
725 * if it's TV-Out/MDP_YCRYCB_H2V1, let's go through the
726 * preloaded gamma setting of 2.2 when the content is
727 * non-linear ppp_lookUp_enable = TRUE;
728 */
729
730 /* x and width must be even number */
731 iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2;
732 iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2;
733 iBuf->roi.x = (iBuf->roi.x / 2) * 2;
734 iBuf->roi.width = (iBuf->roi.width / 2) * 2;
735 break;
736
737 case MDP_Y_CBCR_H2V1:
738 case MDP_Y_CRCB_H2V1:
739 if (iBuf->ibuf_type == MDP_Y_CBCR_H2V1)
740 dst_packPattern =
741 MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
742 else
743 dst_packPattern =
744 MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
745
746 ppp_dst_cfg_reg = PPP_DST_C2R_8BIT |
747 PPP_DST_C0G_8BIT |
748 PPP_DST_C1B_8BIT |
749 PPP_DST_C3A_8BIT |
750 PPP_DST_PACKET_CNT_INTERLVD_2ELEM |
751 PPP_DST_PACK_TIGHT |
752 PPP_DST_PACK_ALIGN_LSB |
753 PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES;
754
755 ppp_operation_reg |= PPP_OP_DST_CHROMA_H2V1;
756 outputRGB = FALSE;
757 pseudoplanr_output = TRUE;
758 /* horizontally (x direction) sample reduction by 2 */
759 dh_slice = 2;
760
761 /* x and width must be even number */
762 iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2;
763 iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2;
764 iBuf->roi.x = (iBuf->roi.x / 2) * 2;
765 iBuf->roi.width = (iBuf->roi.width / 2) * 2;
766 break;
767
768 case MDP_BGR_565:
769 case MDP_RGB_565:
770 default:
771 if (iBuf->ibuf_type == MDP_RGB_565)
772 dst_packPattern =
773 MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
774 else
775 dst_packPattern =
776 MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8);
777
778 ppp_dst_cfg_reg = PPP_DST_C0G_6BIT |
779 PPP_DST_C1B_5BIT |
780 PPP_DST_C2R_5BIT |
781 PPP_DST_PACKET_CNT_INTERLVD_3ELEM |
782 PPP_DST_PACK_TIGHT |
783 PPP_DST_PACK_ALIGN_LSB |
784 PPP_DST_OUT_SEL_AXI |
785 PPP_DST_BPP_2BYTES | PPP_DST_PLANE_INTERLVD;
786 break;
787 }
788
789 /* source config */
790 switch (iBuf->mdpImg.imgType) {
791 case MDP_RGB_888:
792 inpBpp = 3;
793 /*
794 * 565 = 2bytes
795 * RGB = 3Components
796 * RGB interleaved
797 */
798 ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
799 PPP_SRC_C1B_8BITS | PPP_SRC_BPP_INTERLVD_3BYTES |
800 PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT |
801 PPP_SRC_UNPACK_ALIGN_LSB |
802 PPP_SRC_FETCH_PLANES_INTERLVD;
803
804 packPattern = MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
805
806 ppp_operation_reg |= PPP_OP_COLOR_SPACE_RGB |
807 PPP_OP_SRC_CHROMA_RGB | PPP_OP_DST_CHROMA_RGB;
808 break;
809
810 case MDP_BGRA_8888:
811 case MDP_RGBA_8888:
812 case MDP_ARGB_8888:
813 perPixelAlpha = TRUE;
814 case MDP_XRGB_8888:
815 inpBpp = 4;
816 /*
817 * 8888 = 4bytes
818 * ARGB = 4Components
819 * ARGB interleaved
820 */
821 ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
822 PPP_SRC_C1B_8BITS | PPP_SRC_C3A_8BITS |
823 PPP_SRC_C3_ALPHA_EN | PPP_SRC_BPP_INTERLVD_4BYTES |
824 PPP_SRC_INTERLVD_4COMPONENTS | PPP_SRC_UNPACK_TIGHT |
825 PPP_SRC_UNPACK_ALIGN_LSB |
826 PPP_SRC_FETCH_PLANES_INTERLVD;
827
828 if (iBuf->mdpImg.imgType == MDP_BGRA_8888)
829 packPattern =
830 MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
831 8);
832 else if (iBuf->mdpImg.imgType == MDP_RGBA_8888)
833 packPattern =
834 MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R,
835 8);
836 else
837 packPattern =
838 MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
839 8);
840
841 ppp_operation_reg |= PPP_OP_COLOR_SPACE_RGB |
842 PPP_OP_SRC_CHROMA_RGB | PPP_OP_DST_CHROMA_RGB;
843 break;
844
845 case MDP_Y_CBCR_H2V2:
846 case MDP_Y_CRCB_H2V2:
847 inpBpp = 1;
848 src1 = (uint8 *) iBuf->mdpImg.cbcr_addr;
849
850 /*
851 * CbCr = 2bytes
852 * CbCr = 2Components
853 * Y+CbCr
854 */
855 ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
856 PPP_SRC_C1B_8BITS | PPP_SRC_BPP_INTERLVD_2BYTES |
857 PPP_SRC_INTERLVD_2COMPONENTS | PPP_SRC_UNPACK_TIGHT |
858 PPP_SRC_UNPACK_ALIGN_LSB |
859 PPP_SRC_FETCH_PLANES_PSEUDOPLNR;
860
861 if (iBuf->mdpImg.imgType == MDP_Y_CRCB_H2V2)
862 packPattern =
863 MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
864 else
865 packPattern =
866 MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
867
868 ppp_operation_reg |= PPP_OP_COLOR_SPACE_YCBCR |
869 PPP_OP_SRC_CHROMA_420 |
870 PPP_OP_SRC_CHROMA_COSITE |
871 PPP_OP_DST_CHROMA_RGB | PPP_OP_DST_CHROMA_COSITE;
872
873 inputRGB = FALSE;
874 sh_slice = sv_slice = 2;
875 break;
876
877 case MDP_YCRYCB_H2V1:
878 inpBpp = 2;
879 ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
880 PPP_SRC_C0G_8BITS |
881 PPP_SRC_C1B_8BITS |
882 PPP_SRC_C3A_8BITS |
883 PPP_SRC_BPP_INTERLVD_2BYTES |
884 PPP_SRC_INTERLVD_4COMPONENTS |
885 PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB;
886
887 packPattern =
888 MDP_GET_PACK_PATTERN(CLR_Y, CLR_CR, CLR_Y, CLR_CB, 8);
889
890 ppp_operation_reg |= PPP_OP_SRC_CHROMA_H2V1 |
891 PPP_OP_SRC_CHROMA_COSITE | PPP_OP_DST_CHROMA_COSITE;
892
893 /*
894 * if it's TV-Out/MDP_YCRYCB_H2V1, let's go through the
895 * preloaded inverse gamma setting of 2.2 since they're
896 * symetric when the content is non-linear
897 * ppp_lookUp_enable = TRUE;
898 */
899
900 /* x and width must be even number */
901 iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2;
902 iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2;
903 iBuf->roi.x = (iBuf->roi.x / 2) * 2;
904 iBuf->roi.width = (iBuf->roi.width / 2) * 2;
905
906 inputRGB = FALSE;
907 sh_slice = 2;
908 break;
909
910 case MDP_Y_CBCR_H2V1:
911 case MDP_Y_CRCB_H2V1:
912 inpBpp = 1;
913 src1 = (uint8 *) iBuf->mdpImg.cbcr_addr;
914
915 ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
916 PPP_SRC_C0G_8BITS |
917 PPP_SRC_C1B_8BITS |
918 PPP_SRC_C3A_8BITS |
919 PPP_SRC_BPP_INTERLVD_2BYTES |
920 PPP_SRC_INTERLVD_2COMPONENTS |
921 PPP_SRC_UNPACK_TIGHT |
922 PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_PSEUDOPLNR;
923
924 if (iBuf->mdpImg.imgType == MDP_Y_CBCR_H2V1)
925 packPattern =
926 MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
927 else
928 packPattern =
929 MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
930
931 ppp_operation_reg |= PPP_OP_SRC_CHROMA_H2V1 |
932 PPP_OP_SRC_CHROMA_COSITE | PPP_OP_DST_CHROMA_COSITE;
933 inputRGB = FALSE;
934 sh_slice = 2;
935 break;
936
937 case MDP_BGR_565:
938 case MDP_RGB_565:
939 default:
940 inpBpp = 2;
941 /*
942 * 565 = 2bytes
943 * RGB = 3Components
944 * RGB interleaved
945 */
946 ppp_src_cfg_reg = PPP_SRC_C2R_5BITS | PPP_SRC_C0G_6BITS |
947 PPP_SRC_C1B_5BITS | PPP_SRC_BPP_INTERLVD_2BYTES |
948 PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT |
949 PPP_SRC_UNPACK_ALIGN_LSB |
950 PPP_SRC_FETCH_PLANES_INTERLVD;
951
952 if (iBuf->mdpImg.imgType == MDP_RGB_565)
953 packPattern =
954 MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
955 else
956 packPattern =
957 MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8);
958
959 ppp_operation_reg |= PPP_OP_COLOR_SPACE_RGB |
960 PPP_OP_SRC_CHROMA_RGB | PPP_OP_DST_CHROMA_RGB;
961 break;
962
963 }
964
965 if (pseudoplanr_output)
966 ppp_dst_cfg_reg |= PPP_DST_PLANE_PSEUDOPLN;
967
968 /* YCbCr to RGB color conversion flag */
969 if ((!inputRGB) && (outputRGB)) {
970 ppp_operation_reg |= PPP_OP_CONVERT_YCBCR2RGB |
971 PPP_OP_CONVERT_ON;
972
973 /*
974 * primary/secondary is sort of misleading term...but
975 * in mdp2.2/3.0 we only use primary matrix (forward/rev)
976 * in mdp3.1 we use set1(prim) and set2(secd)
977 */
978#ifdef CONFIG_FB_MSM_MDP31
979 ppp_operation_reg |= PPP_OP_CONVERT_MATRIX_SECONDARY |
980 PPP_OP_DST_RGB;
981 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0240, 0);
982#endif
983
984 if (ppp_lookUp_enable) {
985 ppp_operation_reg |= PPP_OP_LUT_C0_ON |
986 PPP_OP_LUT_C1_ON | PPP_OP_LUT_C2_ON;
987 }
988 }
989 /* RGB to YCbCr color conversion flag */
990 if ((inputRGB) && (!outputRGB)) {
991 ppp_operation_reg |= PPP_OP_CONVERT_RGB2YCBCR |
992 PPP_OP_CONVERT_ON;
993
994#ifdef CONFIG_FB_MSM_MDP31
995 ppp_operation_reg |= PPP_OP_CONVERT_MATRIX_PRIMARY |
996 PPP_OP_DST_YCBCR;
997 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0240, 0x1e);
998#endif
999
1000 if (ppp_lookUp_enable) {
1001 ppp_operation_reg |= PPP_OP_LUT_C0_ON |
1002 PPP_OP_LUT_C1_ON | PPP_OP_LUT_C2_ON;
1003 }
1004 }
1005 /* YCbCr to YCbCr color conversion flag */
1006 if ((!inputRGB) && (!outputRGB)) {
1007 if ((ppp_lookUp_enable) &&
1008 (iBuf->mdpImg.imgType != iBuf->ibuf_type)) {
1009 ppp_operation_reg |= PPP_OP_LUT_C0_ON;
1010 }
1011 }
1012
1013 ppp_src_cfg_reg |= (iBuf->roi.x % 2) ? PPP_SRC_BPP_ROI_ODD_X : 0;
1014 ppp_src_cfg_reg |= (iBuf->roi.y % 2) ? PPP_SRC_BPP_ROI_ODD_Y : 0;
1015
1016 if (req->flags & MDP_DEINTERLACE)
1017 ppp_operation_reg |= PPP_OP_DEINT_EN;
1018
1019 /* Dither at DMA side only since iBuf format is RGB888 */
1020 if (iBuf->mdpImg.mdpOp & MDPOP_DITHER)
1021 ppp_operation_reg |= PPP_OP_DITHER_EN;
1022
1023 if (iBuf->mdpImg.mdpOp & MDPOP_ROTATION) {
1024 ppp_operation_reg |= PPP_OP_ROT_ON;
1025
1026 if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) {
1027 ppp_operation_reg |= PPP_OP_ROT_90;
1028 }
1029 if (iBuf->mdpImg.mdpOp & MDPOP_LR) {
1030 ppp_operation_reg |= PPP_OP_FLIP_LR;
1031 }
1032 if (iBuf->mdpImg.mdpOp & MDPOP_UD) {
1033 ppp_operation_reg |= PPP_OP_FLIP_UD;
1034 }
1035 }
1036
1037 src0_ystride = src_width * inpBpp;
1038 dest0_ystride = iBuf->ibuf_width * iBuf->bpp;
1039
1040 /* no need to care about rotation since it's the real-XY. */
1041 dst_roi_width = iBuf->roi.dst_width;
1042 dst_roi_height = iBuf->roi.dst_height;
1043
1044 src0 = (uint8 *) iBuf->mdpImg.bmy_addr;
1045 dest0 = (uint8 *) iBuf->buf;
1046
1047 /* Jumping from Y-Plane to Chroma Plane */
1048 dest1 = mdp_get_chroma_addr(iBuf);
1049
1050 /* first pixel addr calculation */
1051 mdp_adjust_start_addr(&src0, &src1, sv_slice, sh_slice, iBuf->roi.x,
1052 iBuf->roi.y, src_width, src_height, inpBpp, iBuf,
1053 0);
1054 mdp_adjust_start_addr(&dest0, &dest1, dv_slice, dh_slice,
1055 iBuf->roi.lcd_x, iBuf->roi.lcd_y,
1056 iBuf->ibuf_width, iBuf->ibuf_height, iBuf->bpp,
1057 iBuf, 2);
1058
1059 /* set scale operation */
1060 mdp_set_scale(iBuf, dst_roi_width, dst_roi_height,
1061 inputRGB, outputRGB, &ppp_operation_reg);
1062
1063 /*
1064 * setting background source for blending
1065 */
1066 mdp_set_blend_attr(iBuf, &alpha, &tpVal, perPixelAlpha,
1067 &ppp_operation_reg);
1068
1069 if (ppp_operation_reg & PPP_OP_BLEND_ON) {
1070 mdp_ppp_setbg(iBuf);
1071
1072 if (iBuf->ibuf_type == MDP_YCRYCB_H2V1) {
1073 ppp_operation_reg |= PPP_OP_BG_CHROMA_H2V1;
1074
1075 if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP) {
1076 tpVal = mdp_conv_matx_rgb2yuv(tpVal,
1077 (uint16 *) &
1078 mdp_ccs_rgb2yuv,
1079 &mdp_plv[0], NULL);
1080 }
1081 }
1082 }
1083
1084 /*
1085 * 0x0004: enable dbg bus
1086 * 0x0100: "don't care" Edge Condit until scaling is on
1087 * 0x0104: xrc tile x&y size u7.6 format = 7bit.6bit
1088 * 0x0108: src pixel size
1089 * 0x010c: component plane 0 starting address
1090 * 0x011c: component plane 0 ystride
1091 * 0x0124: PPP source config register
1092 * 0x0128: unpacked pattern from lsb to msb (eg. RGB->BGR)
1093 */
1094 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0108, (iBuf->roi.height << 16 |
1095 iBuf->roi.width));
1096 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x010c, src0); /* comp.plane 0 */
1097 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0110, src1); /* comp.plane 1 */
1098 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x011c,
1099 (src0_ystride << 16 | src0_ystride));
1100
1101 /* setup for rgb 565 */
1102 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0124, ppp_src_cfg_reg);
1103 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0128, packPattern);
1104 /*
1105 * 0x0138: PPP destination operation register
1106 * 0x014c: constant_alpha|transparent_color
1107 * 0x0150: PPP destination config register
1108 * 0x0154: PPP packing pattern
1109 */
1110 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0138, ppp_operation_reg);
1111 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x014c, alpha << 24 | tpVal);
1112 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0150, ppp_dst_cfg_reg);
1113 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0154, dst_packPattern);
1114
1115 /*
1116 * 0x0164: ROI height and width
1117 * 0x0168: Component Plane 0 starting addr
1118 * 0x016c: Component Plane 1 starting addr
1119 * 0x0178: Component Plane 1/0 y stride
1120 */
1121 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0164,
1122 (dst_roi_height << 16 | dst_roi_width));
1123 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0168, dest0);
1124 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x016c, dest1);
1125 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0178,
1126 (dest0_ystride << 16 | dest0_ystride));
1127
1128 flush_imgs(req, inpBpp, iBuf->bpp, p_src_file, p_dst_file);
1129#ifdef CONFIG_MDP_PPP_ASYNC_OP
1130 mdp_ppp_process_curr_djob();
1131#else
1132 mdp_pipe_kickoff(MDP_PPP_TERM, mfd);
1133#endif
1134}
1135
1136static int mdp_ppp_verify_req(struct mdp_blit_req *req)
1137{
1138 u32 src_width, src_height, dst_width, dst_height;
1139
1140 if (req == NULL)
1141 return -1;
1142
1143 if (MDP_IS_IMGTYPE_BAD(req->src.format) ||
1144 MDP_IS_IMGTYPE_BAD(req->dst.format))
1145 return -1;
1146
1147 if ((req->src.width == 0) || (req->src.height == 0) ||
1148 (req->src_rect.w == 0) || (req->src_rect.h == 0) ||
1149 (req->dst.width == 0) || (req->dst.height == 0) ||
1150 (req->dst_rect.w == 0) || (req->dst_rect.h == 0))
1151
1152 return -1;
1153
1154 if (((req->src_rect.x + req->src_rect.w) > req->src.width) ||
1155 ((req->src_rect.y + req->src_rect.h) > req->src.height))
1156 return -1;
1157
1158 if (((req->dst_rect.x + req->dst_rect.w) > req->dst.width) ||
1159 ((req->dst_rect.y + req->dst_rect.h) > req->dst.height))
1160 return -1;
1161
1162 /*
1163 * scaling range check
1164 */
1165 src_width = req->src_rect.w;
1166 src_height = req->src_rect.h;
1167
1168 if (req->flags & MDP_ROT_90) {
1169 dst_width = req->dst_rect.h;
1170 dst_height = req->dst_rect.w;
1171 } else {
1172 dst_width = req->dst_rect.w;
1173 dst_height = req->dst_rect.h;
1174 }
1175
1176 switch (req->dst.format) {
1177 case MDP_Y_CRCB_H2V2:
1178 case MDP_Y_CBCR_H2V2:
1179 src_width = (src_width / 2) * 2;
1180 src_height = (src_height / 2) * 2;
1181 dst_width = (src_width / 2) * 2;
1182 dst_height = (src_height / 2) * 2;
1183 break;
1184
1185 case MDP_Y_CRCB_H2V1:
1186 case MDP_Y_CBCR_H2V1:
1187 case MDP_YCRYCB_H2V1:
1188 src_width = (src_width / 2) * 2;
1189 dst_width = (src_width / 2) * 2;
1190 break;
1191
1192 default:
1193 break;
1194 }
1195
1196 if (((MDP_SCALE_Q_FACTOR * dst_width) / src_width >
1197 MDP_MAX_X_SCALE_FACTOR)
1198 || ((MDP_SCALE_Q_FACTOR * dst_width) / src_width <
1199 MDP_MIN_X_SCALE_FACTOR))
1200 return -1;
1201
1202 if (((MDP_SCALE_Q_FACTOR * dst_height) / src_height >
1203 MDP_MAX_Y_SCALE_FACTOR)
1204 || ((MDP_SCALE_Q_FACTOR * dst_height) / src_height <
1205 MDP_MIN_Y_SCALE_FACTOR))
1206 return -1;
1207
1208 return 0;
1209}
1210
1211/**
1212 * get_gem_img() - retrieve drm obj's start address and size
1213 * @img: contains drm file descriptor and gem handle
1214 * @start: repository of starting address of drm obj allocated memory
1215 * @len: repository of size of drm obj alloacted memory
1216 *
1217 **/
1218int get_gem_img(struct mdp_img *img, unsigned long *start, unsigned long *len)
1219{
1220 panic("waaaaaaaah");
1221 //return kgsl_gem_obj_addr(img->memory_id, (int)img->priv, start, len);
1222}
1223
1224int get_img(struct mdp_img *img, struct fb_info *info, unsigned long *start,
1225 unsigned long *len, struct file **pp_file)
1226{
1227 int put_needed, ret = 0;
1228 struct file *file;
1229 unsigned long vstart;
1230#ifdef CONFIG_ANDROID_PMEM
1231 if (!get_pmem_file(img->memory_id, start, &vstart, len, pp_file))
1232 return 0;
1233#endif
1234 file = fget_light(img->memory_id, &put_needed);
1235 if (file == NULL)
1236 return -1;
1237
1238 if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
1239 *start = info->fix.smem_start;
1240 *len = info->fix.smem_len;
1241 *pp_file = file;
1242 } else {
1243 ret = -1;
1244 fput_light(file, put_needed);
1245 }
1246 return ret;
1247}
1248
1249int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req,
1250 struct file **pp_src_file, struct file **pp_dst_file)
1251{
1252 unsigned long src_start, dst_start;
1253 unsigned long src_len = 0;
1254 unsigned long dst_len = 0;
1255 MDPIBUF iBuf;
1256 u32 dst_width, dst_height;
1257 struct file *p_src_file = 0 , *p_dst_file = 0;
1258 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
1259
1260 if (req->dst.format == MDP_FB_FORMAT)
1261 req->dst.format = mfd->fb_imgType;
1262 if (req->src.format == MDP_FB_FORMAT)
1263 req->src.format = mfd->fb_imgType;
1264
1265 if (req->flags & MDP_BLIT_SRC_GEM) {
1266 if (get_gem_img(&req->src, &src_start, &src_len) < 0)
1267 return -1;
1268 } else {
1269 get_img(&req->src, info, &src_start, &src_len, &p_src_file);
1270 }
1271 if (src_len == 0) {
1272 printk(KERN_ERR "mdp_ppp: could not retrieve image from "
1273 "memory\n");
1274 return -1;
1275 }
1276
1277 if (req->flags & MDP_BLIT_DST_GEM) {
1278 if (get_gem_img(&req->dst, &dst_start, &dst_len) < 0)
1279 return -1;
1280 } else {
1281 get_img(&req->dst, info, &dst_start, &dst_len, &p_dst_file);
1282 }
1283 if (dst_len == 0) {
1284 printk(KERN_ERR "mdp_ppp: could not retrieve image from "
1285 "memory\n");
1286 return -1;
1287 }
1288 *pp_src_file = p_src_file;
1289 *pp_dst_file = p_dst_file;
1290 if (mdp_ppp_verify_req(req)) {
1291 printk(KERN_ERR "mdp_ppp: invalid image!\n");
1292 return -1;
1293 }
1294
1295 iBuf.ibuf_width = req->dst.width;
1296 iBuf.ibuf_height = req->dst.height;
1297 iBuf.bpp = bytes_per_pixel[req->dst.format];
1298
1299 iBuf.ibuf_type = req->dst.format;
1300 iBuf.buf = (uint8 *) dst_start;
1301 iBuf.buf += req->dst.offset;
1302
1303 iBuf.roi.lcd_x = req->dst_rect.x;
1304 iBuf.roi.lcd_y = req->dst_rect.y;
1305 iBuf.roi.dst_width = req->dst_rect.w;
1306 iBuf.roi.dst_height = req->dst_rect.h;
1307
1308 iBuf.roi.x = req->src_rect.x;
1309 iBuf.roi.width = req->src_rect.w;
1310 iBuf.roi.y = req->src_rect.y;
1311 iBuf.roi.height = req->src_rect.h;
1312
1313 iBuf.mdpImg.width = req->src.width;
1314 iBuf.mdpImg.imgType = req->src.format;
1315
1316 iBuf.mdpImg.bmy_addr = (uint32 *) (src_start + req->src.offset);
1317 iBuf.mdpImg.cbcr_addr =
1318 (uint32 *) ((uint32) iBuf.mdpImg.bmy_addr +
1319 req->src.width * req->src.height);
1320
1321 iBuf.mdpImg.mdpOp = MDPOP_NOP;
1322
1323 /* blending check */
1324 if (req->transp_mask != MDP_TRANSP_NOP) {
1325 iBuf.mdpImg.mdpOp |= MDPOP_TRANSP;
1326 iBuf.mdpImg.tpVal = req->transp_mask;
1327 iBuf.mdpImg.tpVal = mdp_calc_tpval(&iBuf.mdpImg);
1328 }
1329
1330 req->alpha &= 0xff;
1331 if (req->alpha < MDP_ALPHA_NOP) {
1332 iBuf.mdpImg.mdpOp |= MDPOP_ALPHAB;
1333 iBuf.mdpImg.alpha = req->alpha;
1334 }
1335
1336 /* rotation check */
1337 if (req->flags & MDP_FLIP_LR)
1338 iBuf.mdpImg.mdpOp |= MDPOP_LR;
1339 if (req->flags & MDP_FLIP_UD)
1340 iBuf.mdpImg.mdpOp |= MDPOP_UD;
1341 if (req->flags & MDP_ROT_90)
1342 iBuf.mdpImg.mdpOp |= MDPOP_ROT90;
1343 if (req->flags & MDP_DITHER)
1344 iBuf.mdpImg.mdpOp |= MDPOP_DITHER;
1345
1346 if (req->flags & MDP_BLEND_FG_PREMULT) {
1347#ifdef CONFIG_FB_MSM_MDP31
1348 iBuf.mdpImg.mdpOp |= MDPOP_FG_PM_ALPHA;
1349#else
1350 return -EINVAL;
1351#endif
1352 }
1353
1354 if (req->flags & MDP_DEINTERLACE) {
1355#ifdef CONFIG_FB_MSM_MDP31
1356 if ((req->src.format != MDP_Y_CBCR_H2V2) &&
1357 (req->src.format != MDP_Y_CRCB_H2V2))
1358#endif
1359 return -EINVAL;
1360 }
1361
1362 /* scale check */
1363 if (req->flags & MDP_ROT_90) {
1364 dst_width = req->dst_rect.h;
1365 dst_height = req->dst_rect.w;
1366 } else {
1367 dst_width = req->dst_rect.w;
1368 dst_height = req->dst_rect.h;
1369 }
1370
1371 if ((iBuf.roi.width != dst_width) || (iBuf.roi.height != dst_height))
1372 iBuf.mdpImg.mdpOp |= MDPOP_ASCALE;
1373
1374 if (req->flags & MDP_BLUR) {
1375#ifdef CONFIG_FB_MSM_MDP31
1376 if (req->flags & MDP_SHARPENING)
1377 printk(KERN_WARNING
1378 "mdp: MDP_SHARPENING is set with MDP_BLUR!\n");
1379 req->flags |= MDP_SHARPENING;
1380 req->sharpening_strength = -127;
1381#else
1382 iBuf.mdpImg.mdpOp |= MDPOP_ASCALE | MDPOP_BLUR;
1383
1384#endif
1385 }
1386
1387 if (req->flags & MDP_SHARPENING) {
1388#ifdef CONFIG_FB_MSM_MDP31
1389 if ((req->sharpening_strength > 127) ||
1390 (req->sharpening_strength < -127)) {
1391 printk(KERN_ERR
1392 "%s: sharpening strength out of range\n",
1393 __func__);
1394 return -EINVAL;
1395 }
1396
1397 iBuf.mdpImg.mdpOp |= MDPOP_ASCALE | MDPOP_SHARPENING;
1398 iBuf.mdpImg.sp_value = req->sharpening_strength & 0xff;
1399#else
1400 return -EINVAL;
1401#endif
1402 }
1403
1404 down(&mdp_ppp_mutex);
1405 /* MDP cmd block enable */
1406 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
1407
1408#ifdef CONFIG_FB_MSM_MDP31
1409 mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file);
1410#else
1411 /* bg tile fetching HW workaround */
1412 if (((iBuf.mdpImg.mdpOp & (MDPOP_TRANSP | MDPOP_ALPHAB)) ||
1413 (req->src.format == MDP_ARGB_8888) ||
1414 (req->src.format == MDP_BGRA_8888) ||
1415 (req->src.format == MDP_RGBA_8888)) &&
1416 (iBuf.mdpImg.mdpOp & MDPOP_ROT90) && (req->dst_rect.w <= 16)) {
1417 int dst_h, src_w, i;
1418
1419 src_w = req->src_rect.w;
1420 dst_h = iBuf.roi.dst_height;
1421
1422 for (i = 0; i < (req->dst_rect.h / 16); i++) {
1423 /* this tile size */
1424 iBuf.roi.dst_height = 16;
1425 iBuf.roi.width =
1426 (16 * req->src_rect.w) / req->dst_rect.h;
1427
1428 /* if it's out of scale range... */
1429 if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
1430 iBuf.roi.width) > MDP_MAX_X_SCALE_FACTOR)
1431 iBuf.roi.width =
1432 (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
1433 MDP_MAX_X_SCALE_FACTOR;
1434 else if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
1435 iBuf.roi.width) < MDP_MIN_X_SCALE_FACTOR)
1436 iBuf.roi.width =
1437 (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
1438 MDP_MIN_X_SCALE_FACTOR;
1439
1440 mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file);
1441
1442 /* next tile location */
1443 iBuf.roi.lcd_y += 16;
1444 iBuf.roi.x += iBuf.roi.width;
1445
1446 /* this is for a remainder update */
1447 dst_h -= 16;
1448 src_w -= iBuf.roi.width;
1449 }
1450
1451 if ((dst_h < 0) || (src_w < 0))
1452 printk
1453 ("msm_fb: mdp_blt_ex() unexpected result! line:%d\n",
1454 __LINE__);
1455
1456 /* remainder update */
1457 if ((dst_h > 0) && (src_w > 0)) {
1458 u32 tmp_v;
1459
1460 iBuf.roi.dst_height = dst_h;
1461 iBuf.roi.width = src_w;
1462
1463 if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
1464 iBuf.roi.width) > MDP_MAX_X_SCALE_FACTOR) {
1465 tmp_v =
1466 (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
1467 MDP_MAX_X_SCALE_FACTOR +
1468 (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) %
1469 MDP_MAX_X_SCALE_FACTOR ? 1 : 0;
1470
1471 /* move x location as roi width gets bigger */
1472 iBuf.roi.x -= tmp_v - iBuf.roi.width;
1473 iBuf.roi.width = tmp_v;
1474 } else
1475 if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
1476 iBuf.roi.width) < MDP_MIN_X_SCALE_FACTOR) {
1477 tmp_v =
1478 (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
1479 MDP_MIN_X_SCALE_FACTOR +
1480 (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) %
1481 MDP_MIN_X_SCALE_FACTOR ? 1 : 0;
1482
1483 /*
1484 * we don't move x location for continuity of
1485 * source image
1486 */
1487 iBuf.roi.width = tmp_v;
1488 }
1489
1490 mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file);
1491 }
1492 } else {
1493 mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file);
1494 }
1495#endif
1496
1497 /* MDP cmd block disable */
1498 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
1499 up(&mdp_ppp_mutex);
1500
1501 return 0;
1502}
diff --git a/drivers/staging/msm/mdp_ppp_dq.c b/drivers/staging/msm/mdp_ppp_dq.c
new file mode 100644
index 000000000000..3dc1c0cc61f9
--- /dev/null
+++ b/drivers/staging/msm/mdp_ppp_dq.c
@@ -0,0 +1,347 @@
1/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include "mdp.h"
19
20static boolean mdp_ppp_intr_flag = FALSE;
21static boolean mdp_ppp_busy_flag = FALSE;
22
23/* Queue to keep track of the completed jobs for cleaning */
24static LIST_HEAD(mdp_ppp_djob_clnrq);
25static DEFINE_SPINLOCK(mdp_ppp_djob_clnrq_lock);
26
27/* Worker to cleanup Display Jobs */
28static struct workqueue_struct *mdp_ppp_djob_clnr;
29
30/* Display Queue (DQ) for MDP PPP Block */
31static LIST_HEAD(mdp_ppp_dq);
32static DEFINE_SPINLOCK(mdp_ppp_dq_lock);
33
34/* Current Display Job for MDP PPP */
35static struct mdp_ppp_djob *curr_djob;
36
37/* Track ret code for the last opeartion */
38static int mdp_ppp_ret_code;
39
40inline int mdp_ppp_get_ret_code(void)
41{
42 return mdp_ppp_ret_code;
43}
44
45/* Push <Reg, Val> pair into DQ (if available) to later
46 * program the MDP PPP Block */
47inline void mdp_ppp_outdw(uint32_t addr, uint32_t data)
48{
49 if (curr_djob) {
50
51 /* get the last node of the list. */
52 struct mdp_ppp_roi_cmd_set *node =
53 list_entry(curr_djob->roi_cmd_list.prev,
54 struct mdp_ppp_roi_cmd_set, node);
55
56 /* If a node is already full, create a new one and add it to
57 * the list (roi_cmd_list).
58 */
59 if (node->ncmds == MDP_PPP_ROI_NODE_SIZE) {
60 node = kmalloc(sizeof(struct mdp_ppp_roi_cmd_set),
61 GFP_KERNEL);
62 if (!node) {
63 printk(KERN_ERR
64 "MDP_PPP: not enough memory.\n");
65 mdp_ppp_ret_code = -EINVAL;
66 return;
67 }
68
69 /* no ROI commands initially */
70 node->ncmds = 0;
71
72 /* add one node to roi_cmd_list. */
73 list_add_tail(&node->node, &curr_djob->roi_cmd_list);
74 }
75
76 /* register ROI commands */
77 node->cmd[node->ncmds].reg = addr;
78 node->cmd[node->ncmds].val = data;
79 node->ncmds++;
80 } else
81 /* program MDP PPP block now */
82 outpdw((addr), (data));
83}
84
85/* Initialize DQ */
86inline void mdp_ppp_dq_init(void)
87{
88 mdp_ppp_djob_clnr = create_singlethread_workqueue("MDPDJobClnrThrd");
89}
90
91/* Release resources of a job (DJob). */
92static void mdp_ppp_del_djob(struct mdp_ppp_djob *job)
93{
94 struct mdp_ppp_roi_cmd_set *node, *tmp;
95
96 /* release mem */
97 mdp_ppp_put_img(job->p_src_file, job->p_dst_file);
98
99 /* release roi_cmd_list */
100 list_for_each_entry_safe(node, tmp, &job->roi_cmd_list, node) {
101 list_del(&node->node);
102 kfree(node);
103 }
104
105 /* release job struct */
106 kfree(job);
107}
108
109/* Worker thread to reclaim resources once a display job is done */
110static void mdp_ppp_djob_cleaner(struct work_struct *work)
111{
112 struct mdp_ppp_djob *job;
113
114 MDP_PPP_DEBUG_MSG("mdp ppp display job cleaner started \n");
115
116 /* cleanup display job */
117 job = container_of(work, struct mdp_ppp_djob, cleaner.work);
118 if (likely(work && job))
119 mdp_ppp_del_djob(job);
120}
121
122/* Create a new Display Job (DJob) */
123inline struct mdp_ppp_djob *mdp_ppp_new_djob(void)
124{
125 struct mdp_ppp_djob *job;
126 struct mdp_ppp_roi_cmd_set *node;
127
128 /* create a new djob */
129 job = kmalloc(sizeof(struct mdp_ppp_djob), GFP_KERNEL);
130 if (!job)
131 return NULL;
132
133 /* add the first node to curr_djob->roi_cmd_list */
134 node = kmalloc(sizeof(struct mdp_ppp_roi_cmd_set), GFP_KERNEL);
135 if (!node) {
136 kfree(job);
137 return NULL;
138 }
139
140 /* make this current djob container to keep track of the curr djob not
141 * used in the async path i.e. no sync needed
142 *
143 * Should not contain any references from the past djob
144 */
145 BUG_ON(curr_djob);
146 curr_djob = job;
147 INIT_LIST_HEAD(&curr_djob->roi_cmd_list);
148
149 /* no ROI commands initially */
150 node->ncmds = 0;
151 INIT_LIST_HEAD(&node->node);
152 list_add_tail(&node->node, &curr_djob->roi_cmd_list);
153
154 /* register this djob with the djob cleaner
155 * initializes 'work' data struct
156 */
157 INIT_DELAYED_WORK(&curr_djob->cleaner, mdp_ppp_djob_cleaner);
158 INIT_LIST_HEAD(&curr_djob->entry);
159
160 curr_djob->p_src_file = 0;
161 curr_djob->p_dst_file = 0;
162
163 return job;
164}
165
166/* Undo the effect of mdp_ppp_new_djob() */
167inline void mdp_ppp_clear_curr_djob(void)
168{
169 if (likely(curr_djob)) {
170 mdp_ppp_del_djob(curr_djob);
171 curr_djob = NULL;
172 }
173}
174
175/* Cleanup dirty djobs */
176static void mdp_ppp_flush_dirty_djobs(void *cond)
177{
178 unsigned long flags;
179 struct mdp_ppp_djob *job;
180
181 /* Flush the jobs from the djob clnr queue */
182 while (cond && test_bit(0, (unsigned long *)cond)) {
183
184 /* Until we are done with the cleanup queue */
185 spin_lock_irqsave(&mdp_ppp_djob_clnrq_lock, flags);
186 if (list_empty(&mdp_ppp_djob_clnrq)) {
187 spin_unlock_irqrestore(&mdp_ppp_djob_clnrq_lock, flags);
188 break;
189 }
190
191 MDP_PPP_DEBUG_MSG("flushing djobs ... loop \n");
192
193 /* Retrieve the job that needs to be cleaned */
194 job = list_entry(mdp_ppp_djob_clnrq.next,
195 struct mdp_ppp_djob, entry);
196 list_del_init(&job->entry);
197 spin_unlock_irqrestore(&mdp_ppp_djob_clnrq_lock, flags);
198
199 /* Keep mem state coherent */
200 msm_fb_ensure_mem_coherency_after_dma(job->info, &job->req, 1);
201
202 /* Schedule jobs for cleanup
203 * A seperate worker thread does this */
204 queue_delayed_work(mdp_ppp_djob_clnr, &job->cleaner,
205 mdp_timer_duration);
206 }
207}
208
209/* If MDP PPP engine is busy, wait until it is available again */
210void mdp_ppp_wait(void)
211{
212 unsigned long flags;
213 int cond = 1;
214
215 /* keep flushing dirty djobs as long as MDP PPP engine is busy */
216 mdp_ppp_flush_dirty_djobs(&mdp_ppp_busy_flag);
217
218 /* block if MDP PPP engine is still busy */
219 spin_lock_irqsave(&mdp_ppp_dq_lock, flags);
220 if (test_bit(0, (unsigned long *)&mdp_ppp_busy_flag)) {
221
222 /* prepare for the wakeup event */
223 test_and_set_bit(0, (unsigned long *)&mdp_ppp_waiting);
224 INIT_COMPLETION(mdp_ppp_comp);
225 spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags);
226
227 /* block uninterruptibly until available */
228 MDP_PPP_DEBUG_MSG("waiting for mdp... \n");
229 wait_for_completion_killable(&mdp_ppp_comp);
230
231 /* if MDP PPP engine is still free,
232 * disable INT_MDP if enabled
233 */
234 spin_lock_irqsave(&mdp_ppp_dq_lock, flags);
235 if (!test_bit(0, (unsigned long *)&mdp_ppp_busy_flag) &&
236 test_and_clear_bit(0, (unsigned long *)&mdp_ppp_intr_flag))
237 mdp_disable_irq(MDP_PPP_TERM);
238 }
239 spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags);
240
241 /* flush remaining dirty djobs, if any */
242 mdp_ppp_flush_dirty_djobs(&cond);
243}
244
245/* Program MDP PPP block to process this ROI */
246static void mdp_ppp_process_roi(struct list_head *roi_cmd_list)
247{
248
249 /* program PPP engine with registered ROI commands */
250 struct mdp_ppp_roi_cmd_set *node;
251 list_for_each_entry(node, roi_cmd_list, node) {
252 int i = 0;
253 for (; i < node->ncmds; i++) {
254 MDP_PPP_DEBUG_MSG("%d: reg: 0x%x val: 0x%x \n",
255 i, node->cmd[i].reg, node->cmd[i].val);
256 outpdw(node->cmd[i].reg, node->cmd[i].val);
257 }
258 }
259
260 /* kickoff MDP PPP engine */
261 MDP_PPP_DEBUG_MSG("kicking off mdp \n");
262 outpdw(MDP_BASE + 0x30, 0x1000);
263}
264
265/* Submit this display job to MDP PPP engine */
266static void mdp_ppp_dispatch_djob(struct mdp_ppp_djob *job)
267{
268 /* enable INT_MDP if disabled */
269 if (!test_and_set_bit(0, (unsigned long *)&mdp_ppp_intr_flag))
270 mdp_enable_irq(MDP_PPP_TERM);
271
272 /* turn on PPP and CMD blocks */
273 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
274 mdp_pipe_ctrl(MDP_PPP_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
275
276 /* process this ROI */
277 mdp_ppp_process_roi(&job->roi_cmd_list);
278}
279
280/* Enqueue this display job to be cleaned up later in "mdp_ppp_djob_done" */
281static inline void mdp_ppp_enqueue_djob(struct mdp_ppp_djob *job)
282{
283 unsigned long flags;
284
285 spin_lock_irqsave(&mdp_ppp_dq_lock, flags);
286 list_add_tail(&job->entry, &mdp_ppp_dq);
287 spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags);
288}
289
290/* First enqueue display job for cleanup and dispatch immediately
291 * if MDP PPP engine is free */
292void mdp_ppp_process_curr_djob(void)
293{
294 /* enqueue djob */
295 mdp_ppp_enqueue_djob(curr_djob);
296
297 /* dispatch now if MDP PPP engine is free */
298 if (!test_and_set_bit(0, (unsigned long *)&mdp_ppp_busy_flag))
299 mdp_ppp_dispatch_djob(curr_djob);
300
301 /* done with the current djob */
302 curr_djob = NULL;
303}
304
305/* Called from mdp_isr - cleanup finished job and start with next
306 * if available else set MDP PPP engine free */
307void mdp_ppp_djob_done(void)
308{
309 struct mdp_ppp_djob *curr, *next;
310 unsigned long flags;
311
312 /* dequeue current */
313 spin_lock_irqsave(&mdp_ppp_dq_lock, flags);
314 curr = list_entry(mdp_ppp_dq.next, struct mdp_ppp_djob, entry);
315 list_del_init(&curr->entry);
316 spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags);
317
318 /* cleanup current - enqueue in the djob clnr queue */
319 spin_lock_irqsave(&mdp_ppp_djob_clnrq_lock, flags);
320 list_add_tail(&curr->entry, &mdp_ppp_djob_clnrq);
321 spin_unlock_irqrestore(&mdp_ppp_djob_clnrq_lock, flags);
322
323 /* grab next pending */
324 spin_lock_irqsave(&mdp_ppp_dq_lock, flags);
325 if (!list_empty(&mdp_ppp_dq)) {
326 next = list_entry(mdp_ppp_dq.next, struct mdp_ppp_djob,
327 entry);
328 spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags);
329
330 /* process next in the queue */
331 mdp_ppp_process_roi(&next->roi_cmd_list);
332 } else {
333 /* no pending display job */
334 spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags);
335
336 /* turn off PPP and CMD blocks - "in_isr" is TRUE */
337 mdp_pipe_ctrl(MDP_PPP_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
338 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
339
340 /* notify if waiting */
341 if (test_and_clear_bit(0, (unsigned long *)&mdp_ppp_waiting))
342 complete(&mdp_ppp_comp);
343
344 /* set free */
345 test_and_clear_bit(0, (unsigned long *)&mdp_ppp_busy_flag);
346 }
347}
diff --git a/drivers/staging/msm/mdp_ppp_dq.h b/drivers/staging/msm/mdp_ppp_dq.h
new file mode 100644
index 000000000000..03e4e9a5f234
--- /dev/null
+++ b/drivers/staging/msm/mdp_ppp_dq.h
@@ -0,0 +1,86 @@
1/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of Code Aurora Forum, Inc. nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29
30#ifndef MDP_PPP_DQ_H
31#define MDP_PPP_DQ_H
32
33#include "msm_fb_def.h"
34
35#define MDP_PPP_DEBUG_MSG MSM_FB_DEBUG
36
37/* The maximum number of <Reg,Val> pairs in an mdp_ppp_roi_cmd_set structure (a
38 * node)
39 */
40#define MDP_PPP_ROI_NODE_SIZE 32
41
42/* ROI config command (<Reg,Val> pair) for MDP PPP block */
43struct mdp_ppp_roi_cmd {
44 uint32_t reg;
45 uint32_t val;
46};
47
48/* ROI config commands for MDP PPP block are stored in a list of
49 * mdp_ppp_roi_cmd_set structures (nodes).
50 */
51struct mdp_ppp_roi_cmd_set {
52 struct list_head node;
53 uint32_t ncmds; /* number of commands in this set (node). */
54 struct mdp_ppp_roi_cmd cmd[MDP_PPP_ROI_NODE_SIZE];
55};
56
57/* MDP PPP Display Job (DJob) */
58struct mdp_ppp_djob {
59 struct list_head entry;
60 /* One ROI per MDP PPP DJob */
61 struct list_head roi_cmd_list;
62 struct mdp_blit_req req;
63 struct fb_info *info;
64 struct delayed_work cleaner;
65 struct file *p_src_file, *p_dst_file;
66};
67
68extern struct completion mdp_ppp_comp;
69extern boolean mdp_ppp_waiting;
70extern unsigned long mdp_timer_duration;
71
72unsigned int mdp_ppp_async_op_get(void);
73void mdp_ppp_async_op_set(unsigned int flag);
74void msm_fb_ensure_mem_coherency_after_dma(struct fb_info *info,
75 struct mdp_blit_req *req_list, int req_list_count);
76void mdp_ppp_put_img(struct file *p_src_file, struct file *p_dst_file);
77void mdp_ppp_dq_init(void);
78void mdp_ppp_outdw(uint32_t addr, uint32_t data);
79struct mdp_ppp_djob *mdp_ppp_new_djob(void);
80void mdp_ppp_clear_curr_djob(void);
81void mdp_ppp_process_curr_djob(void);
82int mdp_ppp_get_ret_code(void);
83void mdp_ppp_djob_done(void);
84void mdp_ppp_wait(void);
85
86#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
index 000000000000..b5b7271921e0
--- /dev/null
+++ b/drivers/staging/msm/mdp_ppp_v20.c
@@ -0,0 +1,2486 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/sched.h>
21#include <linux/time.h>
22#include <linux/init.h>
23#include <linux/interrupt.h>
24#include <linux/fb.h>
25#include "linux/proc_fs.h"
26
27#include <mach/hardware.h>
28#include <linux/io.h>
29
30#include <asm/system.h>
31#include <asm/mach-types.h>
32#include <linux/semaphore.h>
33#include <asm/div64.h>
34
35#include "mdp.h"
36#include "msm_fb.h"
37
38static MDP_SCALE_MODE mdp_curr_up_scale_xy;
39static MDP_SCALE_MODE mdp_curr_down_scale_x;
40static MDP_SCALE_MODE mdp_curr_down_scale_y;
41
42static long long mdp_do_div(long long num, long long den)
43{
44 do_div(num, den);
45 return num;
46}
47
48struct mdp_table_entry mdp_gaussian_blur_table[] = {
49 /* max variance */
50 { 0x5fffc, 0x20000080 },
51 { 0x50280, 0x20000080 },
52 { 0x5fffc, 0x20000080 },
53 { 0x50284, 0x20000080 },
54 { 0x5fffc, 0x20000080 },
55 { 0x50288, 0x20000080 },
56 { 0x5fffc, 0x20000080 },
57 { 0x5028c, 0x20000080 },
58 { 0x5fffc, 0x20000080 },
59 { 0x50290, 0x20000080 },
60 { 0x5fffc, 0x20000080 },
61 { 0x50294, 0x20000080 },
62 { 0x5fffc, 0x20000080 },
63 { 0x50298, 0x20000080 },
64 { 0x5fffc, 0x20000080 },
65 { 0x5029c, 0x20000080 },
66 { 0x5fffc, 0x20000080 },
67 { 0x502a0, 0x20000080 },
68 { 0x5fffc, 0x20000080 },
69 { 0x502a4, 0x20000080 },
70 { 0x5fffc, 0x20000080 },
71 { 0x502a8, 0x20000080 },
72 { 0x5fffc, 0x20000080 },
73 { 0x502ac, 0x20000080 },
74 { 0x5fffc, 0x20000080 },
75 { 0x502b0, 0x20000080 },
76 { 0x5fffc, 0x20000080 },
77 { 0x502b4, 0x20000080 },
78 { 0x5fffc, 0x20000080 },
79 { 0x502b8, 0x20000080 },
80 { 0x5fffc, 0x20000080 },
81 { 0x502bc, 0x20000080 },
82 { 0x5fffc, 0x20000080 },
83 { 0x502c0, 0x20000080 },
84 { 0x5fffc, 0x20000080 },
85 { 0x502c4, 0x20000080 },
86 { 0x5fffc, 0x20000080 },
87 { 0x502c8, 0x20000080 },
88 { 0x5fffc, 0x20000080 },
89 { 0x502cc, 0x20000080 },
90 { 0x5fffc, 0x20000080 },
91 { 0x502d0, 0x20000080 },
92 { 0x5fffc, 0x20000080 },
93 { 0x502d4, 0x20000080 },
94 { 0x5fffc, 0x20000080 },
95 { 0x502d8, 0x20000080 },
96 { 0x5fffc, 0x20000080 },
97 { 0x502dc, 0x20000080 },
98 { 0x5fffc, 0x20000080 },
99 { 0x502e0, 0x20000080 },
100 { 0x5fffc, 0x20000080 },
101 { 0x502e4, 0x20000080 },
102 { 0x5fffc, 0x20000080 },
103 { 0x502e8, 0x20000080 },
104 { 0x5fffc, 0x20000080 },
105 { 0x502ec, 0x20000080 },
106 { 0x5fffc, 0x20000080 },
107 { 0x502f0, 0x20000080 },
108 { 0x5fffc, 0x20000080 },
109 { 0x502f4, 0x20000080 },
110 { 0x5fffc, 0x20000080 },
111 { 0x502f8, 0x20000080 },
112 { 0x5fffc, 0x20000080 },
113 { 0x502fc, 0x20000080 },
114 { 0x5fffc, 0x20000080 },
115 { 0x50300, 0x20000080 },
116 { 0x5fffc, 0x20000080 },
117 { 0x50304, 0x20000080 },
118 { 0x5fffc, 0x20000080 },
119 { 0x50308, 0x20000080 },
120 { 0x5fffc, 0x20000080 },
121 { 0x5030c, 0x20000080 },
122 { 0x5fffc, 0x20000080 },
123 { 0x50310, 0x20000080 },
124 { 0x5fffc, 0x20000080 },
125 { 0x50314, 0x20000080 },
126 { 0x5fffc, 0x20000080 },
127 { 0x50318, 0x20000080 },
128 { 0x5fffc, 0x20000080 },
129 { 0x5031c, 0x20000080 },
130 { 0x5fffc, 0x20000080 },
131 { 0x50320, 0x20000080 },
132 { 0x5fffc, 0x20000080 },
133 { 0x50324, 0x20000080 },
134 { 0x5fffc, 0x20000080 },
135 { 0x50328, 0x20000080 },
136 { 0x5fffc, 0x20000080 },
137 { 0x5032c, 0x20000080 },
138 { 0x5fffc, 0x20000080 },
139 { 0x50330, 0x20000080 },
140 { 0x5fffc, 0x20000080 },
141 { 0x50334, 0x20000080 },
142 { 0x5fffc, 0x20000080 },
143 { 0x50338, 0x20000080 },
144 { 0x5fffc, 0x20000080 },
145 { 0x5033c, 0x20000080 },
146 { 0x5fffc, 0x20000080 },
147 { 0x50340, 0x20000080 },
148 { 0x5fffc, 0x20000080 },
149 { 0x50344, 0x20000080 },
150 { 0x5fffc, 0x20000080 },
151 { 0x50348, 0x20000080 },
152 { 0x5fffc, 0x20000080 },
153 { 0x5034c, 0x20000080 },
154 { 0x5fffc, 0x20000080 },
155 { 0x50350, 0x20000080 },
156 { 0x5fffc, 0x20000080 },
157 { 0x50354, 0x20000080 },
158 { 0x5fffc, 0x20000080 },
159 { 0x50358, 0x20000080 },
160 { 0x5fffc, 0x20000080 },
161 { 0x5035c, 0x20000080 },
162 { 0x5fffc, 0x20000080 },
163 { 0x50360, 0x20000080 },
164 { 0x5fffc, 0x20000080 },
165 { 0x50364, 0x20000080 },
166 { 0x5fffc, 0x20000080 },
167 { 0x50368, 0x20000080 },
168 { 0x5fffc, 0x20000080 },
169 { 0x5036c, 0x20000080 },
170 { 0x5fffc, 0x20000080 },
171 { 0x50370, 0x20000080 },
172 { 0x5fffc, 0x20000080 },
173 { 0x50374, 0x20000080 },
174 { 0x5fffc, 0x20000080 },
175 { 0x50378, 0x20000080 },
176 { 0x5fffc, 0x20000080 },
177 { 0x5037c, 0x20000080 },
178};
179
180static void load_scale_table(
181 struct mdp_table_entry *table, int len)
182{
183 int i;
184 for (i = 0; i < len; i++)
185 MDP_OUTP(MDP_BASE + table[i].reg, table[i].val);
186}
187
188static void mdp_load_pr_upscale_table(void)
189{
190 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
191 MDP_OUTP(MDP_BASE + 0x50200, 0x7fc00000);
192 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
193 MDP_OUTP(MDP_BASE + 0x50204, 0x7fc00000);
194 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
195 MDP_OUTP(MDP_BASE + 0x50208, 0x7fc00000);
196 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
197 MDP_OUTP(MDP_BASE + 0x5020c, 0x7fc00000);
198 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
199 MDP_OUTP(MDP_BASE + 0x50210, 0x7fc00000);
200 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
201 MDP_OUTP(MDP_BASE + 0x50214, 0x7fc00000);
202 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
203 MDP_OUTP(MDP_BASE + 0x50218, 0x7fc00000);
204 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
205 MDP_OUTP(MDP_BASE + 0x5021c, 0x7fc00000);
206 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
207 MDP_OUTP(MDP_BASE + 0x50220, 0x7fc00000);
208 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
209 MDP_OUTP(MDP_BASE + 0x50224, 0x7fc00000);
210 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
211 MDP_OUTP(MDP_BASE + 0x50228, 0x7fc00000);
212 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
213 MDP_OUTP(MDP_BASE + 0x5022c, 0x7fc00000);
214 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
215 MDP_OUTP(MDP_BASE + 0x50230, 0x7fc00000);
216 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
217 MDP_OUTP(MDP_BASE + 0x50234, 0x7fc00000);
218 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
219 MDP_OUTP(MDP_BASE + 0x50238, 0x7fc00000);
220 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
221 MDP_OUTP(MDP_BASE + 0x5023c, 0x7fc00000);
222 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
223 MDP_OUTP(MDP_BASE + 0x50240, 0x0);
224 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
225 MDP_OUTP(MDP_BASE + 0x50244, 0x0);
226 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
227 MDP_OUTP(MDP_BASE + 0x50248, 0x0);
228 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
229 MDP_OUTP(MDP_BASE + 0x5024c, 0x0);
230 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
231 MDP_OUTP(MDP_BASE + 0x50250, 0x0);
232 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
233 MDP_OUTP(MDP_BASE + 0x50254, 0x0);
234 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
235 MDP_OUTP(MDP_BASE + 0x50258, 0x0);
236 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
237 MDP_OUTP(MDP_BASE + 0x5025c, 0x0);
238 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
239 MDP_OUTP(MDP_BASE + 0x50260, 0x0);
240 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
241 MDP_OUTP(MDP_BASE + 0x50264, 0x0);
242 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
243 MDP_OUTP(MDP_BASE + 0x50268, 0x0);
244 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
245 MDP_OUTP(MDP_BASE + 0x5026c, 0x0);
246 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
247 MDP_OUTP(MDP_BASE + 0x50270, 0x0);
248 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
249 MDP_OUTP(MDP_BASE + 0x50274, 0x0);
250 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
251 MDP_OUTP(MDP_BASE + 0x50278, 0x0);
252 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
253 MDP_OUTP(MDP_BASE + 0x5027c, 0x0);
254}
255
256static void mdp_load_pr_downscale_table_x_point2TOpoint4(void)
257{
258 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
259 MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000);
260 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
261 MDP_OUTP(MDP_BASE + 0x50284, 0x7fc00000);
262 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
263 MDP_OUTP(MDP_BASE + 0x50288, 0x7fc00000);
264 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
265 MDP_OUTP(MDP_BASE + 0x5028c, 0x7fc00000);
266 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
267 MDP_OUTP(MDP_BASE + 0x50290, 0x7fc00000);
268 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
269 MDP_OUTP(MDP_BASE + 0x50294, 0x7fc00000);
270 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
271 MDP_OUTP(MDP_BASE + 0x50298, 0x7fc00000);
272 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
273 MDP_OUTP(MDP_BASE + 0x5029c, 0x7fc00000);
274 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
275 MDP_OUTP(MDP_BASE + 0x502a0, 0x7fc00000);
276 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
277 MDP_OUTP(MDP_BASE + 0x502a4, 0x7fc00000);
278 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
279 MDP_OUTP(MDP_BASE + 0x502a8, 0x7fc00000);
280 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
281 MDP_OUTP(MDP_BASE + 0x502ac, 0x7fc00000);
282 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
283 MDP_OUTP(MDP_BASE + 0x502b0, 0x7fc00000);
284 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
285 MDP_OUTP(MDP_BASE + 0x502b4, 0x7fc00000);
286 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
287 MDP_OUTP(MDP_BASE + 0x502b8, 0x7fc00000);
288 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
289 MDP_OUTP(MDP_BASE + 0x502bc, 0x7fc00000);
290 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
291 MDP_OUTP(MDP_BASE + 0x502c0, 0x0);
292 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
293 MDP_OUTP(MDP_BASE + 0x502c4, 0x0);
294 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
295 MDP_OUTP(MDP_BASE + 0x502c8, 0x0);
296 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
297 MDP_OUTP(MDP_BASE + 0x502cc, 0x0);
298 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
299 MDP_OUTP(MDP_BASE + 0x502d0, 0x0);
300 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
301 MDP_OUTP(MDP_BASE + 0x502d4, 0x0);
302 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
303 MDP_OUTP(MDP_BASE + 0x502d8, 0x0);
304 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
305 MDP_OUTP(MDP_BASE + 0x502dc, 0x0);
306 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
307 MDP_OUTP(MDP_BASE + 0x502e0, 0x0);
308 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
309 MDP_OUTP(MDP_BASE + 0x502e4, 0x0);
310 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
311 MDP_OUTP(MDP_BASE + 0x502e8, 0x0);
312 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
313 MDP_OUTP(MDP_BASE + 0x502ec, 0x0);
314 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
315 MDP_OUTP(MDP_BASE + 0x502f0, 0x0);
316 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
317 MDP_OUTP(MDP_BASE + 0x502f4, 0x0);
318 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
319 MDP_OUTP(MDP_BASE + 0x502f8, 0x0);
320 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
321 MDP_OUTP(MDP_BASE + 0x502fc, 0x0);
322}
323
324static void mdp_load_pr_downscale_table_y_point2TOpoint4(void)
325{
326 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
327 MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000);
328 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
329 MDP_OUTP(MDP_BASE + 0x50304, 0x7fc00000);
330 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
331 MDP_OUTP(MDP_BASE + 0x50308, 0x7fc00000);
332 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
333 MDP_OUTP(MDP_BASE + 0x5030c, 0x7fc00000);
334 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
335 MDP_OUTP(MDP_BASE + 0x50310, 0x7fc00000);
336 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
337 MDP_OUTP(MDP_BASE + 0x50314, 0x7fc00000);
338 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
339 MDP_OUTP(MDP_BASE + 0x50318, 0x7fc00000);
340 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
341 MDP_OUTP(MDP_BASE + 0x5031c, 0x7fc00000);
342 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
343 MDP_OUTP(MDP_BASE + 0x50320, 0x7fc00000);
344 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
345 MDP_OUTP(MDP_BASE + 0x50324, 0x7fc00000);
346 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
347 MDP_OUTP(MDP_BASE + 0x50328, 0x7fc00000);
348 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
349 MDP_OUTP(MDP_BASE + 0x5032c, 0x7fc00000);
350 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
351 MDP_OUTP(MDP_BASE + 0x50330, 0x7fc00000);
352 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
353 MDP_OUTP(MDP_BASE + 0x50334, 0x7fc00000);
354 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
355 MDP_OUTP(MDP_BASE + 0x50338, 0x7fc00000);
356 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
357 MDP_OUTP(MDP_BASE + 0x5033c, 0x7fc00000);
358 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
359 MDP_OUTP(MDP_BASE + 0x50340, 0x0);
360 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
361 MDP_OUTP(MDP_BASE + 0x50344, 0x0);
362 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
363 MDP_OUTP(MDP_BASE + 0x50348, 0x0);
364 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
365 MDP_OUTP(MDP_BASE + 0x5034c, 0x0);
366 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
367 MDP_OUTP(MDP_BASE + 0x50350, 0x0);
368 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
369 MDP_OUTP(MDP_BASE + 0x50354, 0x0);
370 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
371 MDP_OUTP(MDP_BASE + 0x50358, 0x0);
372 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
373 MDP_OUTP(MDP_BASE + 0x5035c, 0x0);
374 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
375 MDP_OUTP(MDP_BASE + 0x50360, 0x0);
376 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
377 MDP_OUTP(MDP_BASE + 0x50364, 0x0);
378 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
379 MDP_OUTP(MDP_BASE + 0x50368, 0x0);
380 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
381 MDP_OUTP(MDP_BASE + 0x5036c, 0x0);
382 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
383 MDP_OUTP(MDP_BASE + 0x50370, 0x0);
384 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
385 MDP_OUTP(MDP_BASE + 0x50374, 0x0);
386 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
387 MDP_OUTP(MDP_BASE + 0x50378, 0x0);
388 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
389 MDP_OUTP(MDP_BASE + 0x5037c, 0x0);
390}
391
392static void mdp_load_pr_downscale_table_x_point4TOpoint6(void)
393{
394 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
395 MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000);
396 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
397 MDP_OUTP(MDP_BASE + 0x50284, 0x7fc00000);
398 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
399 MDP_OUTP(MDP_BASE + 0x50288, 0x7fc00000);
400 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
401 MDP_OUTP(MDP_BASE + 0x5028c, 0x7fc00000);
402 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
403 MDP_OUTP(MDP_BASE + 0x50290, 0x7fc00000);
404 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
405 MDP_OUTP(MDP_BASE + 0x50294, 0x7fc00000);
406 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
407 MDP_OUTP(MDP_BASE + 0x50298, 0x7fc00000);
408 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
409 MDP_OUTP(MDP_BASE + 0x5029c, 0x7fc00000);
410 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
411 MDP_OUTP(MDP_BASE + 0x502a0, 0x7fc00000);
412 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
413 MDP_OUTP(MDP_BASE + 0x502a4, 0x7fc00000);
414 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
415 MDP_OUTP(MDP_BASE + 0x502a8, 0x7fc00000);
416 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
417 MDP_OUTP(MDP_BASE + 0x502ac, 0x7fc00000);
418 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
419 MDP_OUTP(MDP_BASE + 0x502b0, 0x7fc00000);
420 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
421 MDP_OUTP(MDP_BASE + 0x502b4, 0x7fc00000);
422 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
423 MDP_OUTP(MDP_BASE + 0x502b8, 0x7fc00000);
424 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
425 MDP_OUTP(MDP_BASE + 0x502bc, 0x7fc00000);
426 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
427 MDP_OUTP(MDP_BASE + 0x502c0, 0x0);
428 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
429 MDP_OUTP(MDP_BASE + 0x502c4, 0x0);
430 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
431 MDP_OUTP(MDP_BASE + 0x502c8, 0x0);
432 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
433 MDP_OUTP(MDP_BASE + 0x502cc, 0x0);
434 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
435 MDP_OUTP(MDP_BASE + 0x502d0, 0x0);
436 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
437 MDP_OUTP(MDP_BASE + 0x502d4, 0x0);
438 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
439 MDP_OUTP(MDP_BASE + 0x502d8, 0x0);
440 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
441 MDP_OUTP(MDP_BASE + 0x502dc, 0x0);
442 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
443 MDP_OUTP(MDP_BASE + 0x502e0, 0x0);
444 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
445 MDP_OUTP(MDP_BASE + 0x502e4, 0x0);
446 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
447 MDP_OUTP(MDP_BASE + 0x502e8, 0x0);
448 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
449 MDP_OUTP(MDP_BASE + 0x502ec, 0x0);
450 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
451 MDP_OUTP(MDP_BASE + 0x502f0, 0x0);
452 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
453 MDP_OUTP(MDP_BASE + 0x502f4, 0x0);
454 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
455 MDP_OUTP(MDP_BASE + 0x502f8, 0x0);
456 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
457 MDP_OUTP(MDP_BASE + 0x502fc, 0x0);
458}
459
460static void mdp_load_pr_downscale_table_y_point4TOpoint6(void)
461{
462 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
463 MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000);
464 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
465 MDP_OUTP(MDP_BASE + 0x50304, 0x7fc00000);
466 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
467 MDP_OUTP(MDP_BASE + 0x50308, 0x7fc00000);
468 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
469 MDP_OUTP(MDP_BASE + 0x5030c, 0x7fc00000);
470 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
471 MDP_OUTP(MDP_BASE + 0x50310, 0x7fc00000);
472 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
473 MDP_OUTP(MDP_BASE + 0x50314, 0x7fc00000);
474 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
475 MDP_OUTP(MDP_BASE + 0x50318, 0x7fc00000);
476 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
477 MDP_OUTP(MDP_BASE + 0x5031c, 0x7fc00000);
478 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
479 MDP_OUTP(MDP_BASE + 0x50320, 0x7fc00000);
480 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
481 MDP_OUTP(MDP_BASE + 0x50324, 0x7fc00000);
482 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
483 MDP_OUTP(MDP_BASE + 0x50328, 0x7fc00000);
484 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
485 MDP_OUTP(MDP_BASE + 0x5032c, 0x7fc00000);
486 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
487 MDP_OUTP(MDP_BASE + 0x50330, 0x7fc00000);
488 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
489 MDP_OUTP(MDP_BASE + 0x50334, 0x7fc00000);
490 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
491 MDP_OUTP(MDP_BASE + 0x50338, 0x7fc00000);
492 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
493 MDP_OUTP(MDP_BASE + 0x5033c, 0x7fc00000);
494 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
495 MDP_OUTP(MDP_BASE + 0x50340, 0x0);
496 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
497 MDP_OUTP(MDP_BASE + 0x50344, 0x0);
498 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
499 MDP_OUTP(MDP_BASE + 0x50348, 0x0);
500 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
501 MDP_OUTP(MDP_BASE + 0x5034c, 0x0);
502 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
503 MDP_OUTP(MDP_BASE + 0x50350, 0x0);
504 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
505 MDP_OUTP(MDP_BASE + 0x50354, 0x0);
506 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
507 MDP_OUTP(MDP_BASE + 0x50358, 0x0);
508 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
509 MDP_OUTP(MDP_BASE + 0x5035c, 0x0);
510 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
511 MDP_OUTP(MDP_BASE + 0x50360, 0x0);
512 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
513 MDP_OUTP(MDP_BASE + 0x50364, 0x0);
514 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
515 MDP_OUTP(MDP_BASE + 0x50368, 0x0);
516 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
517 MDP_OUTP(MDP_BASE + 0x5036c, 0x0);
518 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
519 MDP_OUTP(MDP_BASE + 0x50370, 0x0);
520 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
521 MDP_OUTP(MDP_BASE + 0x50374, 0x0);
522 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
523 MDP_OUTP(MDP_BASE + 0x50378, 0x0);
524 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
525 MDP_OUTP(MDP_BASE + 0x5037c, 0x0);
526}
527
528static void mdp_load_pr_downscale_table_x_point6TOpoint8(void)
529{
530 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
531 MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000);
532 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
533 MDP_OUTP(MDP_BASE + 0x50284, 0x7fc00000);
534 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
535 MDP_OUTP(MDP_BASE + 0x50288, 0x7fc00000);
536 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
537 MDP_OUTP(MDP_BASE + 0x5028c, 0x7fc00000);
538 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
539 MDP_OUTP(MDP_BASE + 0x50290, 0x7fc00000);
540 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
541 MDP_OUTP(MDP_BASE + 0x50294, 0x7fc00000);
542 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
543 MDP_OUTP(MDP_BASE + 0x50298, 0x7fc00000);
544 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
545 MDP_OUTP(MDP_BASE + 0x5029c, 0x7fc00000);
546 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
547 MDP_OUTP(MDP_BASE + 0x502a0, 0x7fc00000);
548 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
549 MDP_OUTP(MDP_BASE + 0x502a4, 0x7fc00000);
550 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
551 MDP_OUTP(MDP_BASE + 0x502a8, 0x7fc00000);
552 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
553 MDP_OUTP(MDP_BASE + 0x502ac, 0x7fc00000);
554 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
555 MDP_OUTP(MDP_BASE + 0x502b0, 0x7fc00000);
556 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
557 MDP_OUTP(MDP_BASE + 0x502b4, 0x7fc00000);
558 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
559 MDP_OUTP(MDP_BASE + 0x502b8, 0x7fc00000);
560 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
561 MDP_OUTP(MDP_BASE + 0x502bc, 0x7fc00000);
562 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
563 MDP_OUTP(MDP_BASE + 0x502c0, 0x0);
564 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
565 MDP_OUTP(MDP_BASE + 0x502c4, 0x0);
566 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
567 MDP_OUTP(MDP_BASE + 0x502c8, 0x0);
568 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
569 MDP_OUTP(MDP_BASE + 0x502cc, 0x0);
570 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
571 MDP_OUTP(MDP_BASE + 0x502d0, 0x0);
572 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
573 MDP_OUTP(MDP_BASE + 0x502d4, 0x0);
574 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
575 MDP_OUTP(MDP_BASE + 0x502d8, 0x0);
576 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
577 MDP_OUTP(MDP_BASE + 0x502dc, 0x0);
578 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
579 MDP_OUTP(MDP_BASE + 0x502e0, 0x0);
580 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
581 MDP_OUTP(MDP_BASE + 0x502e4, 0x0);
582 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
583 MDP_OUTP(MDP_BASE + 0x502e8, 0x0);
584 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
585 MDP_OUTP(MDP_BASE + 0x502ec, 0x0);
586 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
587 MDP_OUTP(MDP_BASE + 0x502f0, 0x0);
588 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
589 MDP_OUTP(MDP_BASE + 0x502f4, 0x0);
590 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
591 MDP_OUTP(MDP_BASE + 0x502f8, 0x0);
592 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
593 MDP_OUTP(MDP_BASE + 0x502fc, 0x0);
594}
595
596static void mdp_load_pr_downscale_table_y_point6TOpoint8(void)
597{
598 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
599 MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000);
600 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
601 MDP_OUTP(MDP_BASE + 0x50304, 0x7fc00000);
602 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
603 MDP_OUTP(MDP_BASE + 0x50308, 0x7fc00000);
604 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
605 MDP_OUTP(MDP_BASE + 0x5030c, 0x7fc00000);
606 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
607 MDP_OUTP(MDP_BASE + 0x50310, 0x7fc00000);
608 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
609 MDP_OUTP(MDP_BASE + 0x50314, 0x7fc00000);
610 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
611 MDP_OUTP(MDP_BASE + 0x50318, 0x7fc00000);
612 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
613 MDP_OUTP(MDP_BASE + 0x5031c, 0x7fc00000);
614 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
615 MDP_OUTP(MDP_BASE + 0x50320, 0x7fc00000);
616 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
617 MDP_OUTP(MDP_BASE + 0x50324, 0x7fc00000);
618 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
619 MDP_OUTP(MDP_BASE + 0x50328, 0x7fc00000);
620 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
621 MDP_OUTP(MDP_BASE + 0x5032c, 0x7fc00000);
622 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
623 MDP_OUTP(MDP_BASE + 0x50330, 0x7fc00000);
624 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
625 MDP_OUTP(MDP_BASE + 0x50334, 0x7fc00000);
626 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
627 MDP_OUTP(MDP_BASE + 0x50338, 0x7fc00000);
628 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
629 MDP_OUTP(MDP_BASE + 0x5033c, 0x7fc00000);
630 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
631 MDP_OUTP(MDP_BASE + 0x50340, 0x0);
632 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
633 MDP_OUTP(MDP_BASE + 0x50344, 0x0);
634 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
635 MDP_OUTP(MDP_BASE + 0x50348, 0x0);
636 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
637 MDP_OUTP(MDP_BASE + 0x5034c, 0x0);
638 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
639 MDP_OUTP(MDP_BASE + 0x50350, 0x0);
640 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
641 MDP_OUTP(MDP_BASE + 0x50354, 0x0);
642 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
643 MDP_OUTP(MDP_BASE + 0x50358, 0x0);
644 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
645 MDP_OUTP(MDP_BASE + 0x5035c, 0x0);
646 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
647 MDP_OUTP(MDP_BASE + 0x50360, 0x0);
648 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
649 MDP_OUTP(MDP_BASE + 0x50364, 0x0);
650 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
651 MDP_OUTP(MDP_BASE + 0x50368, 0x0);
652 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
653 MDP_OUTP(MDP_BASE + 0x5036c, 0x0);
654 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
655 MDP_OUTP(MDP_BASE + 0x50370, 0x0);
656 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
657 MDP_OUTP(MDP_BASE + 0x50374, 0x0);
658 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
659 MDP_OUTP(MDP_BASE + 0x50378, 0x0);
660 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
661 MDP_OUTP(MDP_BASE + 0x5037c, 0x0);
662}
663
664static void mdp_load_pr_downscale_table_x_point8TO1(void)
665{
666 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
667 MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000);
668 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
669 MDP_OUTP(MDP_BASE + 0x50284, 0x7fc00000);
670 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
671 MDP_OUTP(MDP_BASE + 0x50288, 0x7fc00000);
672 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
673 MDP_OUTP(MDP_BASE + 0x5028c, 0x7fc00000);
674 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
675 MDP_OUTP(MDP_BASE + 0x50290, 0x7fc00000);
676 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
677 MDP_OUTP(MDP_BASE + 0x50294, 0x7fc00000);
678 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
679 MDP_OUTP(MDP_BASE + 0x50298, 0x7fc00000);
680 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
681 MDP_OUTP(MDP_BASE + 0x5029c, 0x7fc00000);
682 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
683 MDP_OUTP(MDP_BASE + 0x502a0, 0x7fc00000);
684 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
685 MDP_OUTP(MDP_BASE + 0x502a4, 0x7fc00000);
686 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
687 MDP_OUTP(MDP_BASE + 0x502a8, 0x7fc00000);
688 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
689 MDP_OUTP(MDP_BASE + 0x502ac, 0x7fc00000);
690 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
691 MDP_OUTP(MDP_BASE + 0x502b0, 0x7fc00000);
692 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
693 MDP_OUTP(MDP_BASE + 0x502b4, 0x7fc00000);
694 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
695 MDP_OUTP(MDP_BASE + 0x502b8, 0x7fc00000);
696 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
697 MDP_OUTP(MDP_BASE + 0x502bc, 0x7fc00000);
698 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
699 MDP_OUTP(MDP_BASE + 0x502c0, 0x0);
700 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
701 MDP_OUTP(MDP_BASE + 0x502c4, 0x0);
702 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
703 MDP_OUTP(MDP_BASE + 0x502c8, 0x0);
704 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
705 MDP_OUTP(MDP_BASE + 0x502cc, 0x0);
706 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
707 MDP_OUTP(MDP_BASE + 0x502d0, 0x0);
708 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
709 MDP_OUTP(MDP_BASE + 0x502d4, 0x0);
710 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
711 MDP_OUTP(MDP_BASE + 0x502d8, 0x0);
712 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
713 MDP_OUTP(MDP_BASE + 0x502dc, 0x0);
714 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
715 MDP_OUTP(MDP_BASE + 0x502e0, 0x0);
716 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
717 MDP_OUTP(MDP_BASE + 0x502e4, 0x0);
718 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
719 MDP_OUTP(MDP_BASE + 0x502e8, 0x0);
720 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
721 MDP_OUTP(MDP_BASE + 0x502ec, 0x0);
722 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
723 MDP_OUTP(MDP_BASE + 0x502f0, 0x0);
724 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
725 MDP_OUTP(MDP_BASE + 0x502f4, 0x0);
726 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
727 MDP_OUTP(MDP_BASE + 0x502f8, 0x0);
728 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
729 MDP_OUTP(MDP_BASE + 0x502fc, 0x0);
730}
731
732static void mdp_load_pr_downscale_table_y_point8TO1(void)
733{
734 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
735 MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000);
736 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
737 MDP_OUTP(MDP_BASE + 0x50304, 0x7fc00000);
738 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
739 MDP_OUTP(MDP_BASE + 0x50308, 0x7fc00000);
740 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
741 MDP_OUTP(MDP_BASE + 0x5030c, 0x7fc00000);
742 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
743 MDP_OUTP(MDP_BASE + 0x50310, 0x7fc00000);
744 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
745 MDP_OUTP(MDP_BASE + 0x50314, 0x7fc00000);
746 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
747 MDP_OUTP(MDP_BASE + 0x50318, 0x7fc00000);
748 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
749 MDP_OUTP(MDP_BASE + 0x5031c, 0x7fc00000);
750 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
751 MDP_OUTP(MDP_BASE + 0x50320, 0x7fc00000);
752 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
753 MDP_OUTP(MDP_BASE + 0x50324, 0x7fc00000);
754 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
755 MDP_OUTP(MDP_BASE + 0x50328, 0x7fc00000);
756 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
757 MDP_OUTP(MDP_BASE + 0x5032c, 0x7fc00000);
758 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
759 MDP_OUTP(MDP_BASE + 0x50330, 0x7fc00000);
760 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
761 MDP_OUTP(MDP_BASE + 0x50334, 0x7fc00000);
762 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
763 MDP_OUTP(MDP_BASE + 0x50338, 0x7fc00000);
764 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
765 MDP_OUTP(MDP_BASE + 0x5033c, 0x7fc00000);
766 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
767 MDP_OUTP(MDP_BASE + 0x50340, 0x0);
768 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
769 MDP_OUTP(MDP_BASE + 0x50344, 0x0);
770 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
771 MDP_OUTP(MDP_BASE + 0x50348, 0x0);
772 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
773 MDP_OUTP(MDP_BASE + 0x5034c, 0x0);
774 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
775 MDP_OUTP(MDP_BASE + 0x50350, 0x0);
776 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
777 MDP_OUTP(MDP_BASE + 0x50354, 0x0);
778 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
779 MDP_OUTP(MDP_BASE + 0x50358, 0x0);
780 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
781 MDP_OUTP(MDP_BASE + 0x5035c, 0x0);
782 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
783 MDP_OUTP(MDP_BASE + 0x50360, 0x0);
784 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
785 MDP_OUTP(MDP_BASE + 0x50364, 0x0);
786 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
787 MDP_OUTP(MDP_BASE + 0x50368, 0x0);
788 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
789 MDP_OUTP(MDP_BASE + 0x5036c, 0x0);
790 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
791 MDP_OUTP(MDP_BASE + 0x50370, 0x0);
792 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
793 MDP_OUTP(MDP_BASE + 0x50374, 0x0);
794 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
795 MDP_OUTP(MDP_BASE + 0x50378, 0x0);
796 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
797 MDP_OUTP(MDP_BASE + 0x5037c, 0x0);
798}
799
800static void mdp_load_bc_upscale_table(void)
801{
802 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
803 MDP_OUTP(MDP_BASE + 0x50200, 0x7fc00000);
804 MDP_OUTP(MDP_BASE + 0x5fffc, 0xff80000d);
805 MDP_OUTP(MDP_BASE + 0x50204, 0x7ec003f9);
806 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec0001c);
807 MDP_OUTP(MDP_BASE + 0x50208, 0x7d4003f3);
808 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40002b);
809 MDP_OUTP(MDP_BASE + 0x5020c, 0x7b8003ed);
810 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfd80003c);
811 MDP_OUTP(MDP_BASE + 0x50210, 0x794003e8);
812 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc0004d);
813 MDP_OUTP(MDP_BASE + 0x50214, 0x76c003e4);
814 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfc40005f);
815 MDP_OUTP(MDP_BASE + 0x50218, 0x73c003e0);
816 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb800071);
817 MDP_OUTP(MDP_BASE + 0x5021c, 0x708003de);
818 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfac00085);
819 MDP_OUTP(MDP_BASE + 0x50220, 0x6d0003db);
820 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa000098);
821 MDP_OUTP(MDP_BASE + 0x50224, 0x698003d9);
822 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf98000ac);
823 MDP_OUTP(MDP_BASE + 0x50228, 0x654003d8);
824 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8c000c1);
825 MDP_OUTP(MDP_BASE + 0x5022c, 0x610003d7);
826 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf84000d5);
827 MDP_OUTP(MDP_BASE + 0x50230, 0x5c8003d7);
828 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf7c000e9);
829 MDP_OUTP(MDP_BASE + 0x50234, 0x580003d7);
830 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf74000fd);
831 MDP_OUTP(MDP_BASE + 0x50238, 0x534003d8);
832 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c00112);
833 MDP_OUTP(MDP_BASE + 0x5023c, 0x4e8003d8);
834 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6800126);
835 MDP_OUTP(MDP_BASE + 0x50240, 0x494003da);
836 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600013a);
837 MDP_OUTP(MDP_BASE + 0x50244, 0x448003db);
838 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600014d);
839 MDP_OUTP(MDP_BASE + 0x50248, 0x3f4003dd);
840 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00160);
841 MDP_OUTP(MDP_BASE + 0x5024c, 0x3a4003df);
842 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00172);
843 MDP_OUTP(MDP_BASE + 0x50250, 0x354003e1);
844 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00184);
845 MDP_OUTP(MDP_BASE + 0x50254, 0x304003e3);
846 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6000195);
847 MDP_OUTP(MDP_BASE + 0x50258, 0x2b0003e6);
848 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf64001a6);
849 MDP_OUTP(MDP_BASE + 0x5025c, 0x260003e8);
850 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c001b4);
851 MDP_OUTP(MDP_BASE + 0x50260, 0x214003eb);
852 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf78001c2);
853 MDP_OUTP(MDP_BASE + 0x50264, 0x1c4003ee);
854 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf80001cf);
855 MDP_OUTP(MDP_BASE + 0x50268, 0x17c003f1);
856 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf90001db);
857 MDP_OUTP(MDP_BASE + 0x5026c, 0x134003f3);
858 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa0001e5);
859 MDP_OUTP(MDP_BASE + 0x50270, 0xf0003f6);
860 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb4001ee);
861 MDP_OUTP(MDP_BASE + 0x50274, 0xac003f9);
862 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc001f5);
863 MDP_OUTP(MDP_BASE + 0x50278, 0x70003fb);
864 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe4001fb);
865 MDP_OUTP(MDP_BASE + 0x5027c, 0x34003fe);
866}
867
868static void mdp_load_bc_downscale_table_x_point2TOpoint4(void)
869{
870 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ac00084);
871 MDP_OUTP(MDP_BASE + 0x50280, 0x23400083);
872 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b000084);
873 MDP_OUTP(MDP_BASE + 0x50284, 0x23000083);
874 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b400084);
875 MDP_OUTP(MDP_BASE + 0x50288, 0x23000082);
876 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b400085);
877 MDP_OUTP(MDP_BASE + 0x5028c, 0x23000081);
878 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b800085);
879 MDP_OUTP(MDP_BASE + 0x50290, 0x23000080);
880 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1bc00086);
881 MDP_OUTP(MDP_BASE + 0x50294, 0x22c0007f);
882 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c000086);
883 MDP_OUTP(MDP_BASE + 0x50298, 0x2280007f);
884 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c400086);
885 MDP_OUTP(MDP_BASE + 0x5029c, 0x2280007e);
886 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c800086);
887 MDP_OUTP(MDP_BASE + 0x502a0, 0x2280007d);
888 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc00086);
889 MDP_OUTP(MDP_BASE + 0x502a4, 0x2240007d);
890 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc00087);
891 MDP_OUTP(MDP_BASE + 0x502a8, 0x2240007c);
892 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d000087);
893 MDP_OUTP(MDP_BASE + 0x502ac, 0x2240007b);
894 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d400087);
895 MDP_OUTP(MDP_BASE + 0x502b0, 0x2200007b);
896 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d400088);
897 MDP_OUTP(MDP_BASE + 0x502b4, 0x22400079);
898 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d800088);
899 MDP_OUTP(MDP_BASE + 0x502b8, 0x22400078);
900 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc00088);
901 MDP_OUTP(MDP_BASE + 0x502bc, 0x22400077);
902 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc00089);
903 MDP_OUTP(MDP_BASE + 0x502c0, 0x22000077);
904 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1e000089);
905 MDP_OUTP(MDP_BASE + 0x502c4, 0x22000076);
906 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1e400089);
907 MDP_OUTP(MDP_BASE + 0x502c8, 0x22000075);
908 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec00088);
909 MDP_OUTP(MDP_BASE + 0x502cc, 0x21c00075);
910 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec00089);
911 MDP_OUTP(MDP_BASE + 0x502d0, 0x21c00074);
912 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f000089);
913 MDP_OUTP(MDP_BASE + 0x502d4, 0x21c00073);
914 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f400089);
915 MDP_OUTP(MDP_BASE + 0x502d8, 0x21800073);
916 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f40008a);
917 MDP_OUTP(MDP_BASE + 0x502dc, 0x21800072);
918 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f80008a);
919 MDP_OUTP(MDP_BASE + 0x502e0, 0x21800071);
920 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1fc0008a);
921 MDP_OUTP(MDP_BASE + 0x502e4, 0x21800070);
922 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1fc0008b);
923 MDP_OUTP(MDP_BASE + 0x502e8, 0x2180006f);
924 MDP_OUTP(MDP_BASE + 0x5fffc, 0x2000008c);
925 MDP_OUTP(MDP_BASE + 0x502ec, 0x2140006e);
926 MDP_OUTP(MDP_BASE + 0x5fffc, 0x2040008c);
927 MDP_OUTP(MDP_BASE + 0x502f0, 0x2140006d);
928 MDP_OUTP(MDP_BASE + 0x5fffc, 0x2080008c);
929 MDP_OUTP(MDP_BASE + 0x502f4, 0x2100006d);
930 MDP_OUTP(MDP_BASE + 0x5fffc, 0x20c0008c);
931 MDP_OUTP(MDP_BASE + 0x502f8, 0x2100006c);
932 MDP_OUTP(MDP_BASE + 0x5fffc, 0x20c0008d);
933 MDP_OUTP(MDP_BASE + 0x502fc, 0x2100006b);
934}
935
936static void mdp_load_bc_downscale_table_y_point2TOpoint4(void)
937{
938 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ac00084);
939 MDP_OUTP(MDP_BASE + 0x50300, 0x23400083);
940 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b000084);
941 MDP_OUTP(MDP_BASE + 0x50304, 0x23000083);
942 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b400084);
943 MDP_OUTP(MDP_BASE + 0x50308, 0x23000082);
944 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b400085);
945 MDP_OUTP(MDP_BASE + 0x5030c, 0x23000081);
946 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b800085);
947 MDP_OUTP(MDP_BASE + 0x50310, 0x23000080);
948 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1bc00086);
949 MDP_OUTP(MDP_BASE + 0x50314, 0x22c0007f);
950 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c000086);
951 MDP_OUTP(MDP_BASE + 0x50318, 0x2280007f);
952 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c400086);
953 MDP_OUTP(MDP_BASE + 0x5031c, 0x2280007e);
954 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c800086);
955 MDP_OUTP(MDP_BASE + 0x50320, 0x2280007d);
956 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc00086);
957 MDP_OUTP(MDP_BASE + 0x50324, 0x2240007d);
958 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc00087);
959 MDP_OUTP(MDP_BASE + 0x50328, 0x2240007c);
960 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d000087);
961 MDP_OUTP(MDP_BASE + 0x5032c, 0x2240007b);
962 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d400087);
963 MDP_OUTP(MDP_BASE + 0x50330, 0x2200007b);
964 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d400088);
965 MDP_OUTP(MDP_BASE + 0x50334, 0x22400079);
966 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d800088);
967 MDP_OUTP(MDP_BASE + 0x50338, 0x22400078);
968 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc00088);
969 MDP_OUTP(MDP_BASE + 0x5033c, 0x22400077);
970 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc00089);
971 MDP_OUTP(MDP_BASE + 0x50340, 0x22000077);
972 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1e000089);
973 MDP_OUTP(MDP_BASE + 0x50344, 0x22000076);
974 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1e400089);
975 MDP_OUTP(MDP_BASE + 0x50348, 0x22000075);
976 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec00088);
977 MDP_OUTP(MDP_BASE + 0x5034c, 0x21c00075);
978 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec00089);
979 MDP_OUTP(MDP_BASE + 0x50350, 0x21c00074);
980 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f000089);
981 MDP_OUTP(MDP_BASE + 0x50354, 0x21c00073);
982 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f400089);
983 MDP_OUTP(MDP_BASE + 0x50358, 0x21800073);
984 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f40008a);
985 MDP_OUTP(MDP_BASE + 0x5035c, 0x21800072);
986 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f80008a);
987 MDP_OUTP(MDP_BASE + 0x50360, 0x21800071);
988 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1fc0008a);
989 MDP_OUTP(MDP_BASE + 0x50364, 0x21800070);
990 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1fc0008b);
991 MDP_OUTP(MDP_BASE + 0x50368, 0x2180006f);
992 MDP_OUTP(MDP_BASE + 0x5fffc, 0x2000008c);
993 MDP_OUTP(MDP_BASE + 0x5036c, 0x2140006e);
994 MDP_OUTP(MDP_BASE + 0x5fffc, 0x2040008c);
995 MDP_OUTP(MDP_BASE + 0x50370, 0x2140006d);
996 MDP_OUTP(MDP_BASE + 0x5fffc, 0x2080008c);
997 MDP_OUTP(MDP_BASE + 0x50374, 0x2100006d);
998 MDP_OUTP(MDP_BASE + 0x5fffc, 0x20c0008c);
999 MDP_OUTP(MDP_BASE + 0x50378, 0x2100006c);
1000 MDP_OUTP(MDP_BASE + 0x5fffc, 0x20c0008d);
1001 MDP_OUTP(MDP_BASE + 0x5037c, 0x2100006b);
1002}
1003
1004static void mdp_load_bc_downscale_table_x_point4TOpoint6(void)
1005{
1006 MDP_OUTP(MDP_BASE + 0x5fffc, 0x740008c);
1007 MDP_OUTP(MDP_BASE + 0x50280, 0x33800088);
1008 MDP_OUTP(MDP_BASE + 0x5fffc, 0x800008e);
1009 MDP_OUTP(MDP_BASE + 0x50284, 0x33400084);
1010 MDP_OUTP(MDP_BASE + 0x5fffc, 0x8400092);
1011 MDP_OUTP(MDP_BASE + 0x50288, 0x33000080);
1012 MDP_OUTP(MDP_BASE + 0x5fffc, 0x9000094);
1013 MDP_OUTP(MDP_BASE + 0x5028c, 0x3300007b);
1014 MDP_OUTP(MDP_BASE + 0x5fffc, 0x9c00098);
1015 MDP_OUTP(MDP_BASE + 0x50290, 0x32400077);
1016 MDP_OUTP(MDP_BASE + 0x5fffc, 0xa40009b);
1017 MDP_OUTP(MDP_BASE + 0x50294, 0x32000073);
1018 MDP_OUTP(MDP_BASE + 0x5fffc, 0xb00009d);
1019 MDP_OUTP(MDP_BASE + 0x50298, 0x31c0006f);
1020 MDP_OUTP(MDP_BASE + 0x5fffc, 0xbc000a0);
1021 MDP_OUTP(MDP_BASE + 0x5029c, 0x3140006b);
1022 MDP_OUTP(MDP_BASE + 0x5fffc, 0xc8000a2);
1023 MDP_OUTP(MDP_BASE + 0x502a0, 0x31000067);
1024 MDP_OUTP(MDP_BASE + 0x5fffc, 0xd8000a5);
1025 MDP_OUTP(MDP_BASE + 0x502a4, 0x30800062);
1026 MDP_OUTP(MDP_BASE + 0x5fffc, 0xe4000a8);
1027 MDP_OUTP(MDP_BASE + 0x502a8, 0x2fc0005f);
1028 MDP_OUTP(MDP_BASE + 0x5fffc, 0xec000aa);
1029 MDP_OUTP(MDP_BASE + 0x502ac, 0x2fc0005b);
1030 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8000ad);
1031 MDP_OUTP(MDP_BASE + 0x502b0, 0x2f400057);
1032 MDP_OUTP(MDP_BASE + 0x5fffc, 0x108000b0);
1033 MDP_OUTP(MDP_BASE + 0x502b4, 0x2e400054);
1034 MDP_OUTP(MDP_BASE + 0x5fffc, 0x114000b2);
1035 MDP_OUTP(MDP_BASE + 0x502b8, 0x2e000050);
1036 MDP_OUTP(MDP_BASE + 0x5fffc, 0x124000b4);
1037 MDP_OUTP(MDP_BASE + 0x502bc, 0x2d80004c);
1038 MDP_OUTP(MDP_BASE + 0x5fffc, 0x130000b6);
1039 MDP_OUTP(MDP_BASE + 0x502c0, 0x2d000049);
1040 MDP_OUTP(MDP_BASE + 0x5fffc, 0x140000b8);
1041 MDP_OUTP(MDP_BASE + 0x502c4, 0x2c800045);
1042 MDP_OUTP(MDP_BASE + 0x5fffc, 0x150000b9);
1043 MDP_OUTP(MDP_BASE + 0x502c8, 0x2c000042);
1044 MDP_OUTP(MDP_BASE + 0x5fffc, 0x15c000bd);
1045 MDP_OUTP(MDP_BASE + 0x502cc, 0x2b40003e);
1046 MDP_OUTP(MDP_BASE + 0x5fffc, 0x16c000bf);
1047 MDP_OUTP(MDP_BASE + 0x502d0, 0x2a80003b);
1048 MDP_OUTP(MDP_BASE + 0x5fffc, 0x17c000bf);
1049 MDP_OUTP(MDP_BASE + 0x502d4, 0x2a000039);
1050 MDP_OUTP(MDP_BASE + 0x5fffc, 0x188000c2);
1051 MDP_OUTP(MDP_BASE + 0x502d8, 0x29400036);
1052 MDP_OUTP(MDP_BASE + 0x5fffc, 0x19c000c4);
1053 MDP_OUTP(MDP_BASE + 0x502dc, 0x28800032);
1054 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ac000c5);
1055 MDP_OUTP(MDP_BASE + 0x502e0, 0x2800002f);
1056 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1bc000c7);
1057 MDP_OUTP(MDP_BASE + 0x502e4, 0x2740002c);
1058 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc000c8);
1059 MDP_OUTP(MDP_BASE + 0x502e8, 0x26c00029);
1060 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc000c9);
1061 MDP_OUTP(MDP_BASE + 0x502ec, 0x26000027);
1062 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec000cc);
1063 MDP_OUTP(MDP_BASE + 0x502f0, 0x25000024);
1064 MDP_OUTP(MDP_BASE + 0x5fffc, 0x200000cc);
1065 MDP_OUTP(MDP_BASE + 0x502f4, 0x24800021);
1066 MDP_OUTP(MDP_BASE + 0x5fffc, 0x210000cd);
1067 MDP_OUTP(MDP_BASE + 0x502f8, 0x23800020);
1068 MDP_OUTP(MDP_BASE + 0x5fffc, 0x220000ce);
1069 MDP_OUTP(MDP_BASE + 0x502fc, 0x2300001d);
1070}
1071
1072static void mdp_load_bc_downscale_table_y_point4TOpoint6(void)
1073{
1074 MDP_OUTP(MDP_BASE + 0x5fffc, 0x740008c);
1075 MDP_OUTP(MDP_BASE + 0x50300, 0x33800088);
1076 MDP_OUTP(MDP_BASE + 0x5fffc, 0x800008e);
1077 MDP_OUTP(MDP_BASE + 0x50304, 0x33400084);
1078 MDP_OUTP(MDP_BASE + 0x5fffc, 0x8400092);
1079 MDP_OUTP(MDP_BASE + 0x50308, 0x33000080);
1080 MDP_OUTP(MDP_BASE + 0x5fffc, 0x9000094);
1081 MDP_OUTP(MDP_BASE + 0x5030c, 0x3300007b);
1082 MDP_OUTP(MDP_BASE + 0x5fffc, 0x9c00098);
1083 MDP_OUTP(MDP_BASE + 0x50310, 0x32400077);
1084 MDP_OUTP(MDP_BASE + 0x5fffc, 0xa40009b);
1085 MDP_OUTP(MDP_BASE + 0x50314, 0x32000073);
1086 MDP_OUTP(MDP_BASE + 0x5fffc, 0xb00009d);
1087 MDP_OUTP(MDP_BASE + 0x50318, 0x31c0006f);
1088 MDP_OUTP(MDP_BASE + 0x5fffc, 0xbc000a0);
1089 MDP_OUTP(MDP_BASE + 0x5031c, 0x3140006b);
1090 MDP_OUTP(MDP_BASE + 0x5fffc, 0xc8000a2);
1091 MDP_OUTP(MDP_BASE + 0x50320, 0x31000067);
1092 MDP_OUTP(MDP_BASE + 0x5fffc, 0xd8000a5);
1093 MDP_OUTP(MDP_BASE + 0x50324, 0x30800062);
1094 MDP_OUTP(MDP_BASE + 0x5fffc, 0xe4000a8);
1095 MDP_OUTP(MDP_BASE + 0x50328, 0x2fc0005f);
1096 MDP_OUTP(MDP_BASE + 0x5fffc, 0xec000aa);
1097 MDP_OUTP(MDP_BASE + 0x5032c, 0x2fc0005b);
1098 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8000ad);
1099 MDP_OUTP(MDP_BASE + 0x50330, 0x2f400057);
1100 MDP_OUTP(MDP_BASE + 0x5fffc, 0x108000b0);
1101 MDP_OUTP(MDP_BASE + 0x50334, 0x2e400054);
1102 MDP_OUTP(MDP_BASE + 0x5fffc, 0x114000b2);
1103 MDP_OUTP(MDP_BASE + 0x50338, 0x2e000050);
1104 MDP_OUTP(MDP_BASE + 0x5fffc, 0x124000b4);
1105 MDP_OUTP(MDP_BASE + 0x5033c, 0x2d80004c);
1106 MDP_OUTP(MDP_BASE + 0x5fffc, 0x130000b6);
1107 MDP_OUTP(MDP_BASE + 0x50340, 0x2d000049);
1108 MDP_OUTP(MDP_BASE + 0x5fffc, 0x140000b8);
1109 MDP_OUTP(MDP_BASE + 0x50344, 0x2c800045);
1110 MDP_OUTP(MDP_BASE + 0x5fffc, 0x150000b9);
1111 MDP_OUTP(MDP_BASE + 0x50348, 0x2c000042);
1112 MDP_OUTP(MDP_BASE + 0x5fffc, 0x15c000bd);
1113 MDP_OUTP(MDP_BASE + 0x5034c, 0x2b40003e);
1114 MDP_OUTP(MDP_BASE + 0x5fffc, 0x16c000bf);
1115 MDP_OUTP(MDP_BASE + 0x50350, 0x2a80003b);
1116 MDP_OUTP(MDP_BASE + 0x5fffc, 0x17c000bf);
1117 MDP_OUTP(MDP_BASE + 0x50354, 0x2a000039);
1118 MDP_OUTP(MDP_BASE + 0x5fffc, 0x188000c2);
1119 MDP_OUTP(MDP_BASE + 0x50358, 0x29400036);
1120 MDP_OUTP(MDP_BASE + 0x5fffc, 0x19c000c4);
1121 MDP_OUTP(MDP_BASE + 0x5035c, 0x28800032);
1122 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ac000c5);
1123 MDP_OUTP(MDP_BASE + 0x50360, 0x2800002f);
1124 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1bc000c7);
1125 MDP_OUTP(MDP_BASE + 0x50364, 0x2740002c);
1126 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc000c8);
1127 MDP_OUTP(MDP_BASE + 0x50368, 0x26c00029);
1128 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc000c9);
1129 MDP_OUTP(MDP_BASE + 0x5036c, 0x26000027);
1130 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec000cc);
1131 MDP_OUTP(MDP_BASE + 0x50370, 0x25000024);
1132 MDP_OUTP(MDP_BASE + 0x5fffc, 0x200000cc);
1133 MDP_OUTP(MDP_BASE + 0x50374, 0x24800021);
1134 MDP_OUTP(MDP_BASE + 0x5fffc, 0x210000cd);
1135 MDP_OUTP(MDP_BASE + 0x50378, 0x23800020);
1136 MDP_OUTP(MDP_BASE + 0x5fffc, 0x220000ce);
1137 MDP_OUTP(MDP_BASE + 0x5037c, 0x2300001d);
1138}
1139
1140static void mdp_load_bc_downscale_table_x_point6TOpoint8(void)
1141{
1142 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000070);
1143 MDP_OUTP(MDP_BASE + 0x50280, 0x4bc00068);
1144 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000078);
1145 MDP_OUTP(MDP_BASE + 0x50284, 0x4bc00060);
1146 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000080);
1147 MDP_OUTP(MDP_BASE + 0x50288, 0x4b800059);
1148 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000089);
1149 MDP_OUTP(MDP_BASE + 0x5028c, 0x4b000052);
1150 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe400091);
1151 MDP_OUTP(MDP_BASE + 0x50290, 0x4a80004b);
1152 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40009a);
1153 MDP_OUTP(MDP_BASE + 0x50294, 0x4a000044);
1154 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe8000a3);
1155 MDP_OUTP(MDP_BASE + 0x50298, 0x4940003d);
1156 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec000ac);
1157 MDP_OUTP(MDP_BASE + 0x5029c, 0x48400037);
1158 MDP_OUTP(MDP_BASE + 0x5fffc, 0xff0000b4);
1159 MDP_OUTP(MDP_BASE + 0x502a0, 0x47800031);
1160 MDP_OUTP(MDP_BASE + 0x5fffc, 0xff8000bd);
1161 MDP_OUTP(MDP_BASE + 0x502a4, 0x4640002b);
1162 MDP_OUTP(MDP_BASE + 0x5fffc, 0xc5);
1163 MDP_OUTP(MDP_BASE + 0x502a8, 0x45000026);
1164 MDP_OUTP(MDP_BASE + 0x5fffc, 0x8000ce);
1165 MDP_OUTP(MDP_BASE + 0x502ac, 0x43800021);
1166 MDP_OUTP(MDP_BASE + 0x5fffc, 0x10000d6);
1167 MDP_OUTP(MDP_BASE + 0x502b0, 0x4240001c);
1168 MDP_OUTP(MDP_BASE + 0x5fffc, 0x18000df);
1169 MDP_OUTP(MDP_BASE + 0x502b4, 0x40800018);
1170 MDP_OUTP(MDP_BASE + 0x5fffc, 0x24000e6);
1171 MDP_OUTP(MDP_BASE + 0x502b8, 0x3f000014);
1172 MDP_OUTP(MDP_BASE + 0x5fffc, 0x30000ee);
1173 MDP_OUTP(MDP_BASE + 0x502bc, 0x3d400010);
1174 MDP_OUTP(MDP_BASE + 0x5fffc, 0x40000f5);
1175 MDP_OUTP(MDP_BASE + 0x502c0, 0x3b80000c);
1176 MDP_OUTP(MDP_BASE + 0x5fffc, 0x50000fc);
1177 MDP_OUTP(MDP_BASE + 0x502c4, 0x39800009);
1178 MDP_OUTP(MDP_BASE + 0x5fffc, 0x6000102);
1179 MDP_OUTP(MDP_BASE + 0x502c8, 0x37c00006);
1180 MDP_OUTP(MDP_BASE + 0x5fffc, 0x7000109);
1181 MDP_OUTP(MDP_BASE + 0x502cc, 0x35800004);
1182 MDP_OUTP(MDP_BASE + 0x5fffc, 0x840010e);
1183 MDP_OUTP(MDP_BASE + 0x502d0, 0x33800002);
1184 MDP_OUTP(MDP_BASE + 0x5fffc, 0x9800114);
1185 MDP_OUTP(MDP_BASE + 0x502d4, 0x31400000);
1186 MDP_OUTP(MDP_BASE + 0x5fffc, 0xac00119);
1187 MDP_OUTP(MDP_BASE + 0x502d8, 0x2f4003fe);
1188 MDP_OUTP(MDP_BASE + 0x5fffc, 0xc40011e);
1189 MDP_OUTP(MDP_BASE + 0x502dc, 0x2d0003fc);
1190 MDP_OUTP(MDP_BASE + 0x5fffc, 0xdc00121);
1191 MDP_OUTP(MDP_BASE + 0x502e0, 0x2b0003fb);
1192 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf400125);
1193 MDP_OUTP(MDP_BASE + 0x502e4, 0x28c003fa);
1194 MDP_OUTP(MDP_BASE + 0x5fffc, 0x11000128);
1195 MDP_OUTP(MDP_BASE + 0x502e8, 0x268003f9);
1196 MDP_OUTP(MDP_BASE + 0x5fffc, 0x12c0012a);
1197 MDP_OUTP(MDP_BASE + 0x502ec, 0x244003f9);
1198 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1480012c);
1199 MDP_OUTP(MDP_BASE + 0x502f0, 0x224003f8);
1200 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1640012e);
1201 MDP_OUTP(MDP_BASE + 0x502f4, 0x200003f8);
1202 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1800012f);
1203 MDP_OUTP(MDP_BASE + 0x502f8, 0x1e0003f8);
1204 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1a00012f);
1205 MDP_OUTP(MDP_BASE + 0x502fc, 0x1c0003f8);
1206}
1207
1208static void mdp_load_bc_downscale_table_y_point6TOpoint8(void)
1209{
1210 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000070);
1211 MDP_OUTP(MDP_BASE + 0x50300, 0x4bc00068);
1212 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000078);
1213 MDP_OUTP(MDP_BASE + 0x50304, 0x4bc00060);
1214 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000080);
1215 MDP_OUTP(MDP_BASE + 0x50308, 0x4b800059);
1216 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000089);
1217 MDP_OUTP(MDP_BASE + 0x5030c, 0x4b000052);
1218 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe400091);
1219 MDP_OUTP(MDP_BASE + 0x50310, 0x4a80004b);
1220 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40009a);
1221 MDP_OUTP(MDP_BASE + 0x50314, 0x4a000044);
1222 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe8000a3);
1223 MDP_OUTP(MDP_BASE + 0x50318, 0x4940003d);
1224 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec000ac);
1225 MDP_OUTP(MDP_BASE + 0x5031c, 0x48400037);
1226 MDP_OUTP(MDP_BASE + 0x5fffc, 0xff0000b4);
1227 MDP_OUTP(MDP_BASE + 0x50320, 0x47800031);
1228 MDP_OUTP(MDP_BASE + 0x5fffc, 0xff8000bd);
1229 MDP_OUTP(MDP_BASE + 0x50324, 0x4640002b);
1230 MDP_OUTP(MDP_BASE + 0x5fffc, 0xc5);
1231 MDP_OUTP(MDP_BASE + 0x50328, 0x45000026);
1232 MDP_OUTP(MDP_BASE + 0x5fffc, 0x8000ce);
1233 MDP_OUTP(MDP_BASE + 0x5032c, 0x43800021);
1234 MDP_OUTP(MDP_BASE + 0x5fffc, 0x10000d6);
1235 MDP_OUTP(MDP_BASE + 0x50330, 0x4240001c);
1236 MDP_OUTP(MDP_BASE + 0x5fffc, 0x18000df);
1237 MDP_OUTP(MDP_BASE + 0x50334, 0x40800018);
1238 MDP_OUTP(MDP_BASE + 0x5fffc, 0x24000e6);
1239 MDP_OUTP(MDP_BASE + 0x50338, 0x3f000014);
1240 MDP_OUTP(MDP_BASE + 0x5fffc, 0x30000ee);
1241 MDP_OUTP(MDP_BASE + 0x5033c, 0x3d400010);
1242 MDP_OUTP(MDP_BASE + 0x5fffc, 0x40000f5);
1243 MDP_OUTP(MDP_BASE + 0x50340, 0x3b80000c);
1244 MDP_OUTP(MDP_BASE + 0x5fffc, 0x50000fc);
1245 MDP_OUTP(MDP_BASE + 0x50344, 0x39800009);
1246 MDP_OUTP(MDP_BASE + 0x5fffc, 0x6000102);
1247 MDP_OUTP(MDP_BASE + 0x50348, 0x37c00006);
1248 MDP_OUTP(MDP_BASE + 0x5fffc, 0x7000109);
1249 MDP_OUTP(MDP_BASE + 0x5034c, 0x35800004);
1250 MDP_OUTP(MDP_BASE + 0x5fffc, 0x840010e);
1251 MDP_OUTP(MDP_BASE + 0x50350, 0x33800002);
1252 MDP_OUTP(MDP_BASE + 0x5fffc, 0x9800114);
1253 MDP_OUTP(MDP_BASE + 0x50354, 0x31400000);
1254 MDP_OUTP(MDP_BASE + 0x5fffc, 0xac00119);
1255 MDP_OUTP(MDP_BASE + 0x50358, 0x2f4003fe);
1256 MDP_OUTP(MDP_BASE + 0x5fffc, 0xc40011e);
1257 MDP_OUTP(MDP_BASE + 0x5035c, 0x2d0003fc);
1258 MDP_OUTP(MDP_BASE + 0x5fffc, 0xdc00121);
1259 MDP_OUTP(MDP_BASE + 0x50360, 0x2b0003fb);
1260 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf400125);
1261 MDP_OUTP(MDP_BASE + 0x50364, 0x28c003fa);
1262 MDP_OUTP(MDP_BASE + 0x5fffc, 0x11000128);
1263 MDP_OUTP(MDP_BASE + 0x50368, 0x268003f9);
1264 MDP_OUTP(MDP_BASE + 0x5fffc, 0x12c0012a);
1265 MDP_OUTP(MDP_BASE + 0x5036c, 0x244003f9);
1266 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1480012c);
1267 MDP_OUTP(MDP_BASE + 0x50370, 0x224003f8);
1268 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1640012e);
1269 MDP_OUTP(MDP_BASE + 0x50374, 0x200003f8);
1270 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1800012f);
1271 MDP_OUTP(MDP_BASE + 0x50378, 0x1e0003f8);
1272 MDP_OUTP(MDP_BASE + 0x5fffc, 0x1a00012f);
1273 MDP_OUTP(MDP_BASE + 0x5037c, 0x1c0003f8);
1274}
1275
1276static void mdp_load_bc_downscale_table_x_point8TO1(void)
1277{
1278 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
1279 MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000);
1280 MDP_OUTP(MDP_BASE + 0x5fffc, 0xff80000d);
1281 MDP_OUTP(MDP_BASE + 0x50284, 0x7ec003f9);
1282 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec0001c);
1283 MDP_OUTP(MDP_BASE + 0x50288, 0x7d4003f3);
1284 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40002b);
1285 MDP_OUTP(MDP_BASE + 0x5028c, 0x7b8003ed);
1286 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfd80003c);
1287 MDP_OUTP(MDP_BASE + 0x50290, 0x794003e8);
1288 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc0004d);
1289 MDP_OUTP(MDP_BASE + 0x50294, 0x76c003e4);
1290 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfc40005f);
1291 MDP_OUTP(MDP_BASE + 0x50298, 0x73c003e0);
1292 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb800071);
1293 MDP_OUTP(MDP_BASE + 0x5029c, 0x708003de);
1294 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfac00085);
1295 MDP_OUTP(MDP_BASE + 0x502a0, 0x6d0003db);
1296 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa000098);
1297 MDP_OUTP(MDP_BASE + 0x502a4, 0x698003d9);
1298 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf98000ac);
1299 MDP_OUTP(MDP_BASE + 0x502a8, 0x654003d8);
1300 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8c000c1);
1301 MDP_OUTP(MDP_BASE + 0x502ac, 0x610003d7);
1302 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf84000d5);
1303 MDP_OUTP(MDP_BASE + 0x502b0, 0x5c8003d7);
1304 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf7c000e9);
1305 MDP_OUTP(MDP_BASE + 0x502b4, 0x580003d7);
1306 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf74000fd);
1307 MDP_OUTP(MDP_BASE + 0x502b8, 0x534003d8);
1308 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c00112);
1309 MDP_OUTP(MDP_BASE + 0x502bc, 0x4e8003d8);
1310 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6800126);
1311 MDP_OUTP(MDP_BASE + 0x502c0, 0x494003da);
1312 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600013a);
1313 MDP_OUTP(MDP_BASE + 0x502c4, 0x448003db);
1314 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600014d);
1315 MDP_OUTP(MDP_BASE + 0x502c8, 0x3f4003dd);
1316 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00160);
1317 MDP_OUTP(MDP_BASE + 0x502cc, 0x3a4003df);
1318 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00172);
1319 MDP_OUTP(MDP_BASE + 0x502d0, 0x354003e1);
1320 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00184);
1321 MDP_OUTP(MDP_BASE + 0x502d4, 0x304003e3);
1322 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6000195);
1323 MDP_OUTP(MDP_BASE + 0x502d8, 0x2b0003e6);
1324 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf64001a6);
1325 MDP_OUTP(MDP_BASE + 0x502dc, 0x260003e8);
1326 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c001b4);
1327 MDP_OUTP(MDP_BASE + 0x502e0, 0x214003eb);
1328 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf78001c2);
1329 MDP_OUTP(MDP_BASE + 0x502e4, 0x1c4003ee);
1330 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf80001cf);
1331 MDP_OUTP(MDP_BASE + 0x502e8, 0x17c003f1);
1332 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf90001db);
1333 MDP_OUTP(MDP_BASE + 0x502ec, 0x134003f3);
1334 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa0001e5);
1335 MDP_OUTP(MDP_BASE + 0x502f0, 0xf0003f6);
1336 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb4001ee);
1337 MDP_OUTP(MDP_BASE + 0x502f4, 0xac003f9);
1338 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc001f5);
1339 MDP_OUTP(MDP_BASE + 0x502f8, 0x70003fb);
1340 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe4001fb);
1341 MDP_OUTP(MDP_BASE + 0x502fc, 0x34003fe);
1342}
1343
1344static void mdp_load_bc_downscale_table_y_point8TO1(void)
1345{
1346 MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
1347 MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000);
1348 MDP_OUTP(MDP_BASE + 0x5fffc, 0xff80000d);
1349 MDP_OUTP(MDP_BASE + 0x50304, 0x7ec003f9);
1350 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec0001c);
1351 MDP_OUTP(MDP_BASE + 0x50308, 0x7d4003f3);
1352 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40002b);
1353 MDP_OUTP(MDP_BASE + 0x5030c, 0x7b8003ed);
1354 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfd80003c);
1355 MDP_OUTP(MDP_BASE + 0x50310, 0x794003e8);
1356 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc0004d);
1357 MDP_OUTP(MDP_BASE + 0x50314, 0x76c003e4);
1358 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfc40005f);
1359 MDP_OUTP(MDP_BASE + 0x50318, 0x73c003e0);
1360 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb800071);
1361 MDP_OUTP(MDP_BASE + 0x5031c, 0x708003de);
1362 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfac00085);
1363 MDP_OUTP(MDP_BASE + 0x50320, 0x6d0003db);
1364 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa000098);
1365 MDP_OUTP(MDP_BASE + 0x50324, 0x698003d9);
1366 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf98000ac);
1367 MDP_OUTP(MDP_BASE + 0x50328, 0x654003d8);
1368 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8c000c1);
1369 MDP_OUTP(MDP_BASE + 0x5032c, 0x610003d7);
1370 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf84000d5);
1371 MDP_OUTP(MDP_BASE + 0x50330, 0x5c8003d7);
1372 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf7c000e9);
1373 MDP_OUTP(MDP_BASE + 0x50334, 0x580003d7);
1374 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf74000fd);
1375 MDP_OUTP(MDP_BASE + 0x50338, 0x534003d8);
1376 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c00112);
1377 MDP_OUTP(MDP_BASE + 0x5033c, 0x4e8003d8);
1378 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6800126);
1379 MDP_OUTP(MDP_BASE + 0x50340, 0x494003da);
1380 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600013a);
1381 MDP_OUTP(MDP_BASE + 0x50344, 0x448003db);
1382 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600014d);
1383 MDP_OUTP(MDP_BASE + 0x50348, 0x3f4003dd);
1384 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00160);
1385 MDP_OUTP(MDP_BASE + 0x5034c, 0x3a4003df);
1386 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00172);
1387 MDP_OUTP(MDP_BASE + 0x50350, 0x354003e1);
1388 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00184);
1389 MDP_OUTP(MDP_BASE + 0x50354, 0x304003e3);
1390 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6000195);
1391 MDP_OUTP(MDP_BASE + 0x50358, 0x2b0003e6);
1392 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf64001a6);
1393 MDP_OUTP(MDP_BASE + 0x5035c, 0x260003e8);
1394 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c001b4);
1395 MDP_OUTP(MDP_BASE + 0x50360, 0x214003eb);
1396 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf78001c2);
1397 MDP_OUTP(MDP_BASE + 0x50364, 0x1c4003ee);
1398 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf80001cf);
1399 MDP_OUTP(MDP_BASE + 0x50368, 0x17c003f1);
1400 MDP_OUTP(MDP_BASE + 0x5fffc, 0xf90001db);
1401 MDP_OUTP(MDP_BASE + 0x5036c, 0x134003f3);
1402 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa0001e5);
1403 MDP_OUTP(MDP_BASE + 0x50370, 0xf0003f6);
1404 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb4001ee);
1405 MDP_OUTP(MDP_BASE + 0x50374, 0xac003f9);
1406 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc001f5);
1407 MDP_OUTP(MDP_BASE + 0x50378, 0x70003fb);
1408 MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe4001fb);
1409 MDP_OUTP(MDP_BASE + 0x5037c, 0x34003fe);
1410}
1411
1412static int mdp_get_edge_cond(MDPIBUF *iBuf, uint32 *dup, uint32 *dup2)
1413{
1414 uint32 reg;
1415 uint32 dst_roi_width; /* Dimensions of DST ROI. */
1416 uint32 dst_roi_height; /* Used to calculate scaling ratios. */
1417
1418 /*
1419 * positions of the luma pixel(relative to the image ) required for
1420 * scaling the ROI
1421 */
1422 int32 luma_interp_point_left = 0; /* left-most luma pixel needed */
1423 int32 luma_interp_point_right = 0; /* right-most luma pixel needed */
1424 int32 luma_interp_point_top = 0; /* top-most luma pixel needed */
1425 int32 luma_interp_point_bottom = 0; /* bottom-most luma pixel needed */
1426
1427 /*
1428 * positions of the chroma pixel(relative to the image ) required for
1429 * interpolating a chroma value at all required luma positions
1430 */
1431 /* left-most chroma pixel needed */
1432 int32 chroma_interp_point_left = 0;
1433 /* right-most chroma pixel needed */
1434 int32 chroma_interp_point_right = 0;
1435 /* top-most chroma pixel needed */
1436 int32 chroma_interp_point_top = 0;
1437 /* bottom-most chroma pixel needed */
1438 int32 chroma_interp_point_bottom = 0;
1439
1440 /*
1441 * a rectangular region within the chroma plane of the "image".
1442 * Chroma pixels falling inside of this rectangle belongs to the ROI
1443 */
1444 int32 chroma_bound_left = 0;
1445 int32 chroma_bound_right = 0;
1446 int32 chroma_bound_top = 0;
1447 int32 chroma_bound_bottom = 0;
1448
1449 /*
1450 * number of chroma pixels to replicate on the left, right,
1451 * top and bottom edge of the ROI.
1452 */
1453 int32 chroma_repeat_left = 0;
1454 int32 chroma_repeat_right = 0;
1455 int32 chroma_repeat_top = 0;
1456 int32 chroma_repeat_bottom = 0;
1457
1458 /*
1459 * number of luma pixels to replicate on the left, right,
1460 * top and bottom edge of the ROI.
1461 */
1462 int32 luma_repeat_left = 0;
1463 int32 luma_repeat_right = 0;
1464 int32 luma_repeat_top = 0;
1465 int32 luma_repeat_bottom = 0;
1466
1467 boolean chroma_edge_enable;
1468
1469 uint32 _is_scale_enabled = 0;
1470 uint32 _is_yuv_offsite_vertical = 0;
1471
1472 /* fg edge duplicate */
1473 reg = 0x0;
1474
1475 if (iBuf->mdpImg.mdpOp & MDPOP_ASCALE) { /* if scaling enabled */
1476
1477 _is_scale_enabled = 1;
1478
1479 /*
1480 * if rotation mode involves a 90 deg rotation, flip
1481 * dst_roi_width with dst_roi_height.
1482 * Scaling ratios is based on source ROI dimensions, and
1483 * dst ROI dimensions before rotation.
1484 */
1485 if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) {
1486 dst_roi_width = iBuf->roi.dst_height;
1487 dst_roi_height = iBuf->roi.dst_width;
1488 } else {
1489 dst_roi_width = iBuf->roi.dst_width;
1490 dst_roi_height = iBuf->roi.dst_height;
1491 }
1492
1493 /*
1494 * Find out the luma pixels needed for scaling in the
1495 * x direction (LEFT and RIGHT). Locations of pixels are
1496 * relative to the ROI. Upper-left corner of ROI corresponds
1497 * to coordinates (0,0). Also set the number of luma pixel
1498 * to repeat.
1499 */
1500 if (iBuf->roi.width > 3 * dst_roi_width) {
1501 /* scale factor < 1/3 */
1502 luma_interp_point_left = 0;
1503 luma_interp_point_right = (iBuf->roi.width - 1);
1504 luma_repeat_left = 0;
1505 luma_repeat_right = 0;
1506 } else if (iBuf->roi.width == 3 * dst_roi_width) {
1507 /* scale factor == 1/3 */
1508 luma_interp_point_left = 0;
1509 luma_interp_point_right = (iBuf->roi.width - 1) + 1;
1510 luma_repeat_left = 0;
1511 luma_repeat_right = 1;
1512 } else if ((iBuf->roi.width > dst_roi_width) &&
1513 (iBuf->roi.width < 3 * dst_roi_width)) {
1514 /* 1/3 < scale factor < 1 */
1515 luma_interp_point_left = -1;
1516 luma_interp_point_right = (iBuf->roi.width - 1) + 1;
1517 luma_repeat_left = 1;
1518 luma_repeat_right = 1;
1519 }
1520
1521 else if (iBuf->roi.width == dst_roi_width) {
1522 /* scale factor == 1 */
1523 luma_interp_point_left = -1;
1524 luma_interp_point_right = (iBuf->roi.width - 1) + 2;
1525 luma_repeat_left = 1;
1526 luma_repeat_right = 2;
1527 } else { /* (iBuf->roi.width < dst_roi_width) */
1528 /* scale factor > 1 */
1529 luma_interp_point_left = -2;
1530 luma_interp_point_right = (iBuf->roi.width - 1) + 2;
1531 luma_repeat_left = 2;
1532 luma_repeat_right = 2;
1533 }
1534
1535 /*
1536 * Find out the number of pixels needed for scaling in the
1537 * y direction (TOP and BOTTOM). Locations of pixels are
1538 * relative to the ROI. Upper-left corner of ROI corresponds
1539 * to coordinates (0,0). Also set the number of luma pixel
1540 * to repeat.
1541 */
1542 if (iBuf->roi.height > 3 * dst_roi_height) {
1543 /* scale factor < 1/3 */
1544 luma_interp_point_top = 0;
1545 luma_interp_point_bottom = (iBuf->roi.height - 1);
1546 luma_repeat_top = 0;
1547 luma_repeat_bottom = 0;
1548 } else if (iBuf->roi.height == 3 * dst_roi_height) {
1549 /* scale factor == 1/3 */
1550 luma_interp_point_top = 0;
1551 luma_interp_point_bottom = (iBuf->roi.height - 1) + 1;
1552 luma_repeat_top = 0;
1553 luma_repeat_bottom = 1;
1554 } else if ((iBuf->roi.height > dst_roi_height) &&
1555 (iBuf->roi.height < 3 * dst_roi_height)) {
1556 /* 1/3 < scale factor < 1 */
1557 luma_interp_point_top = -1;
1558 luma_interp_point_bottom = (iBuf->roi.height - 1) + 1;
1559 luma_repeat_top = 1;
1560 luma_repeat_bottom = 1;
1561 } else if (iBuf->roi.height == dst_roi_height) {
1562 /* scale factor == 1 */
1563 luma_interp_point_top = -1;
1564 luma_interp_point_bottom = (iBuf->roi.height - 1) + 2;
1565 luma_repeat_top = 1;
1566 luma_repeat_bottom = 2;
1567 } else { /* (iBuf->roi.height < dst_roi_height) */
1568 /* scale factor > 1 */
1569 luma_interp_point_top = -2;
1570 luma_interp_point_bottom = (iBuf->roi.height - 1) + 2;
1571 luma_repeat_top = 2;
1572 luma_repeat_bottom = 2;
1573 }
1574 } /* if (iBuf->scale.scale_flag) */
1575 else { /* scaling disabled */
1576 /*
1577 * Since no scaling needed, Tile Fetch does not require any
1578 * more luma pixel than what the ROI contains.
1579 */
1580 luma_interp_point_left = (int32) 0;
1581 luma_interp_point_right = (int32) (iBuf->roi.width - 1);
1582 luma_interp_point_top = (int32) 0;
1583 luma_interp_point_bottom = (int32) (iBuf->roi.height - 1);
1584
1585 luma_repeat_left = 0;
1586 luma_repeat_right = 0;
1587 luma_repeat_top = 0;
1588 luma_repeat_bottom = 0;
1589 }
1590
1591 /* After adding the ROI offsets, we have locations of
1592 * luma_interp_points relative to the image.
1593 */
1594 luma_interp_point_left += (int32) (iBuf->roi.x);
1595 luma_interp_point_right += (int32) (iBuf->roi.x);
1596 luma_interp_point_top += (int32) (iBuf->roi.y);
1597 luma_interp_point_bottom += (int32) (iBuf->roi.y);
1598
1599 /*
1600 * After adding the ROI offsets, we have locations of
1601 * chroma_interp_points relative to the image.
1602 */
1603 chroma_interp_point_left = luma_interp_point_left;
1604 chroma_interp_point_right = luma_interp_point_right;
1605 chroma_interp_point_top = luma_interp_point_top;
1606 chroma_interp_point_bottom = luma_interp_point_bottom;
1607
1608 chroma_edge_enable = TRUE;
1609 /* find out which chroma pixels are needed for chroma upsampling. */
1610 switch (iBuf->mdpImg.imgType) {
1611 /*
1612 * cosite in horizontal axis
1613 * fully sampled in vertical axis
1614 */
1615 case MDP_Y_CBCR_H2V1:
1616 case MDP_Y_CRCB_H2V1:
1617 case MDP_YCRYCB_H2V1:
1618 /* floor( luma_interp_point_left / 2 ); */
1619 chroma_interp_point_left = luma_interp_point_left >> 1;
1620 /* floor( ( luma_interp_point_right + 1 ) / 2 ); */
1621 chroma_interp_point_right = (luma_interp_point_right + 1) >> 1;
1622
1623 chroma_interp_point_top = luma_interp_point_top;
1624 chroma_interp_point_bottom = luma_interp_point_bottom;
1625 break;
1626
1627 /*
1628 * cosite in horizontal axis
1629 * offsite in vertical axis
1630 */
1631 case MDP_Y_CBCR_H2V2:
1632 case MDP_Y_CRCB_H2V2:
1633 /* floor( luma_interp_point_left / 2) */
1634 chroma_interp_point_left = luma_interp_point_left >> 1;
1635
1636 /* floor( ( luma_interp_point_right + 1 )/ 2 ) */
1637 chroma_interp_point_right = (luma_interp_point_right + 1) >> 1;
1638
1639 /* floor( (luma_interp_point_top - 1 ) / 2 ) */
1640 chroma_interp_point_top = (luma_interp_point_top - 1) >> 1;
1641
1642 /* floor( ( luma_interp_point_bottom + 1 ) / 2 ) */
1643 chroma_interp_point_bottom =
1644 (luma_interp_point_bottom + 1) >> 1;
1645
1646 _is_yuv_offsite_vertical = 1;
1647 break;
1648
1649 default:
1650 chroma_edge_enable = FALSE;
1651 chroma_interp_point_left = luma_interp_point_left;
1652 chroma_interp_point_right = luma_interp_point_right;
1653 chroma_interp_point_top = luma_interp_point_top;
1654 chroma_interp_point_bottom = luma_interp_point_bottom;
1655
1656 break;
1657 }
1658
1659 /* only if the image type is in YUV domain, we calculate chroma edge */
1660 if (chroma_edge_enable) {
1661 /* Defines which chroma pixels belongs to the roi */
1662 switch (iBuf->mdpImg.imgType) {
1663 /*
1664 * Cosite in horizontal direction, and fully sampled
1665 * in vertical direction.
1666 */
1667 case MDP_Y_CBCR_H2V1:
1668 case MDP_Y_CRCB_H2V1:
1669 case MDP_YCRYCB_H2V1:
1670 /*
1671 * width of chroma ROI is 1/2 of size of luma ROI
1672 * height of chroma ROI same as size of luma ROI
1673 */
1674 chroma_bound_left = iBuf->roi.x / 2;
1675
1676 /* there are half as many chroma pixel as luma pixels */
1677 chroma_bound_right =
1678 (iBuf->roi.width + iBuf->roi.x - 1) / 2;
1679 chroma_bound_top = iBuf->roi.y;
1680 chroma_bound_bottom =
1681 (iBuf->roi.height + iBuf->roi.y - 1);
1682 break;
1683
1684 case MDP_Y_CBCR_H2V2:
1685 case MDP_Y_CRCB_H2V2:
1686 /*
1687 * cosite in horizontal dir, and offsite in vertical dir
1688 * width of chroma ROI is 1/2 of size of luma ROI
1689 * height of chroma ROI is 1/2 of size of luma ROI
1690 */
1691
1692 chroma_bound_left = iBuf->roi.x / 2;
1693 chroma_bound_right =
1694 (iBuf->roi.width + iBuf->roi.x - 1) / 2;
1695 chroma_bound_top = iBuf->roi.y / 2;
1696 chroma_bound_bottom =
1697 (iBuf->roi.height + iBuf->roi.y - 1) / 2;
1698 break;
1699
1700 default:
1701 /*
1702 * If no valid chroma sub-sampling format specified,
1703 * assume 4:4:4 ( i.e. fully sampled). Set ROI
1704 * boundaries for chroma same as ROI boundaries for
1705 * luma.
1706 */
1707 chroma_bound_left = iBuf->roi.x;
1708 chroma_bound_right = iBuf->roi.width + iBuf->roi.x - 1;
1709 chroma_bound_top = iBuf->roi.y;
1710 chroma_bound_bottom =
1711 (iBuf->roi.height + iBuf->roi.y - 1);
1712 break;
1713 }
1714
1715 /*
1716 * Knowing which chroma pixels are needed, and which chroma
1717 * pixels belong to the ROI (i.e. available for fetching ),
1718 * calculate how many chroma pixels Tile Fetch needs to
1719 * duplicate. If any required chroma pixels falls outside
1720 * of the ROI, Tile Fetch must obtain them by replicating
1721 * pixels.
1722 */
1723 if (chroma_bound_left > chroma_interp_point_left)
1724 chroma_repeat_left =
1725 chroma_bound_left - chroma_interp_point_left;
1726 else
1727 chroma_repeat_left = 0;
1728
1729 if (chroma_interp_point_right > chroma_bound_right)
1730 chroma_repeat_right =
1731 chroma_interp_point_right - chroma_bound_right;
1732 else
1733 chroma_repeat_right = 0;
1734
1735 if (chroma_bound_top > chroma_interp_point_top)
1736 chroma_repeat_top =
1737 chroma_bound_top - chroma_interp_point_top;
1738 else
1739 chroma_repeat_top = 0;
1740
1741 if (chroma_interp_point_bottom > chroma_bound_bottom)
1742 chroma_repeat_bottom =
1743 chroma_interp_point_bottom - chroma_bound_bottom;
1744 else
1745 chroma_repeat_bottom = 0;
1746
1747 if (_is_scale_enabled && (iBuf->roi.height == 1)
1748 && _is_yuv_offsite_vertical) {
1749 chroma_repeat_bottom = 3;
1750 chroma_repeat_top = 0;
1751 }
1752 }
1753 /* make sure chroma repeats are non-negative */
1754 if ((chroma_repeat_left < 0) || (chroma_repeat_right < 0) ||
1755 (chroma_repeat_top < 0) || (chroma_repeat_bottom < 0))
1756 return -1;
1757
1758 /* make sure chroma repeats are no larger than 3 pixels */
1759 if ((chroma_repeat_left > 3) || (chroma_repeat_right > 3) ||
1760 (chroma_repeat_top > 3) || (chroma_repeat_bottom > 3))
1761 return -1;
1762
1763 /* make sure luma repeats are non-negative */
1764 if ((luma_repeat_left < 0) || (luma_repeat_right < 0) ||
1765 (luma_repeat_top < 0) || (luma_repeat_bottom < 0))
1766 return -1;
1767
1768 /* make sure luma repeats are no larger than 3 pixels */
1769 if ((luma_repeat_left > 3) || (luma_repeat_right > 3) ||
1770 (luma_repeat_top > 3) || (luma_repeat_bottom > 3))
1771 return -1;
1772
1773 /* write chroma_repeat_left to register */
1774 reg |= (chroma_repeat_left & 3) << MDP_LEFT_CHROMA;
1775
1776 /* write chroma_repeat_right to register */
1777 reg |= (chroma_repeat_right & 3) << MDP_RIGHT_CHROMA;
1778
1779 /* write chroma_repeat_top to register */
1780 reg |= (chroma_repeat_top & 3) << MDP_TOP_CHROMA;
1781
1782 /* write chroma_repeat_bottom to register */
1783 reg |= (chroma_repeat_bottom & 3) << MDP_BOTTOM_CHROMA;
1784
1785 /* write luma_repeat_left to register */
1786 reg |= (luma_repeat_left & 3) << MDP_LEFT_LUMA;
1787
1788 /* write luma_repeat_right to register */
1789 reg |= (luma_repeat_right & 3) << MDP_RIGHT_LUMA;
1790
1791 /* write luma_repeat_top to register */
1792 reg |= (luma_repeat_top & 3) << MDP_TOP_LUMA;
1793
1794 /* write luma_repeat_bottom to register */
1795 reg |= (luma_repeat_bottom & 3) << MDP_BOTTOM_LUMA;
1796
1797 /* done with reg */
1798 *dup = reg;
1799
1800 /* bg edge duplicate */
1801 reg = 0x0;
1802
1803 switch (iBuf->ibuf_type) {
1804 case MDP_Y_CBCR_H2V2:
1805 case MDP_Y_CRCB_H2V2:
1806 /*
1807 * Edge condition for MDP_Y_CRCB/CBCR_H2V2 cosite only.
1808 * For 420 cosite, 1 chroma replicated on all sides except
1809 * left, so reg 101b8 should be 0x0209. For 420 offsite,
1810 * 1 chroma replicated all sides.
1811 */
1812 if (iBuf->roi.lcd_y == 0) {
1813 reg |= BIT(MDP_TOP_CHROMA);
1814 }
1815
1816 if ((iBuf->roi.lcd_y + iBuf->roi.dst_height) ==
1817 iBuf->ibuf_height) {
1818 reg |= BIT(MDP_BOTTOM_CHROMA);
1819 }
1820
1821 if (((iBuf->roi.lcd_x + iBuf->roi.dst_width) ==
1822 iBuf->ibuf_width) && ((iBuf->roi.dst_width % 2) == 0)) {
1823 reg |= BIT(MDP_RIGHT_CHROMA);
1824 }
1825
1826 break;
1827
1828 case MDP_Y_CBCR_H2V1:
1829 case MDP_Y_CRCB_H2V1:
1830 case MDP_YCRYCB_H2V1:
1831 if (((iBuf->roi.lcd_x + iBuf->roi.dst_width) ==
1832 iBuf->ibuf_width) && ((iBuf->roi.dst_width % 2) == 0)) {
1833 reg |= BIT(MDP_RIGHT_CHROMA);
1834 }
1835 break;
1836 default:
1837 break;
1838 }
1839
1840 *dup2 = reg;
1841
1842 return 0;
1843}
1844
1845#define ADJUST_IP /* for 1/3 scale factor fix */
1846
1847static int mdp_calc_scale_params(
1848/* ROI origin coordinate for the dimension */
1849 uint32 org,
1850/* src ROI dimension */
1851 uint32 dim_in,
1852/* scaled ROI dimension*/
1853 uint32 dim_out,
1854/* is this ROI width dimension? */
1855 boolean is_W,
1856/* initial phase location address */
1857 int32 *phase_init_ptr,
1858/* phase increment location address */
1859 uint32 *phase_step_ptr,
1860/* ROI start over-fetch location address */
1861 uint32 *num_repl_beg_ptr,
1862/* ROI end over-fetch location address */
1863 uint32 *num_repl_end_ptr)
1864{
1865 boolean rpa_on = FALSE;
1866 int init_phase = 0;
1867 uint32 beg_of = 0;
1868 uint32 end_of = 0;
1869 uint64 numer = 0;
1870 uint64 denom = 0;
1871 /*uint64 inverter = 1; */
1872 int64 point5 = 1;
1873 int64 one = 1;
1874 int64 k1, k2, k3, k4; /* linear equation coefficients */
1875 uint64 int_mask;
1876 uint64 fract_mask;
1877 uint64 Os;
1878 int64 Osprime;
1879 int64 Od;
1880 int64 Odprime;
1881 int64 Oreq;
1882 uint64 Es;
1883 uint64 Ed;
1884 uint64 Ereq;
1885#ifdef ADJUST_IP
1886 int64 IP64;
1887 int64 delta;
1888#endif
1889 uint32 mult;
1890
1891 /*
1892 * The phase accumulator should really be rational for all cases in a
1893 * general purpose polyphase scaler for a tiled architecture with
1894 * non-zero * origin capability because there is no way to represent
1895 * certain scale factors in fixed point regardless of precision.
1896 * The error incurred in attempting to use fixed point is most
1897 * eggregious for SF where 1/SF is an integral multiple of 1/3.
1898 *
1899 * However, since the MDP2 has already been committed to HW, we
1900 * only use the rational phase accumulator (RPA) when 1/SF is an
1901 * integral multiple of 1/3. This will help minimize regressions in
1902 * matching the HW to the C-Sim.
1903 */
1904 /*
1905 * Set the RPA flag for this dimension.
1906 *
1907 * In order for 1/SF (dim_in/dim_out) to be an integral multiple of
1908 * 1/3, dim_out must be an integral multiple of 3.
1909 */
1910 if (!(dim_out % 3)) {
1911 mult = dim_out / 3;
1912 rpa_on = (!(dim_in % mult));
1913 }
1914
1915 numer = dim_out;
1916 denom = dim_in;
1917
1918 /*
1919 * convert to U30.34 before division
1920 *
1921 * The K vectors carry 4 extra bits of precision
1922 * and are rounded.
1923 *
1924 * We initially go 5 bits over then round by adding
1925 * 1 and right shifting by 1
1926 * so final result is U31.33
1927 */
1928 numer <<= PQF_PLUS_5;
1929
1930 /* now calculate the scale factor (aka k3) */
1931 k3 = ((mdp_do_div(numer, denom) + 1) >> 1);
1932
1933 /* check scale factor for legal range [0.25 - 4.0] */
1934 if (((k3 >> 4) < (1LL << PQF_MINUS_2)) ||
1935 ((k3 >> 4) > (1LL << PQF_PLUS_2))) {
1936 return -1;
1937 }
1938
1939 /* calculate inverse scale factor (aka k1) for phase init */
1940 numer = dim_in;
1941 denom = dim_out;
1942 numer <<= PQF_PLUS_5;
1943 k1 = ((mdp_do_div(numer, denom) + 1) >> 1);
1944
1945 /*
1946 * calculate initial phase and ROI overfetch
1947 */
1948 /* convert point5 & one to S39.24 (will always be positive) */
1949 point5 <<= (PQF_PLUS_4 - 1);
1950 one <<= PQF_PLUS_4;
1951 k2 = ((k1 - one) >> 1);
1952 init_phase = (int)(k2 >> 4);
1953 k4 = ((k3 - one) >> 1);
1954 if (k3 == one) {
1955 /* the simple case; SF = 1.0 */
1956 beg_of = 1;
1957 end_of = 2;
1958 } else {
1959 /* calculate the masks */
1960 fract_mask = one - 1;
1961 int_mask = ~fract_mask;
1962
1963 if (!rpa_on) {
1964 /*
1965 * FIXED POINT IMPLEMENTATION
1966 */
1967 if (!org) {
1968 /* A fairly simple case; ROI origin = 0 */
1969 if (k1 < one) {
1970 /* upscaling */
1971 beg_of = end_of = 2;
1972 }
1973 /* 0.33 <= SF < 1.0 */
1974 else if (k1 < (3LL << PQF_PLUS_4))
1975 beg_of = end_of = 1;
1976 /* 0.33 == SF */
1977 else if (k1 == (3LL << PQF_PLUS_4)) {
1978 beg_of = 0;
1979 end_of = 1;
1980 }
1981 /* 0.25 <= SF < 0.33 */
1982 else
1983 beg_of = end_of = 0;
1984 } else {
1985 /*
1986 * The complicated case; ROI origin != 0
1987 * init_phase needs to be adjusted
1988 * OF is also position dependent
1989 */
1990
1991 /* map (org - .5) into destination space */
1992 Os = ((uint64) org << 1) - 1;
1993 Od = ((k3 * Os) >> 1) + k4;
1994
1995 /* take the ceiling */
1996 Odprime = (Od & int_mask);
1997 if (Odprime != Od)
1998 Odprime += one;
1999
2000 /* now map that back to source space */
2001 Osprime = (k1 * (Odprime >> PQF_PLUS_4)) + k2;
2002
2003 /* then floor & decrement to calculate the required
2004 starting coordinate */
2005 Oreq = (Osprime & int_mask) - one;
2006
2007 /* calculate end coord in destination space then map to
2008 source space */
2009 Ed = Odprime +
2010 ((uint64) dim_out << PQF_PLUS_4) - one;
2011 Es = (k1 * (Ed >> PQF_PLUS_4)) + k2;
2012
2013 /* now floor & increment by 2 to calculate the required
2014 ending coordinate */
2015 Ereq = (Es & int_mask) + (one << 1);
2016
2017 /* calculate initial phase */
2018#ifdef ADJUST_IP
2019
2020 IP64 = Osprime - Oreq;
2021 delta = ((int64) (org) << PQF_PLUS_4) - Oreq;
2022 IP64 -= delta;
2023
2024 /* limit to valid range before the left shift */
2025 delta = (IP64 & (1LL << 63)) ? 4 : -4;
2026 delta <<= PQF_PLUS_4;
2027 while (abs((int)(IP64 >> PQF_PLUS_4)) > 4)
2028 IP64 += delta;
2029
2030 /* right shift to account for extra bits of precision */
2031 init_phase = (int)(IP64 >> 4);
2032
2033#else /* ADJUST_IP */
2034
2035 /* just calculate the real initial phase */
2036 init_phase = (int)((Osprime - Oreq) >> 4);
2037
2038#endif /* ADJUST_IP */
2039
2040 /* calculate the overfetch */
2041 beg_of = org - (uint32) (Oreq >> PQF_PLUS_4);
2042 end_of =
2043 (uint32) (Ereq >> PQF_PLUS_4) - (org +
2044 dim_in -
2045 1);
2046 }
2047 } else {
2048 /*
2049 * RPA IMPLEMENTATION
2050 *
2051 * init_phase needs to be calculated in all RPA_on cases
2052 * because it's a numerator, not a fixed point value.
2053 */
2054
2055 /* map (org - .5) into destination space */
2056 Os = ((uint64) org << PQF_PLUS_4) - point5;
2057 Od = mdp_do_div((dim_out * (Os + point5)),
2058 dim_in) - point5;
2059
2060 /* take the ceiling */
2061 Odprime = (Od & int_mask);
2062 if (Odprime != Od)
2063 Odprime += one;
2064
2065 /* now map that back to source space */
2066 Osprime =
2067 mdp_do_div((dim_in * (Odprime + point5)),
2068 dim_out) - point5;
2069
2070 /* then floor & decrement to calculate the required
2071 starting coordinate */
2072 Oreq = (Osprime & int_mask) - one;
2073
2074 /* calculate end coord in destination space then map to
2075 source space */
2076 Ed = Odprime + ((uint64) dim_out << PQF_PLUS_4) - one;
2077 Es = mdp_do_div((dim_in * (Ed + point5)),
2078 dim_out) - point5;
2079
2080 /* now floor & increment by 2 to calculate the required
2081 ending coordinate */
2082 Ereq = (Es & int_mask) + (one << 1);
2083
2084 /* calculate initial phase */
2085
2086#ifdef ADJUST_IP
2087
2088 IP64 = Osprime - Oreq;
2089 delta = ((int64) (org) << PQF_PLUS_4) - Oreq;
2090 IP64 -= delta;
2091
2092 /* limit to valid range before the left shift */
2093 delta = (IP64 & (1LL << 63)) ? 4 : -4;
2094 delta <<= PQF_PLUS_4;
2095 while (abs((int)(IP64 >> PQF_PLUS_4)) > 4)
2096 IP64 += delta;
2097
2098 /* right shift to account for extra bits of precision */
2099 init_phase = (int)(IP64 >> 4);
2100
2101#else /* ADJUST_IP */
2102
2103 /* just calculate the real initial phase */
2104 init_phase = (int)((Osprime - Oreq) >> 4);
2105
2106#endif /* ADJUST_IP */
2107
2108 /* calculate the overfetch */
2109 beg_of = org - (uint32) (Oreq >> PQF_PLUS_4);
2110 end_of =
2111 (uint32) (Ereq >> PQF_PLUS_4) - (org + dim_in - 1);
2112 }
2113 }
2114
2115 /* return the scale parameters */
2116 *phase_init_ptr = init_phase;
2117 *phase_step_ptr = (uint32) (k1 >> 4);
2118 *num_repl_beg_ptr = beg_of;
2119 *num_repl_end_ptr = end_of;
2120
2121 return 0;
2122}
2123
2124static uint8 *mdp_adjust_rot_addr(MDPIBUF *iBuf, uint8 *addr, uint32 uv)
2125{
2126 uint32 dest_ystride = iBuf->ibuf_width * iBuf->bpp;
2127 uint32 h_slice = 1;
2128
2129 if (uv && ((iBuf->ibuf_type == MDP_Y_CBCR_H2V2) ||
2130 (iBuf->ibuf_type == MDP_Y_CRCB_H2V2)))
2131 h_slice = 2;
2132
2133 if (MDP_CHKBIT(iBuf->mdpImg.mdpOp, MDPOP_ROT90) ^
2134 MDP_CHKBIT(iBuf->mdpImg.mdpOp, MDPOP_LR)) {
2135 addr =
2136 addr + (iBuf->roi.dst_width -
2137 MIN(16, iBuf->roi.dst_width)) * iBuf->bpp;
2138 }
2139 if (MDP_CHKBIT(iBuf->mdpImg.mdpOp, MDPOP_UD)) {
2140 addr =
2141 addr + ((iBuf->roi.dst_height -
2142 MIN(16, iBuf->roi.dst_height))/h_slice) * dest_ystride;
2143 }
2144
2145 return addr;
2146}
2147
2148void mdp_set_scale(MDPIBUF *iBuf,
2149 uint32 dst_roi_width,
2150 uint32 dst_roi_height,
2151 boolean inputRGB, boolean outputRGB, uint32 *pppop_reg_ptr)
2152{
2153 uint32 dst_roi_width_scale;
2154 uint32 dst_roi_height_scale;
2155 boolean use_pr;
2156 uint32 phasex_step = 0;
2157 uint32 phasey_step = 0;
2158 int32 phasex_init = 0;
2159 int32 phasey_init = 0;
2160 uint32 lines_dup = 0;
2161 uint32 lines_dup_bg = 0;
2162 uint32 dummy;
2163 uint32 mdp_blur = 0;
2164
2165 if (iBuf->mdpImg.mdpOp & MDPOP_ASCALE) {
2166 if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) {
2167 dst_roi_width_scale = dst_roi_height;
2168 dst_roi_height_scale = dst_roi_width;
2169 } else {
2170 dst_roi_width_scale = dst_roi_width;
2171 dst_roi_height_scale = dst_roi_height;
2172 }
2173
2174 mdp_blur = iBuf->mdpImg.mdpOp & MDPOP_BLUR;
2175
2176 if ((dst_roi_width_scale != iBuf->roi.width) ||
2177 (dst_roi_height_scale != iBuf->roi.height) ||
2178 mdp_blur) {
2179 *pppop_reg_ptr |=
2180 (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON);
2181
2182 /* let's use SHIM logic to calculate the partial ROI scaling */
2183#if 0
2184 phasex_step =
2185 (uint32) mdp_do_div(0x20000000 * iBuf->roi.width,
2186 dst_roi_width_scale);
2187 phasey_step =
2188 (uint32) mdp_do_div(0x20000000 * iBuf->roi.height,
2189 dst_roi_height_scale);
2190
2191/*
2192 phasex_step= ((long long) iBuf->roi.width * 0x20000000)/dst_roi_width_scale;
2193 phasey_step= ((long long)iBuf->roi.height * 0x20000000)/dst_roi_height_scale;
2194*/
2195
2196 phasex_init =
2197 (((long long)phasex_step - 0x20000000) >> 1);
2198 phasey_init =
2199 (((long long)phasey_step - 0x20000000) >> 1);
2200
2201#else
2202 mdp_calc_scale_params(iBuf->roi.x, iBuf->roi.width,
2203 dst_roi_width_scale, 1,
2204 &phasex_init, &phasex_step,
2205 &dummy, &dummy);
2206 mdp_calc_scale_params(iBuf->roi.y, iBuf->roi.height,
2207 dst_roi_height_scale, 0,
2208 &phasey_init, &phasey_step,
2209 &dummy, &dummy);
2210#endif
2211 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x013c,
2212 phasex_init);
2213 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0140,
2214 phasey_init);
2215 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0144,
2216 phasex_step);
2217 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0148,
2218 phasey_step);
2219
2220 use_pr = (inputRGB) && (outputRGB);
2221
2222 if ((dst_roi_width_scale > iBuf->roi.width) ||
2223 (dst_roi_height_scale > iBuf->roi.height)) {
2224 if ((use_pr)
2225 && (mdp_curr_up_scale_xy !=
2226 MDP_PR_SCALE_UP)) {
2227 mdp_load_pr_upscale_table();
2228 mdp_curr_up_scale_xy = MDP_PR_SCALE_UP;
2229 } else if ((!use_pr)
2230 && (mdp_curr_up_scale_xy !=
2231 MDP_BC_SCALE_UP)) {
2232 mdp_load_bc_upscale_table();
2233 mdp_curr_up_scale_xy = MDP_BC_SCALE_UP;
2234 }
2235 }
2236
2237 if (mdp_blur) {
2238 load_scale_table(mdp_gaussian_blur_table,
2239 ARRAY_SIZE(mdp_gaussian_blur_table));
2240 mdp_curr_down_scale_x = MDP_SCALE_BLUR;
2241 mdp_curr_down_scale_y = MDP_SCALE_BLUR;
2242 }
2243
2244 /* 0.2 < x <= 1 scaling factor */
2245 if ((dst_roi_width_scale <= iBuf->roi.width) &&
2246 !mdp_blur) {
2247 if (((dst_roi_width_scale * 10) /
2248 iBuf->roi.width) > 8) {
2249 if ((use_pr)
2250 && (mdp_curr_down_scale_x !=
2251 MDP_PR_SCALE_POINT8_1)) {
2252 mdp_load_pr_downscale_table_x_point8TO1
2253 ();
2254 mdp_curr_down_scale_x =
2255 MDP_PR_SCALE_POINT8_1;
2256 } else if ((!use_pr)
2257 && (mdp_curr_down_scale_x !=
2258 MDP_BC_SCALE_POINT8_1)) {
2259 mdp_load_bc_downscale_table_x_point8TO1
2260 ();
2261 mdp_curr_down_scale_x =
2262 MDP_BC_SCALE_POINT8_1;
2263 }
2264 } else
2265 if (((dst_roi_width_scale * 10) /
2266 iBuf->roi.width) > 6) {
2267 if ((use_pr)
2268 && (mdp_curr_down_scale_x !=
2269 MDP_PR_SCALE_POINT6_POINT8)) {
2270 mdp_load_pr_downscale_table_x_point6TOpoint8
2271 ();
2272 mdp_curr_down_scale_x =
2273 MDP_PR_SCALE_POINT6_POINT8;
2274 } else if ((!use_pr)
2275 && (mdp_curr_down_scale_x !=
2276 MDP_BC_SCALE_POINT6_POINT8))
2277 {
2278 mdp_load_bc_downscale_table_x_point6TOpoint8
2279 ();
2280 mdp_curr_down_scale_x =
2281 MDP_BC_SCALE_POINT6_POINT8;
2282 }
2283 } else
2284 if (((dst_roi_width_scale * 10) /
2285 iBuf->roi.width) > 4) {
2286 if ((use_pr)
2287 && (mdp_curr_down_scale_x !=
2288 MDP_PR_SCALE_POINT4_POINT6)) {
2289 mdp_load_pr_downscale_table_x_point4TOpoint6
2290 ();
2291 mdp_curr_down_scale_x =
2292 MDP_PR_SCALE_POINT4_POINT6;
2293 } else if ((!use_pr)
2294 && (mdp_curr_down_scale_x !=
2295 MDP_BC_SCALE_POINT4_POINT6))
2296 {
2297 mdp_load_bc_downscale_table_x_point4TOpoint6
2298 ();
2299 mdp_curr_down_scale_x =
2300 MDP_BC_SCALE_POINT4_POINT6;
2301 }
2302 } else {
2303 if ((use_pr)
2304 && (mdp_curr_down_scale_x !=
2305 MDP_PR_SCALE_POINT2_POINT4)) {
2306 mdp_load_pr_downscale_table_x_point2TOpoint4
2307 ();
2308 mdp_curr_down_scale_x =
2309 MDP_PR_SCALE_POINT2_POINT4;
2310 } else if ((!use_pr)
2311 && (mdp_curr_down_scale_x !=
2312 MDP_BC_SCALE_POINT2_POINT4))
2313 {
2314 mdp_load_bc_downscale_table_x_point2TOpoint4
2315 ();
2316 mdp_curr_down_scale_x =
2317 MDP_BC_SCALE_POINT2_POINT4;
2318 }
2319 }
2320 }
2321 /* 0.2 < y <= 1 scaling factor */
2322 if ((dst_roi_height_scale <= iBuf->roi.height) &&
2323 !mdp_blur) {
2324 if (((dst_roi_height_scale * 10) /
2325 iBuf->roi.height) > 8) {
2326 if ((use_pr)
2327 && (mdp_curr_down_scale_y !=
2328 MDP_PR_SCALE_POINT8_1)) {
2329 mdp_load_pr_downscale_table_y_point8TO1
2330 ();
2331 mdp_curr_down_scale_y =
2332 MDP_PR_SCALE_POINT8_1;
2333 } else if ((!use_pr)
2334 && (mdp_curr_down_scale_y !=
2335 MDP_BC_SCALE_POINT8_1)) {
2336 mdp_load_bc_downscale_table_y_point8TO1
2337 ();
2338 mdp_curr_down_scale_y =
2339 MDP_BC_SCALE_POINT8_1;
2340 }
2341 } else
2342 if (((dst_roi_height_scale * 10) /
2343 iBuf->roi.height) > 6) {
2344 if ((use_pr)
2345 && (mdp_curr_down_scale_y !=
2346 MDP_PR_SCALE_POINT6_POINT8)) {
2347 mdp_load_pr_downscale_table_y_point6TOpoint8
2348 ();
2349 mdp_curr_down_scale_y =
2350 MDP_PR_SCALE_POINT6_POINT8;
2351 } else if ((!use_pr)
2352 && (mdp_curr_down_scale_y !=
2353 MDP_BC_SCALE_POINT6_POINT8))
2354 {
2355 mdp_load_bc_downscale_table_y_point6TOpoint8
2356 ();
2357 mdp_curr_down_scale_y =
2358 MDP_BC_SCALE_POINT6_POINT8;
2359 }
2360 } else
2361 if (((dst_roi_height_scale * 10) /
2362 iBuf->roi.height) > 4) {
2363 if ((use_pr)
2364 && (mdp_curr_down_scale_y !=
2365 MDP_PR_SCALE_POINT4_POINT6)) {
2366 mdp_load_pr_downscale_table_y_point4TOpoint6
2367 ();
2368 mdp_curr_down_scale_y =
2369 MDP_PR_SCALE_POINT4_POINT6;
2370 } else if ((!use_pr)
2371 && (mdp_curr_down_scale_y !=
2372 MDP_BC_SCALE_POINT4_POINT6))
2373 {
2374 mdp_load_bc_downscale_table_y_point4TOpoint6
2375 ();
2376 mdp_curr_down_scale_y =
2377 MDP_BC_SCALE_POINT4_POINT6;
2378 }
2379 } else {
2380 if ((use_pr)
2381 && (mdp_curr_down_scale_y !=
2382 MDP_PR_SCALE_POINT2_POINT4)) {
2383 mdp_load_pr_downscale_table_y_point2TOpoint4
2384 ();
2385 mdp_curr_down_scale_y =
2386 MDP_PR_SCALE_POINT2_POINT4;
2387 } else if ((!use_pr)
2388 && (mdp_curr_down_scale_y !=
2389 MDP_BC_SCALE_POINT2_POINT4))
2390 {
2391 mdp_load_bc_downscale_table_y_point2TOpoint4
2392 ();
2393 mdp_curr_down_scale_y =
2394 MDP_BC_SCALE_POINT2_POINT4;
2395 }
2396 }
2397 }
2398 } else {
2399 iBuf->mdpImg.mdpOp &= ~(MDPOP_ASCALE);
2400 }
2401 }
2402 /* setting edge condition here after scaling check */
2403 if (mdp_get_edge_cond(iBuf, &lines_dup, &lines_dup_bg))
2404 printk(KERN_ERR "msm_fb: mdp_get_edge_cond() error!\n");
2405
2406 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01b8, lines_dup);
2407 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01bc, lines_dup_bg);
2408}
2409
2410void mdp_init_scale_table(void)
2411{
2412 mdp_curr_up_scale_xy = MDP_INIT_SCALE;
2413 mdp_curr_down_scale_x = MDP_INIT_SCALE;
2414 mdp_curr_down_scale_y = MDP_INIT_SCALE;
2415}
2416
2417void mdp_adjust_start_addr(uint8 **src0,
2418 uint8 **src1,
2419 int v_slice,
2420 int h_slice,
2421 int x,
2422 int y,
2423 uint32 width,
2424 uint32 height, int bpp, MDPIBUF *iBuf, int layer)
2425{
2426 *src0 += (x + y * width) * bpp;
2427
2428 /* if it's dest/bg buffer, we need to adjust it for rotation */
2429 if (layer != 0)
2430 *src0 = mdp_adjust_rot_addr(iBuf, *src0, 0);
2431
2432 if (*src1) {
2433 /*
2434 * MDP_Y_CBCR_H2V2/MDP_Y_CRCB_H2V2 cosite for now
2435 * we need to shift x direction same as y dir for offsite
2436 */
2437 *src1 +=
2438 ((x / h_slice) * h_slice +
2439 ((y == 0) ? 0 : ((y + 1) / v_slice - 1) * width)) * bpp;
2440
2441 /* if it's dest/bg buffer, we need to adjust it for rotation */
2442 if (layer != 0)
2443 *src1 = mdp_adjust_rot_addr(iBuf, *src1, 1);
2444 }
2445}
2446
2447void mdp_set_blend_attr(MDPIBUF *iBuf,
2448 uint32 *alpha,
2449 uint32 *tpVal,
2450 uint32 perPixelAlpha, uint32 *pppop_reg_ptr)
2451{
2452 if (perPixelAlpha) {
2453 *pppop_reg_ptr |= PPP_OP_ROT_ON |
2454 PPP_OP_BLEND_ON | PPP_OP_BLEND_SRCPIXEL_ALPHA;
2455 } else {
2456 if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
2457 && (iBuf->mdpImg.alpha == 0xff)) {
2458 iBuf->mdpImg.mdpOp &= ~(MDPOP_ALPHAB);
2459 }
2460
2461 if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
2462 && (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)) {
2463 *pppop_reg_ptr |=
2464 PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
2465 PPP_OP_BLEND_CONSTANT_ALPHA |
2466 PPP_OP_BLEND_ALPHA_BLEND_NORMAL |
2467 PPP_BLEND_CALPHA_TRNASP;
2468
2469 *alpha = iBuf->mdpImg.alpha;
2470 *tpVal = iBuf->mdpImg.tpVal;
2471 } else {
2472 if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP) {
2473 *pppop_reg_ptr |= PPP_OP_ROT_ON |
2474 PPP_OP_BLEND_ON |
2475 PPP_OP_BLEND_SRCPIXEL_TRANSP;
2476 *tpVal = iBuf->mdpImg.tpVal;
2477 } else if (iBuf->mdpImg.mdpOp & MDPOP_ALPHAB) {
2478 *pppop_reg_ptr |= PPP_OP_ROT_ON |
2479 PPP_OP_BLEND_ON |
2480 PPP_OP_BLEND_ALPHA_BLEND_NORMAL |
2481 PPP_OP_BLEND_CONSTANT_ALPHA;
2482 *alpha = iBuf->mdpImg.alpha;
2483 }
2484 }
2485 }
2486}
diff --git a/drivers/staging/msm/mdp_ppp_v31.c b/drivers/staging/msm/mdp_ppp_v31.c
new file mode 100644
index 000000000000..76495dbe4e64
--- /dev/null
+++ b/drivers/staging/msm/mdp_ppp_v31.c
@@ -0,0 +1,828 @@
1/* Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/sched.h>
21#include <linux/time.h>
22#include <linux/init.h>
23#include <linux/interrupt.h>
24#include <linux/fb.h>
25#include "linux/proc_fs.h"
26
27#include <mach/hardware.h>
28#include <linux/io.h>
29
30#include <asm/system.h>
31#include <asm/mach-types.h>
32#include <linux/semaphore.h>
33#include <asm/div64.h>
34
35#include "mdp.h"
36#include "msm_fb.h"
37
38#define MDP_SCALE_COEFF_NUM 32
39#define MDP_SCALE_0P2_TO_0P4_INDEX 0
40#define MDP_SCALE_0P4_TO_0P6_INDEX 32
41#define MDP_SCALE_0P6_TO_0P8_INDEX 64
42#define MDP_SCALE_0P8_TO_8P0_INDEX 96
43#define MDP_SCALE_COEFF_MASK 0x3ff
44
45#define MDP_SCALE_PR 0
46#define MDP_SCALE_FIR 1
47
48static uint32 mdp_scale_0p8_to_8p0_mode;
49static uint32 mdp_scale_0p6_to_0p8_mode;
50static uint32 mdp_scale_0p4_to_0p6_mode;
51static uint32 mdp_scale_0p2_to_0p4_mode;
52
53/* -------- All scaling range, "pixel repeat" -------- */
54static int16 mdp_scale_pixel_repeat_C0[MDP_SCALE_COEFF_NUM] = {
55 0, 0, 0, 0, 0, 0, 0, 0,
56 0, 0, 0, 0, 0, 0, 0, 0,
57 0, 0, 0, 0, 0, 0, 0, 0,
58 0, 0, 0, 0, 0, 0, 0, 0
59};
60
61static int16 mdp_scale_pixel_repeat_C1[MDP_SCALE_COEFF_NUM] = {
62 511, 511, 511, 511, 511, 511, 511, 511,
63 511, 511, 511, 511, 511, 511, 511, 511,
64 511, 511, 511, 511, 511, 511, 511, 511,
65 511, 511, 511, 511, 511, 511, 511, 511
66};
67
68static int16 mdp_scale_pixel_repeat_C2[MDP_SCALE_COEFF_NUM] = {
69 0, 0, 0, 0, 0, 0, 0, 0,
70 0, 0, 0, 0, 0, 0, 0, 0,
71 0, 0, 0, 0, 0, 0, 0, 0,
72 0, 0, 0, 0, 0, 0, 0, 0
73};
74
75static int16 mdp_scale_pixel_repeat_C3[MDP_SCALE_COEFF_NUM] = {
76 0, 0, 0, 0, 0, 0, 0, 0,
77 0, 0, 0, 0, 0, 0, 0, 0,
78 0, 0, 0, 0, 0, 0, 0, 0,
79 0, 0, 0, 0, 0, 0, 0, 0
80};
81
82/* --------------------------- FIR ------------------------------------- */
83/* -------- Downscale, ranging from 0.8x to 8.0x of original size -------- */
84
85static int16 mdp_scale_0p8_to_8p0_C0[MDP_SCALE_COEFF_NUM] = {
86 0, -7, -13, -19, -24, -28, -32, -34, -37, -39,
87 -40, -41, -41, -41, -40, -40, -38, -37, -35, -33,
88 -31, -29, -26, -24, -21, -18, -15, -13, -10, -7,
89 -5, -2
90};
91
92static int16 mdp_scale_0p8_to_8p0_C1[MDP_SCALE_COEFF_NUM] = {
93 511, 507, 501, 494, 485, 475, 463, 450, 436, 422,
94 405, 388, 370, 352, 333, 314, 293, 274, 253, 233,
95 213, 193, 172, 152, 133, 113, 95, 77, 60, 43,
96 28, 13
97};
98
99static int16 mdp_scale_0p8_to_8p0_C2[MDP_SCALE_COEFF_NUM] = {
100 0, 13, 28, 43, 60, 77, 95, 113, 133, 152,
101 172, 193, 213, 233, 253, 274, 294, 314, 333, 352,
102 370, 388, 405, 422, 436, 450, 463, 475, 485, 494,
103 501, 507,
104};
105
106static int16 mdp_scale_0p8_to_8p0_C3[MDP_SCALE_COEFF_NUM] = {
107 0, -2, -5, -7, -10, -13, -15, -18, -21, -24,
108 -26, -29, -31, -33, -35, -37, -38, -40, -40, -41,
109 -41, -41, -40, -39, -37, -34, -32, -28, -24, -19,
110 -13, -7
111};
112
113/* -------- Downscale, ranging from 0.6x to 0.8x of original size -------- */
114
115static int16 mdp_scale_0p6_to_0p8_C0[MDP_SCALE_COEFF_NUM] = {
116 104, 96, 89, 82, 75, 68, 61, 55, 49, 43,
117 38, 33, 28, 24, 20, 16, 12, 9, 6, 4,
118 2, 0, -2, -4, -5, -6, -7, -7, -8, -8,
119 -8, -8
120};
121
122static int16 mdp_scale_0p6_to_0p8_C1[MDP_SCALE_COEFF_NUM] = {
123 303, 303, 302, 300, 298, 296, 293, 289, 286, 281,
124 276, 270, 265, 258, 252, 245, 238, 230, 223, 214,
125 206, 197, 189, 180, 172, 163, 154, 145, 137, 128,
126 120, 112
127};
128
129static int16 mdp_scale_0p6_to_0p8_C2[MDP_SCALE_COEFF_NUM] = {
130 112, 120, 128, 137, 145, 154, 163, 172, 180, 189,
131 197, 206, 214, 223, 230, 238, 245, 252, 258, 265,
132 270, 276, 281, 286, 289, 293, 296, 298, 300, 302,
133 303, 303
134};
135
136static int16 mdp_scale_0p6_to_0p8_C3[MDP_SCALE_COEFF_NUM] = {
137 -8, -8, -8, -8, -7, -7, -6, -5, -4, -2,
138 0, 2, 4, 6, 9, 12, 16, 20, 24, 28,
139 33, 38, 43, 49, 55, 61, 68, 75, 82, 89,
140 96, 104
141};
142
143/* -------- Downscale, ranging from 0.4x to 0.6x of original size -------- */
144
145static int16 mdp_scale_0p4_to_0p6_C0[MDP_SCALE_COEFF_NUM] = {
146 136, 132, 128, 123, 119, 115, 111, 107, 103, 98,
147 95, 91, 87, 84, 80, 76, 73, 69, 66, 62,
148 59, 57, 54, 50, 47, 44, 41, 39, 36, 33,
149 32, 29
150};
151
152static int16 mdp_scale_0p4_to_0p6_C1[MDP_SCALE_COEFF_NUM] = {
153 206, 205, 204, 204, 201, 200, 199, 197, 196, 194,
154 191, 191, 189, 185, 184, 182, 180, 178, 176, 173,
155 170, 168, 165, 162, 160, 157, 155, 152, 148, 146,
156 142, 140
157};
158
159static int16 mdp_scale_0p4_to_0p6_C2[MDP_SCALE_COEFF_NUM] = {
160 140, 142, 146, 148, 152, 155, 157, 160, 162, 165,
161 168, 170, 173, 176, 178, 180, 182, 184, 185, 189,
162 191, 191, 194, 196, 197, 199, 200, 201, 204, 204,
163 205, 206
164};
165
166static int16 mdp_scale_0p4_to_0p6_C3[MDP_SCALE_COEFF_NUM] = {
167 29, 32, 33, 36, 39, 41, 44, 47, 50, 54,
168 57, 59, 62, 66, 69, 73, 76, 80, 84, 87,
169 91, 95, 98, 103, 107, 111, 115, 119, 123, 128,
170 132, 136
171};
172
173/* -------- Downscale, ranging from 0.2x to 0.4x of original size -------- */
174
175static int16 mdp_scale_0p2_to_0p4_C0[MDP_SCALE_COEFF_NUM] = {
176 131, 131, 130, 129, 128, 127, 127, 126, 125, 125,
177 124, 123, 123, 121, 120, 119, 119, 118, 117, 117,
178 116, 115, 115, 114, 113, 112, 111, 110, 109, 109,
179 108, 107
180};
181
182static int16 mdp_scale_0p2_to_0p4_C1[MDP_SCALE_COEFF_NUM] = {
183 141, 140, 140, 140, 140, 139, 138, 138, 138, 137,
184 137, 137, 136, 137, 137, 137, 136, 136, 136, 135,
185 135, 135, 134, 134, 134, 134, 134, 133, 133, 132,
186 132, 132
187};
188
189static int16 mdp_scale_0p2_to_0p4_C2[MDP_SCALE_COEFF_NUM] = {
190 132, 132, 132, 133, 133, 134, 134, 134, 134, 134,
191 135, 135, 135, 136, 136, 136, 137, 137, 137, 136,
192 137, 137, 137, 138, 138, 138, 139, 140, 140, 140,
193 140, 141
194};
195
196static int16 mdp_scale_0p2_to_0p4_C3[MDP_SCALE_COEFF_NUM] = {
197 107, 108, 109, 109, 110, 111, 112, 113, 114, 115,
198 115, 116, 117, 117, 118, 119, 119, 120, 121, 123,
199 123, 124, 125, 125, 126, 127, 127, 128, 129, 130,
200 131, 131
201};
202
203static void mdp_update_scale_table(int index, int16 *c0, int16 *c1,
204 int16 *c2, int16 *c3)
205{
206 int i, val;
207
208 for (i = 0; i < MDP_SCALE_COEFF_NUM; i++) {
209 val =
210 ((MDP_SCALE_COEFF_MASK & c1[i]) << 16) |
211 (MDP_SCALE_COEFF_MASK & c0[i]);
212 MDP_OUTP(MDP_PPP_SCALE_COEFF_LSBn(index), val);
213 val =
214 ((MDP_SCALE_COEFF_MASK & c3[i]) << 16) |
215 (MDP_SCALE_COEFF_MASK & c2[i]);
216 MDP_OUTP(MDP_PPP_SCALE_COEFF_MSBn(index), val);
217 index++;
218 }
219}
220
221void mdp_init_scale_table(void)
222{
223 mdp_scale_0p2_to_0p4_mode = MDP_SCALE_FIR;
224 mdp_update_scale_table(MDP_SCALE_0P2_TO_0P4_INDEX,
225 mdp_scale_0p2_to_0p4_C0,
226 mdp_scale_0p2_to_0p4_C1,
227 mdp_scale_0p2_to_0p4_C2,
228 mdp_scale_0p2_to_0p4_C3);
229
230 mdp_scale_0p4_to_0p6_mode = MDP_SCALE_FIR;
231 mdp_update_scale_table(MDP_SCALE_0P4_TO_0P6_INDEX,
232 mdp_scale_0p4_to_0p6_C0,
233 mdp_scale_0p4_to_0p6_C1,
234 mdp_scale_0p4_to_0p6_C2,
235 mdp_scale_0p4_to_0p6_C3);
236
237 mdp_scale_0p6_to_0p8_mode = MDP_SCALE_FIR;
238 mdp_update_scale_table(MDP_SCALE_0P6_TO_0P8_INDEX,
239 mdp_scale_0p6_to_0p8_C0,
240 mdp_scale_0p6_to_0p8_C1,
241 mdp_scale_0p6_to_0p8_C2,
242 mdp_scale_0p6_to_0p8_C3);
243
244 mdp_scale_0p8_to_8p0_mode = MDP_SCALE_FIR;
245 mdp_update_scale_table(MDP_SCALE_0P8_TO_8P0_INDEX,
246 mdp_scale_0p8_to_8p0_C0,
247 mdp_scale_0p8_to_8p0_C1,
248 mdp_scale_0p8_to_8p0_C2,
249 mdp_scale_0p8_to_8p0_C3);
250}
251
252static long long mdp_do_div(long long num, long long den)
253{
254 do_div(num, den);
255 return num;
256}
257
258#define SCALER_PHASE_BITS 29
259#define HAL_MDP_PHASE_STEP_2P50 0x50000000
260#define HAL_MDP_PHASE_STEP_1P66 0x35555555
261#define HAL_MDP_PHASE_STEP_1P25 0x28000000
262
263struct phase_val {
264 int phase_init_x;
265 int phase_init_y;
266 int phase_step_x;
267 int phase_step_y;
268};
269
270static void mdp_calc_scaleInitPhase_3p1(uint32 in_w,
271 uint32 in_h,
272 uint32 out_w,
273 uint32 out_h,
274 boolean is_rotate,
275 boolean is_pp_x,
276 boolean is_pp_y, struct phase_val *pval)
277{
278 uint64 dst_ROI_width;
279 uint64 dst_ROI_height;
280 uint64 src_ROI_width;
281 uint64 src_ROI_height;
282
283 /*
284 * phase_step_x, phase_step_y, phase_init_x and phase_init_y
285 * are represented in fixed-point, unsigned 3.29 format
286 */
287 uint32 phase_step_x = 0;
288 uint32 phase_step_y = 0;
289 uint32 phase_init_x = 0;
290 uint32 phase_init_y = 0;
291 uint32 yscale_filter_sel, xscale_filter_sel;
292 uint32 scale_unit_sel_x, scale_unit_sel_y;
293
294 uint64 numerator, denominator;
295 uint64 temp_dim;
296
297 src_ROI_width = in_w;
298 src_ROI_height = in_h;
299 dst_ROI_width = out_w;
300 dst_ROI_height = out_h;
301
302 /* if there is a 90 degree rotation */
303 if (is_rotate) {
304 /* decide whether to use FIR or M/N for scaling */
305
306 /* if down-scaling by a factor smaller than 1/4 */
307 if (src_ROI_width > (4 * dst_ROI_height))
308 scale_unit_sel_x = 1; /* use M/N scalar */
309 else
310 scale_unit_sel_x = 0; /* use FIR scalar */
311
312 /* if down-scaling by a factor smaller than 1/4 */
313 if (src_ROI_height > (4 * dst_ROI_width))
314 scale_unit_sel_y = 1; /* use M/N scalar */
315 else
316 scale_unit_sel_y = 0; /* use FIR scalar */
317 } else {
318 /* decide whether to use FIR or M/N for scaling */
319
320 if (src_ROI_width > (4 * dst_ROI_width))
321 scale_unit_sel_x = 1; /* use M/N scalar */
322 else
323 scale_unit_sel_x = 0; /* use FIR scalar */
324
325 if (src_ROI_height > (4 * dst_ROI_height))
326 scale_unit_sel_y = 1; /* use M/N scalar */
327 else
328 scale_unit_sel_y = 0; /* use FIR scalar */
329
330 }
331
332 /* if there is a 90 degree rotation */
333 if (is_rotate) {
334 /* swap the width and height of dst ROI */
335 temp_dim = dst_ROI_width;
336 dst_ROI_width = dst_ROI_height;
337 dst_ROI_height = temp_dim;
338 }
339
340 /* calculate phase step for the x direction */
341
342 /* if destination is only 1 pixel wide, the value of phase_step_x
343 is unimportant. Assigning phase_step_x to src ROI width
344 as an arbitrary value. */
345 if (dst_ROI_width == 1)
346 phase_step_x = (uint32) ((src_ROI_width) << SCALER_PHASE_BITS);
347
348 /* if using FIR scalar */
349 else if (scale_unit_sel_x == 0) {
350
351 /* Calculate the quotient ( src_ROI_width - 1 ) / ( dst_ROI_width - 1)
352 with u3.29 precision. Quotient is rounded up to the larger
353 29th decimal point. */
354 numerator = (src_ROI_width - 1) << SCALER_PHASE_BITS;
355 denominator = (dst_ROI_width - 1); /* never equals to 0 because of the "( dst_ROI_width == 1 ) case" */
356 phase_step_x = (uint32) mdp_do_div((numerator + denominator - 1), denominator); /* divide and round up to the larger 29th decimal point. */
357
358 }
359
360 /* if M/N scalar */
361 else if (scale_unit_sel_x == 1) {
362 /* Calculate the quotient ( src_ROI_width ) / ( dst_ROI_width)
363 with u3.29 precision. Quotient is rounded down to the
364 smaller 29th decimal point. */
365 numerator = (src_ROI_width) << SCALER_PHASE_BITS;
366 denominator = (dst_ROI_width);
367 phase_step_x = (uint32) mdp_do_div(numerator, denominator);
368 }
369 /* calculate phase step for the y direction */
370
371 /* if destination is only 1 pixel wide, the value of
372 phase_step_x is unimportant. Assigning phase_step_x
373 to src ROI width as an arbitrary value. */
374 if (dst_ROI_height == 1)
375 phase_step_y = (uint32) ((src_ROI_height) << SCALER_PHASE_BITS);
376
377 /* if FIR scalar */
378 else if (scale_unit_sel_y == 0) {
379 /* Calculate the quotient ( src_ROI_height - 1 ) / ( dst_ROI_height - 1)
380 with u3.29 precision. Quotient is rounded up to the larger
381 29th decimal point. */
382 numerator = (src_ROI_height - 1) << SCALER_PHASE_BITS;
383 denominator = (dst_ROI_height - 1); /* never equals to 0 because of the "( dst_ROI_height == 1 )" case */
384 phase_step_y = (uint32) mdp_do_div((numerator + denominator - 1), denominator); /* Quotient is rounded up to the larger 29th decimal point. */
385
386 }
387
388 /* if M/N scalar */
389 else if (scale_unit_sel_y == 1) {
390 /* Calculate the quotient ( src_ROI_height ) / ( dst_ROI_height)
391 with u3.29 precision. Quotient is rounded down to the smaller
392 29th decimal point. */
393 numerator = (src_ROI_height) << SCALER_PHASE_BITS;
394 denominator = (dst_ROI_height);
395 phase_step_y = (uint32) mdp_do_div(numerator, denominator);
396 }
397
398 /* decide which set of FIR coefficients to use */
399 if (phase_step_x > HAL_MDP_PHASE_STEP_2P50)
400 xscale_filter_sel = 0;
401 else if (phase_step_x > HAL_MDP_PHASE_STEP_1P66)
402 xscale_filter_sel = 1;
403 else if (phase_step_x > HAL_MDP_PHASE_STEP_1P25)
404 xscale_filter_sel = 2;
405 else
406 xscale_filter_sel = 3;
407
408 if (phase_step_y > HAL_MDP_PHASE_STEP_2P50)
409 yscale_filter_sel = 0;
410 else if (phase_step_y > HAL_MDP_PHASE_STEP_1P66)
411 yscale_filter_sel = 1;
412 else if (phase_step_y > HAL_MDP_PHASE_STEP_1P25)
413 yscale_filter_sel = 2;
414 else
415 yscale_filter_sel = 3;
416
417 /* calculate phase init for the x direction */
418
419 /* if using FIR scalar */
420 if (scale_unit_sel_x == 0) {
421 if (dst_ROI_width == 1)
422 phase_init_x =
423 (uint32) ((src_ROI_width - 1) << SCALER_PHASE_BITS);
424 else
425 phase_init_x = 0;
426
427 }
428 /* M over N scalar */
429 else if (scale_unit_sel_x == 1)
430 phase_init_x = 0;
431
432 /* calculate phase init for the y direction
433 if using FIR scalar */
434 if (scale_unit_sel_y == 0) {
435 if (dst_ROI_height == 1)
436 phase_init_y =
437 (uint32) ((src_ROI_height -
438 1) << SCALER_PHASE_BITS);
439 else
440 phase_init_y = 0;
441
442 }
443 /* M over N scalar */
444 else if (scale_unit_sel_y == 1)
445 phase_init_y = 0;
446
447 /* write registers */
448 pval->phase_step_x = (uint32) phase_step_x;
449 pval->phase_step_y = (uint32) phase_step_y;
450 pval->phase_init_x = (uint32) phase_init_x;
451 pval->phase_init_y = (uint32) phase_init_y;
452
453 return;
454}
455
456void mdp_set_scale(MDPIBUF *iBuf,
457 uint32 dst_roi_width,
458 uint32 dst_roi_height,
459 boolean inputRGB, boolean outputRGB, uint32 *pppop_reg_ptr)
460{
461 uint32 dst_roi_width_scale;
462 uint32 dst_roi_height_scale;
463 struct phase_val pval;
464 boolean use_pr;
465 uint32 ppp_scale_config = 0;
466
467 if (!inputRGB)
468 ppp_scale_config |= BIT(6);
469
470 if (iBuf->mdpImg.mdpOp & MDPOP_ASCALE) {
471 if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) {
472 dst_roi_width_scale = dst_roi_height;
473 dst_roi_height_scale = dst_roi_width;
474 } else {
475 dst_roi_width_scale = dst_roi_width;
476 dst_roi_height_scale = dst_roi_height;
477 }
478
479 if ((dst_roi_width_scale != iBuf->roi.width) ||
480 (dst_roi_height_scale != iBuf->roi.height) ||
481 (iBuf->mdpImg.mdpOp & MDPOP_SHARPENING)) {
482 *pppop_reg_ptr |=
483 (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON);
484
485 mdp_calc_scaleInitPhase_3p1(iBuf->roi.width,
486 iBuf->roi.height,
487 dst_roi_width,
488 dst_roi_height,
489 iBuf->mdpImg.
490 mdpOp & MDPOP_ROT90, 1, 1,
491 &pval);
492
493 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x013c,
494 pval.phase_init_x);
495 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0140,
496 pval.phase_init_y);
497 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0144,
498 pval.phase_step_x);
499 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0148,
500 pval.phase_step_y);
501
502 use_pr = (inputRGB) && (outputRGB);
503
504 /* x-direction */
505 if ((dst_roi_width_scale == iBuf->roi.width) &&
506 !(iBuf->mdpImg.mdpOp & MDPOP_SHARPENING)) {
507 *pppop_reg_ptr &= ~PPP_OP_SCALE_X_ON;
508 } else
509 if (((dst_roi_width_scale * 10) / iBuf->roi.width) >
510 8) {
511 if ((use_pr)
512 && (mdp_scale_0p8_to_8p0_mode !=
513 MDP_SCALE_PR)) {
514 mdp_scale_0p8_to_8p0_mode =
515 MDP_SCALE_PR;
516 mdp_update_scale_table
517 (MDP_SCALE_0P8_TO_8P0_INDEX,
518 mdp_scale_pixel_repeat_C0,
519 mdp_scale_pixel_repeat_C1,
520 mdp_scale_pixel_repeat_C2,
521 mdp_scale_pixel_repeat_C3);
522 } else if ((!use_pr)
523 && (mdp_scale_0p8_to_8p0_mode !=
524 MDP_SCALE_FIR)) {
525 mdp_scale_0p8_to_8p0_mode =
526 MDP_SCALE_FIR;
527 mdp_update_scale_table
528 (MDP_SCALE_0P8_TO_8P0_INDEX,
529 mdp_scale_0p8_to_8p0_C0,
530 mdp_scale_0p8_to_8p0_C1,
531 mdp_scale_0p8_to_8p0_C2,
532 mdp_scale_0p8_to_8p0_C3);
533 }
534 ppp_scale_config |= (SCALE_U1_SET << 2);
535 } else
536 if (((dst_roi_width_scale * 10) / iBuf->roi.width) >
537 6) {
538 if ((use_pr)
539 && (mdp_scale_0p6_to_0p8_mode !=
540 MDP_SCALE_PR)) {
541 mdp_scale_0p6_to_0p8_mode =
542 MDP_SCALE_PR;
543 mdp_update_scale_table
544 (MDP_SCALE_0P6_TO_0P8_INDEX,
545 mdp_scale_pixel_repeat_C0,
546 mdp_scale_pixel_repeat_C1,
547 mdp_scale_pixel_repeat_C2,
548 mdp_scale_pixel_repeat_C3);
549 } else if ((!use_pr)
550 && (mdp_scale_0p6_to_0p8_mode !=
551 MDP_SCALE_FIR)) {
552 mdp_scale_0p6_to_0p8_mode =
553 MDP_SCALE_FIR;
554 mdp_update_scale_table
555 (MDP_SCALE_0P6_TO_0P8_INDEX,
556 mdp_scale_0p6_to_0p8_C0,
557 mdp_scale_0p6_to_0p8_C1,
558 mdp_scale_0p6_to_0p8_C2,
559 mdp_scale_0p6_to_0p8_C3);
560 }
561 ppp_scale_config |= (SCALE_D2_SET << 2);
562 } else
563 if (((dst_roi_width_scale * 10) / iBuf->roi.width) >
564 4) {
565 if ((use_pr)
566 && (mdp_scale_0p4_to_0p6_mode !=
567 MDP_SCALE_PR)) {
568 mdp_scale_0p4_to_0p6_mode =
569 MDP_SCALE_PR;
570 mdp_update_scale_table
571 (MDP_SCALE_0P4_TO_0P6_INDEX,
572 mdp_scale_pixel_repeat_C0,
573 mdp_scale_pixel_repeat_C1,
574 mdp_scale_pixel_repeat_C2,
575 mdp_scale_pixel_repeat_C3);
576 } else if ((!use_pr)
577 && (mdp_scale_0p4_to_0p6_mode !=
578 MDP_SCALE_FIR)) {
579 mdp_scale_0p4_to_0p6_mode =
580 MDP_SCALE_FIR;
581 mdp_update_scale_table
582 (MDP_SCALE_0P4_TO_0P6_INDEX,
583 mdp_scale_0p4_to_0p6_C0,
584 mdp_scale_0p4_to_0p6_C1,
585 mdp_scale_0p4_to_0p6_C2,
586 mdp_scale_0p4_to_0p6_C3);
587 }
588 ppp_scale_config |= (SCALE_D1_SET << 2);
589 } else
590 if (((dst_roi_width_scale * 4) / iBuf->roi.width) >=
591 1) {
592 if ((use_pr)
593 && (mdp_scale_0p2_to_0p4_mode !=
594 MDP_SCALE_PR)) {
595 mdp_scale_0p2_to_0p4_mode =
596 MDP_SCALE_PR;
597 mdp_update_scale_table
598 (MDP_SCALE_0P2_TO_0P4_INDEX,
599 mdp_scale_pixel_repeat_C0,
600 mdp_scale_pixel_repeat_C1,
601 mdp_scale_pixel_repeat_C2,
602 mdp_scale_pixel_repeat_C3);
603 } else if ((!use_pr)
604 && (mdp_scale_0p2_to_0p4_mode !=
605 MDP_SCALE_FIR)) {
606 mdp_scale_0p2_to_0p4_mode =
607 MDP_SCALE_FIR;
608 mdp_update_scale_table
609 (MDP_SCALE_0P2_TO_0P4_INDEX,
610 mdp_scale_0p2_to_0p4_C0,
611 mdp_scale_0p2_to_0p4_C1,
612 mdp_scale_0p2_to_0p4_C2,
613 mdp_scale_0p2_to_0p4_C3);
614 }
615 ppp_scale_config |= (SCALE_D0_SET << 2);
616 } else
617 ppp_scale_config |= BIT(0);
618
619 /* y-direction */
620 if ((dst_roi_height_scale == iBuf->roi.height) &&
621 !(iBuf->mdpImg.mdpOp & MDPOP_SHARPENING)) {
622 *pppop_reg_ptr &= ~PPP_OP_SCALE_Y_ON;
623 } else if (((dst_roi_height_scale * 10) /
624 iBuf->roi.height) > 8) {
625 if ((use_pr)
626 && (mdp_scale_0p8_to_8p0_mode !=
627 MDP_SCALE_PR)) {
628 mdp_scale_0p8_to_8p0_mode =
629 MDP_SCALE_PR;
630 mdp_update_scale_table
631 (MDP_SCALE_0P8_TO_8P0_INDEX,
632 mdp_scale_pixel_repeat_C0,
633 mdp_scale_pixel_repeat_C1,
634 mdp_scale_pixel_repeat_C2,
635 mdp_scale_pixel_repeat_C3);
636 } else if ((!use_pr)
637 && (mdp_scale_0p8_to_8p0_mode !=
638 MDP_SCALE_FIR)) {
639 mdp_scale_0p8_to_8p0_mode =
640 MDP_SCALE_FIR;
641 mdp_update_scale_table
642 (MDP_SCALE_0P8_TO_8P0_INDEX,
643 mdp_scale_0p8_to_8p0_C0,
644 mdp_scale_0p8_to_8p0_C1,
645 mdp_scale_0p8_to_8p0_C2,
646 mdp_scale_0p8_to_8p0_C3);
647 }
648 ppp_scale_config |= (SCALE_U1_SET << 4);
649 } else
650 if (((dst_roi_height_scale * 10) /
651 iBuf->roi.height) > 6) {
652 if ((use_pr)
653 && (mdp_scale_0p6_to_0p8_mode !=
654 MDP_SCALE_PR)) {
655 mdp_scale_0p6_to_0p8_mode =
656 MDP_SCALE_PR;
657 mdp_update_scale_table
658 (MDP_SCALE_0P6_TO_0P8_INDEX,
659 mdp_scale_pixel_repeat_C0,
660 mdp_scale_pixel_repeat_C1,
661 mdp_scale_pixel_repeat_C2,
662 mdp_scale_pixel_repeat_C3);
663 } else if ((!use_pr)
664 && (mdp_scale_0p6_to_0p8_mode !=
665 MDP_SCALE_FIR)) {
666 mdp_scale_0p6_to_0p8_mode =
667 MDP_SCALE_FIR;
668 mdp_update_scale_table
669 (MDP_SCALE_0P6_TO_0P8_INDEX,
670 mdp_scale_0p6_to_0p8_C0,
671 mdp_scale_0p6_to_0p8_C1,
672 mdp_scale_0p6_to_0p8_C2,
673 mdp_scale_0p6_to_0p8_C3);
674 }
675 ppp_scale_config |= (SCALE_D2_SET << 4);
676 } else
677 if (((dst_roi_height_scale * 10) /
678 iBuf->roi.height) > 4) {
679 if ((use_pr)
680 && (mdp_scale_0p4_to_0p6_mode !=
681 MDP_SCALE_PR)) {
682 mdp_scale_0p4_to_0p6_mode =
683 MDP_SCALE_PR;
684 mdp_update_scale_table
685 (MDP_SCALE_0P4_TO_0P6_INDEX,
686 mdp_scale_pixel_repeat_C0,
687 mdp_scale_pixel_repeat_C1,
688 mdp_scale_pixel_repeat_C2,
689 mdp_scale_pixel_repeat_C3);
690 } else if ((!use_pr)
691 && (mdp_scale_0p4_to_0p6_mode !=
692 MDP_SCALE_FIR)) {
693 mdp_scale_0p4_to_0p6_mode =
694 MDP_SCALE_FIR;
695 mdp_update_scale_table
696 (MDP_SCALE_0P4_TO_0P6_INDEX,
697 mdp_scale_0p4_to_0p6_C0,
698 mdp_scale_0p4_to_0p6_C1,
699 mdp_scale_0p4_to_0p6_C2,
700 mdp_scale_0p4_to_0p6_C3);
701 }
702 ppp_scale_config |= (SCALE_D1_SET << 4);
703 } else
704 if (((dst_roi_height_scale * 4) /
705 iBuf->roi.height) >= 1) {
706 if ((use_pr)
707 && (mdp_scale_0p2_to_0p4_mode !=
708 MDP_SCALE_PR)) {
709 mdp_scale_0p2_to_0p4_mode =
710 MDP_SCALE_PR;
711 mdp_update_scale_table
712 (MDP_SCALE_0P2_TO_0P4_INDEX,
713 mdp_scale_pixel_repeat_C0,
714 mdp_scale_pixel_repeat_C1,
715 mdp_scale_pixel_repeat_C2,
716 mdp_scale_pixel_repeat_C3);
717 } else if ((!use_pr)
718 && (mdp_scale_0p2_to_0p4_mode !=
719 MDP_SCALE_FIR)) {
720 mdp_scale_0p2_to_0p4_mode =
721 MDP_SCALE_FIR;
722 mdp_update_scale_table
723 (MDP_SCALE_0P2_TO_0P4_INDEX,
724 mdp_scale_0p2_to_0p4_C0,
725 mdp_scale_0p2_to_0p4_C1,
726 mdp_scale_0p2_to_0p4_C2,
727 mdp_scale_0p2_to_0p4_C3);
728 }
729 ppp_scale_config |= (SCALE_D0_SET << 4);
730 } else
731 ppp_scale_config |= BIT(1);
732
733 if (iBuf->mdpImg.mdpOp & MDPOP_SHARPENING) {
734 ppp_scale_config |= BIT(7);
735 MDP_OUTP(MDP_BASE + 0x50020,
736 iBuf->mdpImg.sp_value);
737 }
738
739 MDP_OUTP(MDP_BASE + 0x10230, ppp_scale_config);
740 } else {
741 iBuf->mdpImg.mdpOp &= ~(MDPOP_ASCALE);
742 }
743 }
744}
745
746void mdp_adjust_start_addr(uint8 **src0,
747 uint8 **src1,
748 int v_slice,
749 int h_slice,
750 int x,
751 int y,
752 uint32 width,
753 uint32 height, int bpp, MDPIBUF *iBuf, int layer)
754{
755 switch (layer) {
756 case 0:
757 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0200, (y << 16) | (x));
758 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0208,
759 (height << 16) | (width));
760 break;
761
762 case 1:
763 /* MDP 3.1 HW bug workaround */
764 if (iBuf->ibuf_type == MDP_YCRYCB_H2V1) {
765 *src0 += (x + y * width) * bpp;
766 x = y = 0;
767 width = iBuf->roi.dst_width;
768 height = iBuf->roi.dst_height;
769 }
770
771 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0204, (y << 16) | (x));
772 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x020c,
773 (height << 16) | (width));
774 break;
775
776 case 2:
777 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x019c, (y << 16) | (x));
778 break;
779 }
780}
781
782void mdp_set_blend_attr(MDPIBUF *iBuf,
783 uint32 *alpha,
784 uint32 *tpVal,
785 uint32 perPixelAlpha, uint32 *pppop_reg_ptr)
786{
787 int bg_alpha;
788
789 *alpha = iBuf->mdpImg.alpha;
790 *tpVal = iBuf->mdpImg.tpVal;
791
792 if (iBuf->mdpImg.mdpOp & MDPOP_FG_PM_ALPHA) {
793 *pppop_reg_ptr |= PPP_OP_ROT_ON |
794 PPP_OP_BLEND_ON | PPP_OP_BLEND_CONSTANT_ALPHA;
795
796 bg_alpha = PPP_BLEND_BG_USE_ALPHA_SEL |
797 PPP_BLEND_BG_ALPHA_REVERSE;
798
799 if (perPixelAlpha)
800 bg_alpha |= PPP_BLEND_BG_SRCPIXEL_ALPHA;
801 else
802 bg_alpha |= PPP_BLEND_BG_CONSTANT_ALPHA;
803
804 outpdw(MDP_BASE + 0x70010, bg_alpha);
805
806 if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)
807 *pppop_reg_ptr |= PPP_BLEND_CALPHA_TRNASP;
808 } else if (perPixelAlpha) {
809 *pppop_reg_ptr |= PPP_OP_ROT_ON |
810 PPP_OP_BLEND_ON | PPP_OP_BLEND_SRCPIXEL_ALPHA;
811 } else {
812 if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
813 && (iBuf->mdpImg.alpha == 0xff)) {
814 iBuf->mdpImg.mdpOp &= ~(MDPOP_ALPHAB);
815 }
816
817 if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
818 || (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)) {
819 *pppop_reg_ptr |=
820 PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
821 PPP_OP_BLEND_CONSTANT_ALPHA |
822 PPP_OP_BLEND_ALPHA_BLEND_NORMAL;
823 }
824
825 if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)
826 *pppop_reg_ptr |= PPP_BLEND_CALPHA_TRNASP;
827 }
828}
diff --git a/drivers/staging/msm/mdp_vsync.c b/drivers/staging/msm/mdp_vsync.c
new file mode 100644
index 000000000000..bbd456044356
--- /dev/null
+++ b/drivers/staging/msm/mdp_vsync.c
@@ -0,0 +1,389 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/sched.h>
21#include <linux/time.h>
22#include <linux/init.h>
23#include <linux/interrupt.h>
24#include <linux/spinlock.h>
25#include <linux/hrtimer.h>
26#include <linux/vmalloc.h>
27#include <linux/clk.h>
28
29#include <mach/hardware.h>
30#include <linux/io.h>
31
32#include <asm/system.h>
33#include <asm/mach-types.h>
34#include <linux/semaphore.h>
35#include <linux/uaccess.h>
36#include <mach/gpio.h>
37
38#include "mdp.h"
39#include "msm_fb.h"
40#include "mddihost.h"
41
42#ifdef CONFIG_FB_MSM_MDP40
43#define MDP_SYNC_CFG_0 0x100
44#define MDP_SYNC_STATUS_0 0x10c
45#define MDP_PRIM_VSYNC_OUT_CTRL 0x118
46#define MDP_PRIM_VSYNC_INIT_VAL 0x128
47#else
48#define MDP_SYNC_CFG_0 0x300
49#define MDP_SYNC_STATUS_0 0x30c
50#define MDP_PRIM_VSYNC_OUT_CTRL 0x318
51#define MDP_PRIM_VSYNC_INIT_VAL 0x328
52#endif
53
54extern mddi_lcd_type mddi_lcd_idx;
55extern spinlock_t mdp_spin_lock;
56extern struct workqueue_struct *mdp_vsync_wq;
57extern int lcdc_mode;
58extern int vsync_mode;
59
60#ifdef MDP_HW_VSYNC
61int vsync_above_th = 4;
62int vsync_start_th = 1;
63int vsync_load_cnt;
64
65struct clk *mdp_vsync_clk;
66
67void mdp_hw_vsync_clk_enable(struct msm_fb_data_type *mfd)
68{
69 if (mfd->use_mdp_vsync)
70 clk_enable(mdp_vsync_clk);
71}
72
73void mdp_hw_vsync_clk_disable(struct msm_fb_data_type *mfd)
74{
75 if (mfd->use_mdp_vsync)
76 clk_disable(mdp_vsync_clk);
77}
78#endif
79
80static void mdp_set_vsync(unsigned long data)
81{
82 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)data;
83 struct msm_fb_panel_data *pdata = NULL;
84
85 pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
86
87 if ((pdata) && (pdata->set_vsync_notifier == NULL))
88 return;
89
90 init_timer(&mfd->vsync_resync_timer);
91 mfd->vsync_resync_timer.function = mdp_set_vsync;
92 mfd->vsync_resync_timer.data = data;
93 mfd->vsync_resync_timer.expires =
94 jiffies + mfd->panel_info.lcd.vsync_notifier_period;
95 add_timer(&mfd->vsync_resync_timer);
96
97 if ((mfd->panel_info.lcd.vsync_enable) && (mfd->panel_power_on)
98 && (!mfd->vsync_handler_pending)) {
99 mfd->vsync_handler_pending = TRUE;
100 if (!queue_work(mdp_vsync_wq, &mfd->vsync_resync_worker)) {
101 MSM_FB_INFO
102 ("mdp_set_vsync: can't queue_work! -> needs to increase vsync_resync_timer_duration\n");
103 }
104 } else {
105 MSM_FB_DEBUG
106 ("mdp_set_vsync failed! EN:%d PWR:%d PENDING:%d\n",
107 mfd->panel_info.lcd.vsync_enable, mfd->panel_power_on,
108 mfd->vsync_handler_pending);
109 }
110}
111
112static void mdp_vsync_handler(void *data)
113{
114 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)data;
115
116 if (mfd->use_mdp_vsync) {
117#ifdef MDP_HW_VSYNC
118 if (mfd->panel_power_on)
119 MDP_OUTP(MDP_BASE + MDP_SYNC_STATUS_0, vsync_load_cnt);
120
121 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
122#endif
123 } else {
124 mfd->last_vsync_timetick = ktime_get_real();
125 }
126
127 mfd->vsync_handler_pending = FALSE;
128}
129
130irqreturn_t mdp_hw_vsync_handler_proxy(int irq, void *data)
131{
132 /*
133 * ToDo: tried enabling/disabling GPIO MDP HW VSYNC interrupt
134 * but getting inaccurate timing in mdp_vsync_handler()
135 * disable_irq(MDP_HW_VSYNC_IRQ);
136 */
137 mdp_vsync_handler(data);
138
139 return IRQ_HANDLED;
140}
141
142#ifdef MDP_HW_VSYNC
143static void mdp_set_sync_cfg_0(struct msm_fb_data_type *mfd, int vsync_cnt)
144{
145 unsigned long cfg;
146
147 cfg = mfd->total_lcd_lines - 1;
148 cfg <<= MDP_SYNCFG_HGT_LOC;
149 if (mfd->panel_info.lcd.hw_vsync_mode)
150 cfg |= MDP_SYNCFG_VSYNC_EXT_EN;
151 cfg |= (MDP_SYNCFG_VSYNC_INT_EN | vsync_cnt);
152
153 MDP_OUTP(MDP_BASE + MDP_SYNC_CFG_0, cfg);
154}
155#endif
156
157void mdp_config_vsync(struct msm_fb_data_type *mfd)
158{
159
160 /* vsync on primary lcd only for now */
161 if ((mfd->dest != DISPLAY_LCD) || (mfd->panel_info.pdest != DISPLAY_1)
162 || (!vsync_mode)) {
163 goto err_handle;
164 }
165
166 if (mfd->panel_info.lcd.vsync_enable) {
167 mfd->total_porch_lines = mfd->panel_info.lcd.v_back_porch +
168 mfd->panel_info.lcd.v_front_porch +
169 mfd->panel_info.lcd.v_pulse_width;
170 mfd->total_lcd_lines =
171 mfd->panel_info.yres + mfd->total_porch_lines;
172 mfd->lcd_ref_usec_time =
173 100000000 / mfd->panel_info.lcd.refx100;
174 mfd->vsync_handler_pending = FALSE;
175 mfd->last_vsync_timetick.tv.sec = 0;
176 mfd->last_vsync_timetick.tv.nsec = 0;
177
178#ifdef MDP_HW_VSYNC
179 if (mdp_vsync_clk == NULL)
180 mdp_vsync_clk = clk_get(NULL, "mdp_vsync_clk");
181
182 if (IS_ERR(mdp_vsync_clk)) {
183 printk(KERN_ERR "error: can't get mdp_vsync_clk!\n");
184 mfd->use_mdp_vsync = 0;
185 } else
186 mfd->use_mdp_vsync = 1;
187
188 if (mfd->use_mdp_vsync) {
189 uint32 vsync_cnt_cfg, vsync_cnt_cfg_dem;
190 uint32 mdp_vsync_clk_speed_hz;
191
192 mdp_vsync_clk_speed_hz = clk_get_rate(mdp_vsync_clk);
193
194 if (mdp_vsync_clk_speed_hz == 0) {
195 mfd->use_mdp_vsync = 0;
196 } else {
197 /*
198 * Do this calculation in 2 steps for
199 * rounding uint32 properly.
200 */
201 vsync_cnt_cfg_dem =
202 (mfd->panel_info.lcd.refx100 *
203 mfd->total_lcd_lines) / 100;
204 vsync_cnt_cfg =
205 (mdp_vsync_clk_speed_hz) /
206 vsync_cnt_cfg_dem;
207
208 /* MDP cmd block enable */
209 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON,
210 FALSE);
211 mdp_hw_vsync_clk_enable(mfd);
212
213 mdp_set_sync_cfg_0(mfd, vsync_cnt_cfg);
214
215 /*
216 * load the last line + 1 to be in the
217 * safety zone
218 */
219 vsync_load_cnt = mfd->panel_info.yres;
220
221 /* line counter init value at the next pulse */
222 MDP_OUTP(MDP_BASE + MDP_PRIM_VSYNC_INIT_VAL,
223 vsync_load_cnt);
224
225 /*
226 * external vsync source pulse width and
227 * polarity flip
228 */
229 MDP_OUTP(MDP_BASE + MDP_PRIM_VSYNC_OUT_CTRL,
230 BIT(30) | BIT(0));
231
232
233 /* threshold */
234 MDP_OUTP(MDP_BASE + 0x200,
235 (vsync_above_th << 16) |
236 (vsync_start_th));
237
238 mdp_hw_vsync_clk_disable(mfd);
239 /* MDP cmd block disable */
240 mdp_pipe_ctrl(MDP_CMD_BLOCK,
241 MDP_BLOCK_POWER_OFF, FALSE);
242 }
243 }
244#else
245 mfd->use_mdp_vsync = 0;
246 hrtimer_init(&mfd->dma_hrtimer, CLOCK_MONOTONIC,
247 HRTIMER_MODE_REL);
248 mfd->dma_hrtimer.function = mdp_dma2_vsync_hrtimer_handler;
249 mfd->vsync_width_boundary = vmalloc(mfd->panel_info.xres * 4);
250#endif
251
252 mfd->channel_irq = 0;
253 if (mfd->panel_info.lcd.hw_vsync_mode) {
254 u32 vsync_gpio = mfd->vsync_gpio;
255 u32 ret;
256
257 if (vsync_gpio == -1) {
258 MSM_FB_INFO("vsync_gpio not defined!\n");
259 goto err_handle;
260 }
261
262 ret = gpio_tlmm_config(GPIO_CFG
263 (vsync_gpio,
264 (mfd->use_mdp_vsync) ? 1 : 0,
265 GPIO_INPUT,
266 GPIO_PULL_DOWN,
267 GPIO_2MA),
268 GPIO_ENABLE);
269 if (ret)
270 goto err_handle;
271
272 if (!mfd->use_mdp_vsync) {
273 mfd->channel_irq = MSM_GPIO_TO_INT(vsync_gpio);
274 if (request_irq
275 (mfd->channel_irq,
276 &mdp_hw_vsync_handler_proxy,
277 IRQF_TRIGGER_FALLING, "VSYNC_GPIO",
278 (void *)mfd)) {
279 MSM_FB_INFO
280 ("irq=%d failed! vsync_gpio=%d\n",
281 mfd->channel_irq,
282 vsync_gpio);
283 goto err_handle;
284 }
285 }
286 }
287
288 mdp_set_vsync((unsigned long)mfd);
289 }
290
291 return;
292
293err_handle:
294 if (mfd->vsync_width_boundary)
295 vfree(mfd->vsync_width_boundary);
296 mfd->panel_info.lcd.vsync_enable = FALSE;
297 printk(KERN_ERR "%s: failed!\n", __func__);
298}
299
300void mdp_vsync_resync_workqueue_handler(struct work_struct *work)
301{
302 struct msm_fb_data_type *mfd = NULL;
303 int vsync_fnc_enabled = FALSE;
304 struct msm_fb_panel_data *pdata = NULL;
305
306 mfd = container_of(work, struct msm_fb_data_type, vsync_resync_worker);
307
308 if (mfd) {
309 if (mfd->panel_power_on) {
310 pdata =
311 (struct msm_fb_panel_data *)mfd->pdev->dev.
312 platform_data;
313
314 /*
315 * we need to turn on MDP power if it uses MDP vsync
316 * HW block in SW mode
317 */
318 if ((!mfd->panel_info.lcd.hw_vsync_mode) &&
319 (mfd->use_mdp_vsync) &&
320 (pdata) && (pdata->set_vsync_notifier != NULL)) {
321 /*
322 * enable pwr here since we can't enable it in
323 * vsync callback in isr mode
324 */
325 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON,
326 FALSE);
327 }
328
329 if (pdata->set_vsync_notifier != NULL) {
330 vsync_fnc_enabled = TRUE;
331 pdata->set_vsync_notifier(mdp_vsync_handler,
332 (void *)mfd);
333 }
334 }
335 }
336
337 if ((mfd) && (!vsync_fnc_enabled))
338 mfd->vsync_handler_pending = FALSE;
339}
340
341boolean mdp_hw_vsync_set_handler(msm_fb_vsync_handler_type handler, void *data)
342{
343 /*
344 * ToDo: tried enabling/disabling GPIO MDP HW VSYNC interrupt
345 * but getting inaccurate timing in mdp_vsync_handler()
346 * enable_irq(MDP_HW_VSYNC_IRQ);
347 */
348
349 return TRUE;
350}
351
352uint32 mdp_get_lcd_line_counter(struct msm_fb_data_type *mfd)
353{
354 uint32 elapsed_usec_time;
355 uint32 lcd_line;
356 ktime_t last_vsync_timetick_local;
357 ktime_t curr_time;
358 unsigned long flag;
359
360 if ((!mfd->panel_info.lcd.vsync_enable) || (!vsync_mode))
361 return 0;
362
363 spin_lock_irqsave(&mdp_spin_lock, flag);
364 last_vsync_timetick_local = mfd->last_vsync_timetick;
365 spin_unlock_irqrestore(&mdp_spin_lock, flag);
366
367 curr_time = ktime_get_real();
368 elapsed_usec_time =
369 ((curr_time.tv.sec - last_vsync_timetick_local.tv.sec) * 1000000) +
370 ((curr_time.tv.nsec - last_vsync_timetick_local.tv.nsec) / 1000);
371
372 elapsed_usec_time = elapsed_usec_time % mfd->lcd_ref_usec_time;
373
374 /* lcd line calculation referencing to line counter = 0 */
375 lcd_line =
376 (elapsed_usec_time * mfd->total_lcd_lines) / mfd->lcd_ref_usec_time;
377
378 /* lcd line adjusment referencing to the actual line counter at vsync */
379 lcd_line =
380 (mfd->total_lcd_lines - mfd->panel_info.lcd.v_back_porch +
381 lcd_line) % (mfd->total_lcd_lines + 1);
382
383 if (lcd_line > mfd->total_lcd_lines) {
384 MSM_FB_INFO
385 ("mdp_get_lcd_line_counter: mdp_lcd_rd_cnt >= mfd->total_lcd_lines error!\n");
386 }
387
388 return lcd_line;
389}
diff --git a/drivers/staging/msm/memory.c b/drivers/staging/msm/memory.c
new file mode 100644
index 000000000000..cc80fdf17d61
--- /dev/null
+++ b/drivers/staging/msm/memory.c
@@ -0,0 +1,214 @@
1/* arch/arm/mach-msm/memory.c
2 *
3 * Copyright (C) 2007 Google, Inc.
4 * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#include <linux/mm.h>
18#include <linux/mm_types.h>
19#include <linux/bootmem.h>
20#include <linux/module.h>
21#include <asm/pgtable.h>
22#include <asm/io.h>
23#include <asm/mach/map.h>
24#include "memory_ll.h"
25#include <asm/cacheflush.h>
26#if defined(CONFIG_MSM_NPA_REMOTE)
27#include "npa_remote.h"
28#include <linux/completion.h>
29#include <linux/err.h>
30#endif
31
32int arch_io_remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,
33 unsigned long pfn, unsigned long size, pgprot_t prot)
34{
35 unsigned long pfn_addr = pfn << PAGE_SHIFT;
36/*
37 if ((pfn_addr >= 0x88000000) && (pfn_addr < 0xD0000000)) {
38 prot = pgprot_device(prot);
39 printk("remapping device %lx\n", prot);
40 }
41*/
42 panic("Memory remap PFN stuff not done\n");
43 return remap_pfn_range(vma, addr, pfn, size, prot);
44}
45
46void *zero_page_strongly_ordered;
47
48static void map_zero_page_strongly_ordered(void)
49{
50 if (zero_page_strongly_ordered)
51 return;
52/*
53 zero_page_strongly_ordered =
54 ioremap_strongly_ordered(page_to_pfn(empty_zero_page)
55 << PAGE_SHIFT, PAGE_SIZE);
56*/
57 panic("Strongly ordered memory functions not implemented\n");
58}
59
60void write_to_strongly_ordered_memory(void)
61{
62 map_zero_page_strongly_ordered();
63 *(int *)zero_page_strongly_ordered = 0;
64}
65EXPORT_SYMBOL(write_to_strongly_ordered_memory);
66
67void flush_axi_bus_buffer(void)
68{
69 __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" \
70 : : "r" (0) : "memory");
71 write_to_strongly_ordered_memory();
72}
73
74#define CACHE_LINE_SIZE 32
75
76/* These cache related routines make the assumption that the associated
77 * physical memory is contiguous. They will operate on all (L1
78 * and L2 if present) caches.
79 */
80void clean_and_invalidate_caches(unsigned long vstart,
81 unsigned long length, unsigned long pstart)
82{
83 unsigned long vaddr;
84
85 for (vaddr = vstart; vaddr < vstart + length; vaddr += CACHE_LINE_SIZE)
86 asm ("mcr p15, 0, %0, c7, c14, 1" : : "r" (vaddr));
87#ifdef CONFIG_OUTER_CACHE
88 outer_flush_range(pstart, pstart + length);
89#endif
90 asm ("mcr p15, 0, %0, c7, c10, 4" : : "r" (0));
91 asm ("mcr p15, 0, %0, c7, c5, 0" : : "r" (0));
92
93 flush_axi_bus_buffer();
94}
95
96void clean_caches(unsigned long vstart,
97 unsigned long length, unsigned long pstart)
98{
99 unsigned long vaddr;
100
101 for (vaddr = vstart; vaddr < vstart + length; vaddr += CACHE_LINE_SIZE)
102 asm ("mcr p15, 0, %0, c7, c10, 1" : : "r" (vaddr));
103#ifdef CONFIG_OUTER_CACHE
104 outer_clean_range(pstart, pstart + length);
105#endif
106 asm ("mcr p15, 0, %0, c7, c10, 4" : : "r" (0));
107 asm ("mcr p15, 0, %0, c7, c5, 0" : : "r" (0));
108
109 flush_axi_bus_buffer();
110}
111
112void invalidate_caches(unsigned long vstart,
113 unsigned long length, unsigned long pstart)
114{
115 unsigned long vaddr;
116
117 for (vaddr = vstart; vaddr < vstart + length; vaddr += CACHE_LINE_SIZE)
118 asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (vaddr));
119#ifdef CONFIG_OUTER_CACHE
120 outer_inv_range(pstart, pstart + length);
121#endif
122 asm ("mcr p15, 0, %0, c7, c10, 4" : : "r" (0));
123 asm ("mcr p15, 0, %0, c7, c5, 0" : : "r" (0));
124
125 flush_axi_bus_buffer();
126}
127
128void *alloc_bootmem_aligned(unsigned long size, unsigned long alignment)
129{
130 void *unused_addr = NULL;
131 unsigned long addr, tmp_size, unused_size;
132
133 /* Allocate maximum size needed, see where it ends up.
134 * Then free it -- in this path there are no other allocators
135 * so we can depend on getting the same address back
136 * when we allocate a smaller piece that is aligned
137 * at the end (if necessary) and the piece we really want,
138 * then free the unused first piece.
139 */
140
141 tmp_size = size + alignment - PAGE_SIZE;
142 addr = (unsigned long)alloc_bootmem(tmp_size);
143 free_bootmem(__pa(addr), tmp_size);
144
145 unused_size = alignment - (addr % alignment);
146 if (unused_size)
147 unused_addr = alloc_bootmem(unused_size);
148
149 addr = (unsigned long)alloc_bootmem(size);
150 if (unused_size)
151 free_bootmem(__pa(unused_addr), unused_size);
152
153 return (void *)addr;
154}
155
156#if defined(CONFIG_MSM_NPA_REMOTE)
157struct npa_client *npa_memory_client;
158#endif
159
160static int change_memory_power_state(unsigned long start_pfn,
161 unsigned long nr_pages, int state)
162{
163#if defined(CONFIG_MSM_NPA_REMOTE)
164 static atomic_t node_created_flag = ATOMIC_INIT(1);
165#else
166 unsigned long start;
167 unsigned long size;
168 unsigned long virtual;
169#endif
170 int rc = 0;
171
172#if defined(CONFIG_MSM_NPA_REMOTE)
173 if (atomic_dec_and_test(&node_created_flag)) {
174 /* Create NPA 'required' client. */
175 npa_memory_client = npa_create_sync_client(NPA_MEMORY_NODE_NAME,
176 "memory node", NPA_CLIENT_REQUIRED);
177 if (IS_ERR(npa_memory_client)) {
178 rc = PTR_ERR(npa_memory_client);
179 return rc;
180 }
181 }
182
183 rc = npa_issue_required_request(npa_memory_client, state);
184#else
185 if (state == MEMORY_DEEP_POWERDOWN) {
186 /* simulate turning off memory by writing bit pattern into it */
187 start = start_pfn << PAGE_SHIFT;
188 size = nr_pages << PAGE_SHIFT;
189 virtual = __phys_to_virt(start);
190 memset((void *)virtual, 0x27, size);
191 }
192#endif
193 return rc;
194}
195
196int platform_physical_remove_pages(unsigned long start_pfn,
197 unsigned long nr_pages)
198{
199 return change_memory_power_state(start_pfn, nr_pages,
200 MEMORY_DEEP_POWERDOWN);
201}
202
203int platform_physical_add_pages(unsigned long start_pfn,
204 unsigned long nr_pages)
205{
206 return change_memory_power_state(start_pfn, nr_pages, MEMORY_ACTIVE);
207}
208
209int platform_physical_low_power_pages(unsigned long start_pfn,
210 unsigned long nr_pages)
211{
212 return change_memory_power_state(start_pfn, nr_pages,
213 MEMORY_SELF_REFRESH);
214}
diff --git a/drivers/staging/msm/memory_ll.h b/drivers/staging/msm/memory_ll.h
new file mode 100644
index 000000000000..18a239a89a78
--- /dev/null
+++ b/drivers/staging/msm/memory_ll.h
@@ -0,0 +1,61 @@
1/*
2 * Copyright (C) 2007 Google, Inc.
3 * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 */
15#ifndef __ASM_ARCH_MEMORY_LL_H
16#define __ASM_ARCH_MEMORY_LL_H
17
18#define MAX_PHYSMEM_BITS 32
19#define SECTION_SIZE_BITS 25
20
21#define HAS_ARCH_IO_REMAP_PFN_RANGE
22
23#ifndef __ASSEMBLY__
24void *alloc_bootmem_aligned(unsigned long size, unsigned long alignment);
25void clean_and_invalidate_caches(unsigned long, unsigned long, unsigned long);
26void clean_caches(unsigned long, unsigned long, unsigned long);
27void invalidate_caches(unsigned long, unsigned long, unsigned long);
28int platform_physical_remove_pages(unsigned long, unsigned long);
29int platform_physical_add_pages(unsigned long, unsigned long);
30int platform_physical_low_power_pages(unsigned long, unsigned long);
31
32#ifdef CONFIG_ARCH_MSM_ARM11
33void write_to_strongly_ordered_memory(void);
34
35#include <asm/mach-types.h>
36
37#define arch_barrier_extra() do \
38 { if (machine_is_msm7x27_surf() || machine_is_msm7x27_ffa()) \
39 write_to_strongly_ordered_memory(); \
40 } while (0)
41#endif
42
43#ifdef CONFIG_CACHE_L2X0
44extern void l2x0_cache_sync(void);
45#define finish_arch_switch(prev) do { l2x0_cache_sync(); } while (0)
46#endif
47
48#endif
49
50#ifdef CONFIG_ARCH_MSM_SCORPION
51#define arch_has_speculative_dfetch() 1
52#endif
53
54#endif
55
56/* these correspond to values known by the modem */
57#define MEMORY_DEEP_POWERDOWN 0
58#define MEMORY_SELF_REFRESH 1
59#define MEMORY_ACTIVE 2
60
61#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
index 000000000000..af5620e4eee1
--- /dev/null
+++ b/drivers/staging/msm/msm_fb.c
@@ -0,0 +1,2354 @@
1/*
2 *
3 * Core MSM framebuffer driver.
4 *
5 * Copyright (C) 2007 Google Incorporated
6 * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
7 *
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#include <linux/module.h>
19#include <linux/moduleparam.h>
20#include <linux/kernel.h>
21#include <linux/slab.h>
22#include <linux/delay.h>
23#include <linux/mm.h>
24#include <linux/fb.h>
25#include "msm_mdp.h"
26#include <linux/init.h>
27#include <linux/ioport.h>
28#include <linux/device.h>
29#include <linux/dma-mapping.h>
30#include <mach/board.h>
31#include <linux/uaccess.h>
32
33#include <linux/workqueue.h>
34#include <linux/string.h>
35#include <linux/version.h>
36#include <linux/proc_fs.h>
37#include <linux/vmalloc.h>
38#include <linux/debugfs.h>
39#include <linux/console.h>
40#include <linux/leds.h>
41#include <asm/dma-mapping.h>
42
43
44#define MSM_FB_C
45#include "msm_fb.h"
46#include "mddihosti.h"
47#include "tvenc.h"
48#include "mdp.h"
49#include "mdp4.h"
50
51#ifdef CONFIG_FB_MSM_LOGO
52#define INIT_IMAGE_FILE "/logo.rle"
53extern int load_565rle_image(char *filename);
54#endif
55
56
57#define pgprot_noncached(prot) \
58 __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED)
59#define pgprot_writecombine(prot) \
60 __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE)
61#define pgprot_device(prot) \
62 __pgprot_modify(prot, L_PTE_MT_MASK|L_PTE_EXEC, L_PTE_MT_DEV_NONSHARED)
63#define pgprot_writethroughcache(prot) \
64 __pgprot((pgprot_val(prot) & ~L_PTE_MT_MASK) | L_PTE_MT_WRITETHROUGH)
65#define pgprot_writebackcache(prot) \
66 __pgprot((pgprot_val(prot) & ~L_PTE_MT_MASK) | L_PTE_MT_WRITEBACK)
67#define pgprot_writebackwacache(prot) \
68 __pgprot((pgprot_val(prot) & ~L_PTE_MT_MASK) | L_PTE_MT_WRITEALLOC)
69
70static unsigned char *fbram;
71static unsigned char *fbram_phys;
72static int fbram_size;
73
74static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
75static int pdev_list_cnt;
76
77int vsync_mode = 1;
78
79#define MAX_FBI_LIST 32
80static struct fb_info *fbi_list[MAX_FBI_LIST];
81static int fbi_list_index;
82
83static struct msm_fb_data_type *mfd_list[MAX_FBI_LIST];
84static int mfd_list_index;
85
86static u32 msm_fb_pseudo_palette[16] = {
87 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff,
88 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
89 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
90 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
91};
92
93u32 msm_fb_debug_enabled;
94/* Setting msm_fb_msg_level to 8 prints out ALL messages */
95u32 msm_fb_msg_level = 7;
96
97/* Setting mddi_msg_level to 8 prints out ALL messages */
98u32 mddi_msg_level = 5;
99
100extern int32 mdp_block_power_cnt[MDP_MAX_BLOCK];
101extern unsigned long mdp_timer_duration;
102
103static int msm_fb_register(struct msm_fb_data_type *mfd);
104static int msm_fb_open(struct fb_info *info, int user);
105static int msm_fb_release(struct fb_info *info, int user);
106static int msm_fb_pan_display(struct fb_var_screeninfo *var,
107 struct fb_info *info);
108static int msm_fb_stop_sw_refresher(struct msm_fb_data_type *mfd);
109int msm_fb_resume_sw_refresher(struct msm_fb_data_type *mfd);
110static int msm_fb_check_var(struct fb_var_screeninfo *var,
111 struct fb_info *info);
112static int msm_fb_set_par(struct fb_info *info);
113static int msm_fb_blank_sub(int blank_mode, struct fb_info *info,
114 boolean op_enable);
115static int msm_fb_suspend_sub(struct msm_fb_data_type *mfd);
116static int msm_fb_resume_sub(struct msm_fb_data_type *mfd);
117static int msm_fb_ioctl(struct fb_info *info, unsigned int cmd,
118 unsigned long arg);
119static int msm_fb_mmap(struct fb_info *info, struct vm_area_struct * vma);
120
121#ifdef MSM_FB_ENABLE_DBGFS
122
123#define MSM_FB_MAX_DBGFS 1024
124#define MAX_BACKLIGHT_BRIGHTNESS 255
125
126int msm_fb_debugfs_file_index;
127struct dentry *msm_fb_debugfs_root;
128struct dentry *msm_fb_debugfs_file[MSM_FB_MAX_DBGFS];
129
130struct dentry *msm_fb_get_debugfs_root(void)
131{
132 if (msm_fb_debugfs_root == NULL)
133 msm_fb_debugfs_root = debugfs_create_dir("msm_fb", NULL);
134
135 return msm_fb_debugfs_root;
136}
137
138void msm_fb_debugfs_file_create(struct dentry *root, const char *name,
139 u32 *var)
140{
141 if (msm_fb_debugfs_file_index >= MSM_FB_MAX_DBGFS)
142 return;
143
144 msm_fb_debugfs_file[msm_fb_debugfs_file_index++] =
145 debugfs_create_u32(name, S_IRUGO | S_IWUSR, root, var);
146}
147#endif
148
149int msm_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
150{
151 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
152
153 if (!mfd->cursor_update)
154 return -ENODEV;
155
156 return mfd->cursor_update(info, cursor);
157}
158
159static int msm_fb_resource_initialized;
160
161#ifndef CONFIG_FB_BACKLIGHT
162static int lcd_backlight_registered;
163
164static void msm_fb_set_bl_brightness(struct led_classdev *led_cdev,
165 enum led_brightness value)
166{
167 struct msm_fb_data_type *mfd = dev_get_drvdata(led_cdev->dev->parent);
168 int bl_lvl;
169
170 if (value > MAX_BACKLIGHT_BRIGHTNESS)
171 value = MAX_BACKLIGHT_BRIGHTNESS;
172
173 /* This maps android backlight level 0 to 255 into
174 driver backlight level 0 to bl_max with rounding */
175 bl_lvl = (2 * value * mfd->panel_info.bl_max + MAX_BACKLIGHT_BRIGHTNESS)
176 /(2 * MAX_BACKLIGHT_BRIGHTNESS);
177
178 if (!bl_lvl && value)
179 bl_lvl = 1;
180
181 msm_fb_set_backlight(mfd, bl_lvl, 1);
182}
183
184static struct led_classdev backlight_led = {
185 .name = "lcd-backlight",
186 .brightness = MAX_BACKLIGHT_BRIGHTNESS,
187 .brightness_set = msm_fb_set_bl_brightness,
188};
189#endif
190
191static struct msm_fb_platform_data *msm_fb_pdata;
192
193int msm_fb_detect_client(const char *name)
194{
195 int ret = -EPERM;
196#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
197 u32 id;
198#endif
199
200 if (msm_fb_pdata && msm_fb_pdata->detect_client) {
201 ret = msm_fb_pdata->detect_client(name);
202
203 /* if it's non mddi panel, we need to pre-scan
204 mddi client to see if we can disable mddi host */
205
206#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
207 if (!ret && msm_fb_pdata->mddi_prescan)
208 id = mddi_get_client_id();
209#endif
210 }
211
212 return ret;
213}
214
215static int msm_fb_probe(struct platform_device *pdev)
216{
217 struct msm_fb_data_type *mfd;
218 int rc;
219
220 MSM_FB_DEBUG("msm_fb_probe\n");
221
222 if ((pdev->id == 0) && (pdev->num_resources > 0)) {
223 msm_fb_pdata = pdev->dev.platform_data;
224 fbram_size =
225 pdev->resource[0].end - pdev->resource[0].start + 1;
226 fbram_phys = (char *)pdev->resource[0].start;
227 fbram = ioremap((unsigned long)fbram_phys, fbram_size);
228
229 if (!fbram) {
230 printk(KERN_ERR "fbram ioremap failed!\n");
231 return -ENOMEM;
232 }
233 MSM_FB_INFO("msm_fb_probe: phy_Addr = 0x%x virt = 0x%x\n",
234 (int)fbram_phys, (int)fbram);
235
236 msm_fb_resource_initialized = 1;
237 return 0;
238 }
239
240 if (!msm_fb_resource_initialized)
241 return -EPERM;
242
243 mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
244
245 if (!mfd)
246 return -ENODEV;
247
248 if (mfd->key != MFD_KEY)
249 return -EINVAL;
250
251 if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
252 return -ENOMEM;
253
254 mfd->panel_info.frame_count = 0;
255 mfd->bl_level = mfd->panel_info.bl_max;
256
257 if (mfd->panel_info.type == LCDC_PANEL)
258 mfd->allow_set_offset =
259 msm_fb_pdata->allow_set_offset != NULL ?
260 msm_fb_pdata->allow_set_offset() : 0;
261 else
262 mfd->allow_set_offset = 0;
263
264 rc = msm_fb_register(mfd);
265 if (rc)
266 return rc;
267
268#ifdef CONFIG_FB_BACKLIGHT
269 msm_fb_config_backlight(mfd);
270#else
271 /* android supports only one lcd-backlight/lcd for now */
272 if (!lcd_backlight_registered) {
273 if (led_classdev_register(&pdev->dev, &backlight_led))
274 printk(KERN_ERR "led_classdev_register failed\n");
275 else
276 lcd_backlight_registered = 1;
277 }
278#endif
279
280 pdev_list[pdev_list_cnt++] = pdev;
281 return 0;
282}
283
284static int msm_fb_remove(struct platform_device *pdev)
285{
286 struct msm_fb_data_type *mfd;
287
288 MSM_FB_DEBUG("msm_fb_remove\n");
289
290 mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
291
292 if (!mfd)
293 return -ENODEV;
294
295 if (mfd->key != MFD_KEY)
296 return -EINVAL;
297
298 if (msm_fb_suspend_sub(mfd))
299 printk(KERN_ERR "msm_fb_remove: can't stop the device %d\n", mfd->index);
300
301 if (mfd->channel_irq != 0)
302 free_irq(mfd->channel_irq, (void *)mfd);
303
304 if (mfd->vsync_width_boundary)
305 vfree(mfd->vsync_width_boundary);
306
307 if (mfd->vsync_resync_timer.function)
308 del_timer(&mfd->vsync_resync_timer);
309
310 if (mfd->refresh_timer.function)
311 del_timer(&mfd->refresh_timer);
312
313 if (mfd->dma_hrtimer.function)
314 hrtimer_cancel(&mfd->dma_hrtimer);
315
316 /* remove /dev/fb* */
317 unregister_framebuffer(mfd->fbi);
318
319#ifdef CONFIG_FB_BACKLIGHT
320 /* remove /sys/class/backlight */
321 backlight_device_unregister(mfd->fbi->bl_dev);
322#else
323 if (lcd_backlight_registered) {
324 lcd_backlight_registered = 0;
325 led_classdev_unregister(&backlight_led);
326 }
327#endif
328
329#ifdef MSM_FB_ENABLE_DBGFS
330 if (mfd->sub_dir)
331 debugfs_remove(mfd->sub_dir);
332#endif
333
334 return 0;
335}
336
337#if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND)
338static int msm_fb_suspend(struct platform_device *pdev, pm_message_t state)
339{
340 struct msm_fb_data_type *mfd;
341 int ret = 0;
342
343 MSM_FB_DEBUG("msm_fb_suspend\n");
344
345 mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
346
347 if ((!mfd) || (mfd->key != MFD_KEY))
348 return 0;
349
350 acquire_console_sem();
351 fb_set_suspend(mfd->fbi, 1);
352
353 ret = msm_fb_suspend_sub(mfd);
354 if (ret != 0) {
355 printk(KERN_ERR "msm_fb: failed to suspend! %d\n", ret);
356 fb_set_suspend(mfd->fbi, 0);
357 } else {
358 pdev->dev.power.power_state = state;
359 }
360
361 release_console_sem();
362 return ret;
363}
364#else
365#define msm_fb_suspend NULL
366#endif
367
368static int msm_fb_suspend_sub(struct msm_fb_data_type *mfd)
369{
370 int ret = 0;
371
372 if ((!mfd) || (mfd->key != MFD_KEY))
373 return 0;
374
375 /*
376 * suspend this channel
377 */
378 mfd->suspend.sw_refreshing_enable = mfd->sw_refreshing_enable;
379 mfd->suspend.op_enable = mfd->op_enable;
380 mfd->suspend.panel_power_on = mfd->panel_power_on;
381
382 if (mfd->op_enable) {
383 ret =
384 msm_fb_blank_sub(FB_BLANK_POWERDOWN, mfd->fbi,
385 mfd->suspend.op_enable);
386 if (ret) {
387 MSM_FB_INFO
388 ("msm_fb_suspend: can't turn off display!\n");
389 return ret;
390 }
391 mfd->op_enable = FALSE;
392 }
393 /*
394 * try to power down
395 */
396 mdp_pipe_ctrl(MDP_MASTER_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
397
398 /*
399 * detach display channel irq if there's any
400 * or wait until vsync-resync completes
401 */
402 if ((mfd->dest == DISPLAY_LCD)) {
403 if (mfd->panel_info.lcd.vsync_enable) {
404 if (mfd->panel_info.lcd.hw_vsync_mode) {
405 if (mfd->channel_irq != 0)
406 disable_irq(mfd->channel_irq);
407 } else {
408 volatile boolean vh_pending;
409 do {
410 vh_pending = mfd->vsync_handler_pending;
411 } while (vh_pending);
412 }
413 }
414 }
415
416 return 0;
417}
418
419#if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND)
420static int msm_fb_resume(struct platform_device *pdev)
421{
422 /* This resume function is called when interrupt is enabled.
423 */
424 int ret = 0;
425 struct msm_fb_data_type *mfd;
426
427 MSM_FB_DEBUG("msm_fb_resume\n");
428
429 mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
430
431 if ((!mfd) || (mfd->key != MFD_KEY))
432 return 0;
433
434 acquire_console_sem();
435 ret = msm_fb_resume_sub(mfd);
436 pdev->dev.power.power_state = PMSG_ON;
437 fb_set_suspend(mfd->fbi, 1);
438 release_console_sem();
439
440 return ret;
441}
442#else
443#define msm_fb_resume NULL
444#endif
445
446static int msm_fb_resume_sub(struct msm_fb_data_type *mfd)
447{
448 int ret = 0;
449
450 if ((!mfd) || (mfd->key != MFD_KEY))
451 return 0;
452
453 /* attach display channel irq if there's any */
454 if (mfd->channel_irq != 0)
455 enable_irq(mfd->channel_irq);
456
457 /* resume state var recover */
458 mfd->sw_refreshing_enable = mfd->suspend.sw_refreshing_enable;
459 mfd->op_enable = mfd->suspend.op_enable;
460
461 if (mfd->suspend.panel_power_on) {
462 ret =
463 msm_fb_blank_sub(FB_BLANK_UNBLANK, mfd->fbi,
464 mfd->op_enable);
465 if (ret)
466 MSM_FB_INFO("msm_fb_resume: can't turn on display!\n");
467 }
468
469 return ret;
470}
471
472static struct platform_driver msm_fb_driver = {
473 .probe = msm_fb_probe,
474 .remove = msm_fb_remove,
475#ifndef CONFIG_HAS_EARLYSUSPEND
476 .suspend = msm_fb_suspend,
477 .resume = msm_fb_resume,
478#endif
479 .shutdown = NULL,
480 .driver = {
481 /* Driver name must match the device name added in platform.c. */
482 .name = "msm_fb",
483 },
484};
485
486#ifdef CONFIG_HAS_EARLYSUSPEND
487static void msmfb_early_suspend(struct early_suspend *h)
488{
489 struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
490 early_suspend);
491 msm_fb_suspend_sub(mfd);
492}
493
494static void msmfb_early_resume(struct early_suspend *h)
495{
496 struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
497 early_suspend);
498 msm_fb_resume_sub(mfd);
499}
500#endif
501
502void msm_fb_set_backlight(struct msm_fb_data_type *mfd, __u32 bkl_lvl, u32 save)
503{
504 struct msm_fb_panel_data *pdata;
505
506 pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
507
508 if ((pdata) && (pdata->set_backlight)) {
509 down(&mfd->sem);
510 if ((bkl_lvl != mfd->bl_level) || (!save)) {
511 u32 old_lvl;
512
513 old_lvl = mfd->bl_level;
514 mfd->bl_level = bkl_lvl;
515 pdata->set_backlight(mfd);
516
517 if (!save)
518 mfd->bl_level = old_lvl;
519 }
520 up(&mfd->sem);
521 }
522}
523
524static int msm_fb_blank_sub(int blank_mode, struct fb_info *info,
525 boolean op_enable)
526{
527 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
528 struct msm_fb_panel_data *pdata = NULL;
529 int ret = 0;
530
531 if (!op_enable)
532 return -EPERM;
533
534 pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
535 if ((!pdata) || (!pdata->on) || (!pdata->off)) {
536 printk(KERN_ERR "msm_fb_blank_sub: no panel operation detected!\n");
537 return -ENODEV;
538 }
539
540 switch (blank_mode) {
541 case FB_BLANK_UNBLANK:
542 if (!mfd->panel_power_on) {
543 mdelay(100);
544 ret = pdata->on(mfd->pdev);
545 if (ret == 0) {
546 mfd->panel_power_on = TRUE;
547
548 msm_fb_set_backlight(mfd,
549 mfd->bl_level, 0);
550
551/* ToDo: possible conflict with android which doesn't expect sw refresher */
552/*
553 if (!mfd->hw_refresh)
554 {
555 if ((ret = msm_fb_resume_sw_refresher(mfd)) != 0)
556 {
557 MSM_FB_INFO("msm_fb_blank_sub: msm_fb_resume_sw_refresher failed = %d!\n",ret);
558 }
559 }
560*/
561 }
562 }
563 break;
564
565 case FB_BLANK_VSYNC_SUSPEND:
566 case FB_BLANK_HSYNC_SUSPEND:
567 case FB_BLANK_NORMAL:
568 case FB_BLANK_POWERDOWN:
569 default:
570 if (mfd->panel_power_on) {
571 int curr_pwr_state;
572
573 mfd->op_enable = FALSE;
574 curr_pwr_state = mfd->panel_power_on;
575 mfd->panel_power_on = FALSE;
576
577 mdelay(100);
578 ret = pdata->off(mfd->pdev);
579 if (ret)
580 mfd->panel_power_on = curr_pwr_state;
581
582 msm_fb_set_backlight(mfd, 0, 0);
583 mfd->op_enable = TRUE;
584 }
585 break;
586 }
587
588 return ret;
589}
590
591static void msm_fb_fillrect(struct fb_info *info,
592 const struct fb_fillrect *rect)
593{
594 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
595
596 cfb_fillrect(info, rect);
597 if (!mfd->hw_refresh && (info->var.yoffset == 0) &&
598 !mfd->sw_currently_refreshing) {
599 struct fb_var_screeninfo var;
600
601 var = info->var;
602 var.reserved[0] = 0x54445055;
603 var.reserved[1] = (rect->dy << 16) | (rect->dx);
604 var.reserved[2] = ((rect->dy + rect->height) << 16) |
605 (rect->dx + rect->width);
606
607 msm_fb_pan_display(&var, info);
608 }
609}
610
611static void msm_fb_copyarea(struct fb_info *info,
612 const struct fb_copyarea *area)
613{
614 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
615
616 cfb_copyarea(info, area);
617 if (!mfd->hw_refresh && (info->var.yoffset == 0) &&
618 !mfd->sw_currently_refreshing) {
619 struct fb_var_screeninfo var;
620
621 var = info->var;
622 var.reserved[0] = 0x54445055;
623 var.reserved[1] = (area->dy << 16) | (area->dx);
624 var.reserved[2] = ((area->dy + area->height) << 16) |
625 (area->dx + area->width);
626
627 msm_fb_pan_display(&var, info);
628 }
629}
630
631static void msm_fb_imageblit(struct fb_info *info, const struct fb_image *image)
632{
633 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
634
635 cfb_imageblit(info, image);
636 if (!mfd->hw_refresh && (info->var.yoffset == 0) &&
637 !mfd->sw_currently_refreshing) {
638 struct fb_var_screeninfo var;
639
640 var = info->var;
641 var.reserved[0] = 0x54445055;
642 var.reserved[1] = (image->dy << 16) | (image->dx);
643 var.reserved[2] = ((image->dy + image->height) << 16) |
644 (image->dx + image->width);
645
646 msm_fb_pan_display(&var, info);
647 }
648}
649
650static int msm_fb_blank(int blank_mode, struct fb_info *info)
651{
652 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
653 return msm_fb_blank_sub(blank_mode, info, mfd->op_enable);
654}
655
656static int msm_fb_set_lut(struct fb_cmap *cmap, struct fb_info *info)
657{
658 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
659
660 if (!mfd->lut_update)
661 return -ENODEV;
662
663 mfd->lut_update(info, cmap);
664 return 0;
665}
666
667/*
668 * Custom Framebuffer mmap() function for MSM driver.
669 * Differs from standard mmap() function by allowing for customized
670 * page-protection.
671 */
672static int msm_fb_mmap(struct fb_info *info, struct vm_area_struct * vma)
673{
674 /* Get frame buffer memory range. */
675 unsigned long start = info->fix.smem_start;
676 u32 len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len);
677 unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
678 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
679 if (off >= len) {
680 /* memory mapped io */
681 off -= len;
682 if (info->var.accel_flags) {
683 mutex_unlock(&info->lock);
684 return -EINVAL;
685 }
686 start = info->fix.mmio_start;
687 len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len);
688 }
689
690 /* Set VM flags. */
691 start &= PAGE_MASK;
692 if ((vma->vm_end - vma->vm_start + off) > len)
693 return -EINVAL;
694 off += start;
695 vma->vm_pgoff = off >> PAGE_SHIFT;
696 /* This is an IO map - tell maydump to skip this VMA */
697 vma->vm_flags |= VM_IO | VM_RESERVED;
698
699 /* Set VM page protection */
700 if (mfd->mdp_fb_page_protection == MDP_FB_PAGE_PROTECTION_WRITECOMBINE)
701 vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
702 else if (mfd->mdp_fb_page_protection ==
703 MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE)
704 vma->vm_page_prot = pgprot_writethroughcache(vma->vm_page_prot);
705 else if (mfd->mdp_fb_page_protection ==
706 MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE)
707 vma->vm_page_prot = pgprot_writebackcache(vma->vm_page_prot);
708 else if (mfd->mdp_fb_page_protection ==
709 MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE)
710 vma->vm_page_prot = pgprot_writebackwacache(vma->vm_page_prot);
711 else
712 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
713
714 /* Remap the frame buffer I/O range */
715 if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
716 vma->vm_end - vma->vm_start,
717 vma->vm_page_prot))
718 return -EAGAIN;
719
720 return 0;
721}
722
723static struct fb_ops msm_fb_ops = {
724 .owner = THIS_MODULE,
725 .fb_open = msm_fb_open,
726 .fb_release = msm_fb_release,
727 .fb_read = NULL,
728 .fb_write = NULL,
729 .fb_cursor = NULL,
730 .fb_check_var = msm_fb_check_var, /* vinfo check */
731 .fb_set_par = msm_fb_set_par, /* set the video mode according to info->var */
732 .fb_setcolreg = NULL, /* set color register */
733 .fb_blank = msm_fb_blank, /* blank display */
734 .fb_pan_display = msm_fb_pan_display, /* pan display */
735 .fb_fillrect = msm_fb_fillrect, /* Draws a rectangle */
736 .fb_copyarea = msm_fb_copyarea, /* Copy data from area to another */
737 .fb_imageblit = msm_fb_imageblit, /* Draws a image to the display */
738 .fb_rotate = NULL,
739 .fb_sync = NULL, /* wait for blit idle, optional */
740 .fb_ioctl = msm_fb_ioctl, /* perform fb specific ioctl (optional) */
741 .fb_mmap = msm_fb_mmap,
742};
743
744static int msm_fb_register(struct msm_fb_data_type *mfd)
745{
746 int ret = -ENODEV;
747 int bpp;
748 struct msm_panel_info *panel_info = &mfd->panel_info;
749 struct fb_info *fbi = mfd->fbi;
750 struct fb_fix_screeninfo *fix;
751 struct fb_var_screeninfo *var;
752 int *id;
753 int fbram_offset;
754
755 /*
756 * fb info initialization
757 */
758 fix = &fbi->fix;
759 var = &fbi->var;
760
761 fix->type_aux = 0; /* if type == FB_TYPE_INTERLEAVED_PLANES */
762 fix->visual = FB_VISUAL_TRUECOLOR; /* True Color */
763 fix->ywrapstep = 0; /* No support */
764 fix->mmio_start = 0; /* No MMIO Address */
765 fix->mmio_len = 0; /* No MMIO Address */
766 fix->accel = FB_ACCEL_NONE;/* FB_ACCEL_MSM needes to be added in fb.h */
767
768 var->xoffset = 0, /* Offset from virtual to visible */
769 var->yoffset = 0, /* resolution */
770 var->grayscale = 0, /* No graylevels */
771 var->nonstd = 0, /* standard pixel format */
772 var->activate = FB_ACTIVATE_VBL, /* activate it at vsync */
773 var->height = -1, /* height of picture in mm */
774 var->width = -1, /* width of picture in mm */
775 var->accel_flags = 0, /* acceleration flags */
776 var->sync = 0, /* see FB_SYNC_* */
777 var->rotate = 0, /* angle we rotate counter clockwise */
778 mfd->op_enable = FALSE;
779
780 switch (mfd->fb_imgType) {
781 case MDP_RGB_565:
782 fix->type = FB_TYPE_PACKED_PIXELS;
783 fix->xpanstep = 1;
784 fix->ypanstep = 1;
785 var->vmode = FB_VMODE_NONINTERLACED;
786 var->blue.offset = 0;
787 var->green.offset = 5;
788 var->red.offset = 11;
789 var->blue.length = 5;
790 var->green.length = 6;
791 var->red.length = 5;
792 var->blue.msb_right = 0;
793 var->green.msb_right = 0;
794 var->red.msb_right = 0;
795 var->transp.offset = 0;
796 var->transp.length = 0;
797 bpp = 2;
798 break;
799
800 case MDP_RGB_888:
801 fix->type = FB_TYPE_PACKED_PIXELS;
802 fix->xpanstep = 1;
803 fix->ypanstep = 1;
804 var->vmode = FB_VMODE_NONINTERLACED;
805 var->blue.offset = 0;
806 var->green.offset = 8;
807 var->red.offset = 16;
808 var->blue.length = 8;
809 var->green.length = 8;
810 var->red.length = 8;
811 var->blue.msb_right = 0;
812 var->green.msb_right = 0;
813 var->red.msb_right = 0;
814 var->transp.offset = 0;
815 var->transp.length = 0;
816 bpp = 3;
817 break;
818
819 case MDP_ARGB_8888:
820 fix->type = FB_TYPE_PACKED_PIXELS;
821 fix->xpanstep = 1;
822 fix->ypanstep = 1;
823 var->vmode = FB_VMODE_NONINTERLACED;
824 var->blue.offset = 0;
825 var->green.offset = 8;
826 var->red.offset = 16;
827 var->blue.length = 8;
828 var->green.length = 8;
829 var->red.length = 8;
830 var->blue.msb_right = 0;
831 var->green.msb_right = 0;
832 var->red.msb_right = 0;
833 var->transp.offset = 24;
834 var->transp.length = 8;
835 bpp = 3;
836 break;
837
838 case MDP_YCRYCB_H2V1:
839 /* ToDo: need to check TV-Out YUV422i framebuffer format */
840 /* we might need to create new type define */
841 fix->type = FB_TYPE_INTERLEAVED_PLANES;
842 fix->xpanstep = 2;
843 fix->ypanstep = 1;
844 var->vmode = FB_VMODE_NONINTERLACED;
845
846 /* how about R/G/B offset? */
847 var->blue.offset = 0;
848 var->green.offset = 5;
849 var->red.offset = 11;
850 var->blue.length = 5;
851 var->green.length = 6;
852 var->red.length = 5;
853 var->blue.msb_right = 0;
854 var->green.msb_right = 0;
855 var->red.msb_right = 0;
856 var->transp.offset = 0;
857 var->transp.length = 0;
858 bpp = 2;
859 break;
860
861 default:
862 MSM_FB_ERR("msm_fb_init: fb %d unkown image type!\n",
863 mfd->index);
864 return ret;
865 }
866
867 /* The adreno GPU hardware requires that the pitch be aligned to
868 32 pixels for color buffers, so for the cases where the GPU
869 is writing directly to fb0, the framebuffer pitch
870 also needs to be 32 pixel aligned */
871
872 if (mfd->index == 0)
873 fix->line_length = ALIGN(panel_info->xres * bpp, 32);
874 else
875 fix->line_length = panel_info->xres * bpp;
876
877 fix->smem_len = fix->line_length * panel_info->yres * mfd->fb_page;
878
879 mfd->var_xres = panel_info->xres;
880 mfd->var_yres = panel_info->yres;
881
882 var->pixclock = mfd->panel_info.clk_rate;
883 mfd->var_pixclock = var->pixclock;
884
885 var->xres = panel_info->xres;
886 var->yres = panel_info->yres;
887 var->xres_virtual = panel_info->xres;
888 var->yres_virtual = panel_info->yres * mfd->fb_page;
889 var->bits_per_pixel = bpp * 8, /* FrameBuffer color depth */
890 /*
891 * id field for fb app
892 */
893 id = (int *)&mfd->panel;
894
895#if defined(CONFIG_FB_MSM_MDP22)
896 snprintf(fix->id, sizeof(fix->id), "msmfb22_%x", (__u32) *id);
897#elif defined(CONFIG_FB_MSM_MDP30)
898 snprintf(fix->id, sizeof(fix->id), "msmfb30_%x", (__u32) *id);
899#elif defined(CONFIG_FB_MSM_MDP31)
900 snprintf(fix->id, sizeof(fix->id), "msmfb31_%x", (__u32) *id);
901#elif defined(CONFIG_FB_MSM_MDP40)
902 snprintf(fix->id, sizeof(fix->id), "msmfb40_%x", (__u32) *id);
903#else
904 error CONFIG_FB_MSM_MDP undefined !
905#endif
906 fbi->fbops = &msm_fb_ops;
907 fbi->flags = FBINFO_FLAG_DEFAULT;
908 fbi->pseudo_palette = msm_fb_pseudo_palette;
909
910 mfd->ref_cnt = 0;
911 mfd->sw_currently_refreshing = FALSE;
912 mfd->sw_refreshing_enable = TRUE;
913 mfd->panel_power_on = FALSE;
914
915 mfd->pan_waiting = FALSE;
916 init_completion(&mfd->pan_comp);
917 init_completion(&mfd->refresher_comp);
918 init_MUTEX(&mfd->sem);
919
920 fbram_offset = PAGE_ALIGN((int)fbram)-(int)fbram;
921 fbram += fbram_offset;
922 fbram_phys += fbram_offset;
923 fbram_size -= fbram_offset;
924
925 if (fbram_size < fix->smem_len) {
926 printk(KERN_ERR "error: no more framebuffer memory!\n");
927 return -ENOMEM;
928 }
929
930 fbi->screen_base = fbram;
931 fbi->fix.smem_start = (unsigned long)fbram_phys;
932
933 memset(fbi->screen_base, 0x0, fix->smem_len);
934
935 mfd->op_enable = TRUE;
936 mfd->panel_power_on = FALSE;
937
938 /* cursor memory allocation */
939 if (mfd->cursor_update) {
940 mfd->cursor_buf = dma_alloc_coherent(NULL,
941 MDP_CURSOR_SIZE,
942 (dma_addr_t *) &mfd->cursor_buf_phys,
943 GFP_KERNEL);
944 if (!mfd->cursor_buf)
945 mfd->cursor_update = 0;
946 }
947
948 if (mfd->lut_update) {
949 ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
950 if (ret)
951 printk(KERN_ERR "%s: fb_alloc_cmap() failed!\n",
952 __func__);
953 }
954
955 if (register_framebuffer(fbi) < 0) {
956 if (mfd->lut_update)
957 fb_dealloc_cmap(&fbi->cmap);
958
959 if (mfd->cursor_buf)
960 dma_free_coherent(NULL,
961 MDP_CURSOR_SIZE,
962 mfd->cursor_buf,
963 (dma_addr_t) mfd->cursor_buf_phys);
964
965 mfd->op_enable = FALSE;
966 return -EPERM;
967 }
968
969 fbram += fix->smem_len;
970 fbram_phys += fix->smem_len;
971 fbram_size -= fix->smem_len;
972
973 MSM_FB_INFO
974 ("FrameBuffer[%d] %dx%d size=%d bytes is registered successfully!\n",
975 mfd->index, fbi->var.xres, fbi->var.yres, fbi->fix.smem_len);
976
977#ifdef CONFIG_FB_MSM_LOGO
978 if (!load_565rle_image(INIT_IMAGE_FILE)) ; /* Flip buffer */
979#endif
980 ret = 0;
981
982#ifdef CONFIG_HAS_EARLYSUSPEND
983 mfd->early_suspend.suspend = msmfb_early_suspend;
984 mfd->early_suspend.resume = msmfb_early_resume;
985 mfd->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 2;
986 register_early_suspend(&mfd->early_suspend);
987#endif
988
989#ifdef MSM_FB_ENABLE_DBGFS
990 {
991 struct dentry *root;
992 struct dentry *sub_dir;
993 char sub_name[2];
994
995 root = msm_fb_get_debugfs_root();
996 if (root != NULL) {
997 sub_name[0] = (char)(mfd->index + 0x30);
998 sub_name[1] = '\0';
999 sub_dir = debugfs_create_dir(sub_name, root);
1000 } else {
1001 sub_dir = NULL;
1002 }
1003
1004 mfd->sub_dir = sub_dir;
1005
1006 if (sub_dir) {
1007 msm_fb_debugfs_file_create(sub_dir, "op_enable",
1008 (u32 *) &mfd->op_enable);
1009 msm_fb_debugfs_file_create(sub_dir, "panel_power_on",
1010 (u32 *) &mfd->
1011 panel_power_on);
1012 msm_fb_debugfs_file_create(sub_dir, "ref_cnt",
1013 (u32 *) &mfd->ref_cnt);
1014 msm_fb_debugfs_file_create(sub_dir, "fb_imgType",
1015 (u32 *) &mfd->fb_imgType);
1016 msm_fb_debugfs_file_create(sub_dir,
1017 "sw_currently_refreshing",
1018 (u32 *) &mfd->
1019 sw_currently_refreshing);
1020 msm_fb_debugfs_file_create(sub_dir,
1021 "sw_refreshing_enable",
1022 (u32 *) &mfd->
1023 sw_refreshing_enable);
1024
1025 msm_fb_debugfs_file_create(sub_dir, "xres",
1026 (u32 *) &mfd->panel_info.
1027 xres);
1028 msm_fb_debugfs_file_create(sub_dir, "yres",
1029 (u32 *) &mfd->panel_info.
1030 yres);
1031 msm_fb_debugfs_file_create(sub_dir, "bpp",
1032 (u32 *) &mfd->panel_info.
1033 bpp);
1034 msm_fb_debugfs_file_create(sub_dir, "type",
1035 (u32 *) &mfd->panel_info.
1036 type);
1037 msm_fb_debugfs_file_create(sub_dir, "wait_cycle",
1038 (u32 *) &mfd->panel_info.
1039 wait_cycle);
1040 msm_fb_debugfs_file_create(sub_dir, "pdest",
1041 (u32 *) &mfd->panel_info.
1042 pdest);
1043 msm_fb_debugfs_file_create(sub_dir, "backbuff",
1044 (u32 *) &mfd->panel_info.
1045 fb_num);
1046 msm_fb_debugfs_file_create(sub_dir, "clk_rate",
1047 (u32 *) &mfd->panel_info.
1048 clk_rate);
1049 msm_fb_debugfs_file_create(sub_dir, "frame_count",
1050 (u32 *) &mfd->panel_info.
1051 frame_count);
1052
1053
1054 switch (mfd->dest) {
1055 case DISPLAY_LCD:
1056 msm_fb_debugfs_file_create(sub_dir,
1057 "vsync_enable",
1058 (u32 *)&mfd->panel_info.lcd.vsync_enable);
1059 msm_fb_debugfs_file_create(sub_dir,
1060 "refx100",
1061 (u32 *) &mfd->panel_info.lcd. refx100);
1062 msm_fb_debugfs_file_create(sub_dir,
1063 "v_back_porch",
1064 (u32 *) &mfd->panel_info.lcd.v_back_porch);
1065 msm_fb_debugfs_file_create(sub_dir,
1066 "v_front_porch",
1067 (u32 *) &mfd->panel_info.lcd.v_front_porch);
1068 msm_fb_debugfs_file_create(sub_dir,
1069 "v_pulse_width",
1070 (u32 *) &mfd->panel_info.lcd.v_pulse_width);
1071 msm_fb_debugfs_file_create(sub_dir,
1072 "hw_vsync_mode",
1073 (u32 *) &mfd->panel_info.lcd.hw_vsync_mode);
1074 msm_fb_debugfs_file_create(sub_dir,
1075 "vsync_notifier_period", (u32 *)
1076 &mfd->panel_info.lcd.vsync_notifier_period);
1077 break;
1078
1079 case DISPLAY_LCDC:
1080 msm_fb_debugfs_file_create(sub_dir,
1081 "h_back_porch",
1082 (u32 *) &mfd->panel_info.lcdc.h_back_porch);
1083 msm_fb_debugfs_file_create(sub_dir,
1084 "h_front_porch",
1085 (u32 *) &mfd->panel_info.lcdc.h_front_porch);
1086 msm_fb_debugfs_file_create(sub_dir,
1087 "h_pulse_width",
1088 (u32 *) &mfd->panel_info.lcdc.h_pulse_width);
1089 msm_fb_debugfs_file_create(sub_dir,
1090 "v_back_porch",
1091 (u32 *) &mfd->panel_info.lcdc.v_back_porch);
1092 msm_fb_debugfs_file_create(sub_dir,
1093 "v_front_porch",
1094 (u32 *) &mfd->panel_info.lcdc.v_front_porch);
1095 msm_fb_debugfs_file_create(sub_dir,
1096 "v_pulse_width",
1097 (u32 *) &mfd->panel_info.lcdc.v_pulse_width);
1098 msm_fb_debugfs_file_create(sub_dir,
1099 "border_clr",
1100 (u32 *) &mfd->panel_info.lcdc.border_clr);
1101 msm_fb_debugfs_file_create(sub_dir,
1102 "underflow_clr",
1103 (u32 *) &mfd->panel_info.lcdc.underflow_clr);
1104 msm_fb_debugfs_file_create(sub_dir,
1105 "hsync_skew",
1106 (u32 *) &mfd->panel_info.lcdc.hsync_skew);
1107 break;
1108
1109 default:
1110 break;
1111 }
1112 }
1113 }
1114#endif /* MSM_FB_ENABLE_DBGFS */
1115
1116 return ret;
1117}
1118
1119static int msm_fb_open(struct fb_info *info, int user)
1120{
1121 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
1122
1123 if (!mfd->ref_cnt) {
1124 mdp_set_dma_pan_info(info, NULL, TRUE);
1125
1126 if (msm_fb_blank_sub(FB_BLANK_UNBLANK, info, mfd->op_enable)) {
1127 printk(KERN_ERR "msm_fb_open: can't turn on display!\n");
1128 return -1;
1129 }
1130 }
1131
1132 mfd->ref_cnt++;
1133 return 0;
1134}
1135
1136static int msm_fb_release(struct fb_info *info, int user)
1137{
1138 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
1139 int ret = 0;
1140
1141 if (!mfd->ref_cnt) {
1142 MSM_FB_INFO("msm_fb_release: try to close unopened fb %d!\n",
1143 mfd->index);
1144 return -EINVAL;
1145 }
1146
1147 mfd->ref_cnt--;
1148
1149 if (!mfd->ref_cnt) {
1150 if ((ret =
1151 msm_fb_blank_sub(FB_BLANK_POWERDOWN, info,
1152 mfd->op_enable)) != 0) {
1153 printk(KERN_ERR "msm_fb_release: can't turn off display!\n");
1154 return ret;
1155 }
1156 }
1157
1158 return ret;
1159}
1160
1161DECLARE_MUTEX(msm_fb_pan_sem);
1162
1163static int msm_fb_pan_display(struct fb_var_screeninfo *var,
1164 struct fb_info *info)
1165{
1166 struct mdp_dirty_region dirty;
1167 struct mdp_dirty_region *dirtyPtr = NULL;
1168 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
1169
1170 if ((!mfd->op_enable) || (!mfd->panel_power_on))
1171 return -EPERM;
1172
1173 if (var->xoffset > (info->var.xres_virtual - info->var.xres))
1174 return -EINVAL;
1175
1176 if (var->yoffset > (info->var.yres_virtual - info->var.yres))
1177 return -EINVAL;
1178
1179 if (info->fix.xpanstep)
1180 info->var.xoffset =
1181 (var->xoffset / info->fix.xpanstep) * info->fix.xpanstep;
1182
1183 if (info->fix.ypanstep)
1184 info->var.yoffset =
1185 (var->yoffset / info->fix.ypanstep) * info->fix.ypanstep;
1186
1187 /* "UPDT" */
1188 if (var->reserved[0] == 0x54445055) {
1189 dirty.xoffset = var->reserved[1] & 0xffff;
1190 dirty.yoffset = (var->reserved[1] >> 16) & 0xffff;
1191
1192 if ((var->reserved[2] & 0xffff) <= dirty.xoffset)
1193 return -EINVAL;
1194 if (((var->reserved[2] >> 16) & 0xffff) <= dirty.yoffset)
1195 return -EINVAL;
1196
1197 dirty.width = (var->reserved[2] & 0xffff) - dirty.xoffset;
1198 dirty.height =
1199 ((var->reserved[2] >> 16) & 0xffff) - dirty.yoffset;
1200 info->var.yoffset = var->yoffset;
1201
1202 if (dirty.xoffset < 0)
1203 return -EINVAL;
1204
1205 if (dirty.yoffset < 0)
1206 return -EINVAL;
1207
1208 if ((dirty.xoffset + dirty.width) > info->var.xres)
1209 return -EINVAL;
1210
1211 if ((dirty.yoffset + dirty.height) > info->var.yres)
1212 return -EINVAL;
1213
1214 if ((dirty.width <= 0) || (dirty.height <= 0))
1215 return -EINVAL;
1216
1217 dirtyPtr = &dirty;
1218 }
1219
1220 /* Flip */
1221 /* A constant value is used to indicate that we should change the DMA
1222 output buffer instead of just panning */
1223
1224 if (var->reserved[0] == 0x466c6970) {
1225 unsigned long length, address;
1226 struct file *p_src_file;
1227 struct mdp_img imgdata;
1228 int bpp;
1229
1230 if (mfd->allow_set_offset) {
1231 imgdata.memory_id = var->reserved[1];
1232 imgdata.priv = var->reserved[2];
1233
1234 /* If there is no memory ID then we want to reset back
1235 to the original fb visibility */
1236 if (var->reserved[1]) {
1237 if (var->reserved[4] == MDP_BLIT_SRC_GEM) {
1238 panic("waaaaaaaaaaaaaah");
1239 if ( /*get_gem_img(&imgdata,
1240 (unsigned long *) &address,
1241 &length)*/ -1 < 0) {
1242 return -1;
1243 }
1244 } else {
1245 /*get_img(&imgdata, info, &address,
1246 &length, &p_src_file);*/
1247 panic("waaaaaah");
1248 }
1249 mfd->ibuf.visible_swapped = TRUE;
1250 } else {
1251 /* Flip back to the original address
1252 adjusted for xoffset and yoffset */
1253
1254 bpp = info->var.bits_per_pixel / 8;
1255 address = (unsigned long) info->fix.smem_start;
1256 address += info->var.xoffset * bpp +
1257 info->var.yoffset * info->fix.line_length;
1258
1259 mfd->ibuf.visible_swapped = FALSE;
1260 }
1261
1262 mdp_set_offset_info(info, address,
1263 (var->activate == FB_ACTIVATE_VBL));
1264
1265 mfd->dma_fnc(mfd);
1266 return 0;
1267 } else
1268 return -EINVAL;
1269 }
1270
1271 down(&msm_fb_pan_sem);
1272 mdp_set_dma_pan_info(info, dirtyPtr,
1273 (var->activate == FB_ACTIVATE_VBL));
1274 mdp_dma_pan_update(info);
1275 up(&msm_fb_pan_sem);
1276
1277 ++mfd->panel_info.frame_count;
1278 return 0;
1279}
1280
1281static int msm_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1282{
1283 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
1284
1285 if (var->rotate != FB_ROTATE_UR)
1286 return -EINVAL;
1287 if (var->grayscale != info->var.grayscale)
1288 return -EINVAL;
1289
1290 switch (var->bits_per_pixel) {
1291 case 16:
1292 if ((var->green.offset != 5) ||
1293 !((var->blue.offset == 11)
1294 || (var->blue.offset == 0)) ||
1295 !((var->red.offset == 11)
1296 || (var->red.offset == 0)) ||
1297 (var->blue.length != 5) ||
1298 (var->green.length != 6) ||
1299 (var->red.length != 5) ||
1300 (var->blue.msb_right != 0) ||
1301 (var->green.msb_right != 0) ||
1302 (var->red.msb_right != 0) ||
1303 (var->transp.offset != 0) ||
1304 (var->transp.length != 0))
1305 return -EINVAL;
1306 break;
1307
1308 case 24:
1309 if ((var->blue.offset != 0) ||
1310 (var->green.offset != 8) ||
1311 (var->red.offset != 16) ||
1312 (var->blue.length != 8) ||
1313 (var->green.length != 8) ||
1314 (var->red.length != 8) ||
1315 (var->blue.msb_right != 0) ||
1316 (var->green.msb_right != 0) ||
1317 (var->red.msb_right != 0) ||
1318 !(((var->transp.offset == 0) &&
1319 (var->transp.length == 0)) ||
1320 ((var->transp.offset == 24) &&
1321 (var->transp.length == 8))))
1322 return -EINVAL;
1323 break;
1324
1325 default:
1326 return -EINVAL;
1327 }
1328
1329 if ((var->xres_virtual <= 0) || (var->yres_virtual <= 0))
1330 return -EINVAL;
1331
1332 if (info->fix.smem_len <
1333 (var->xres_virtual*var->yres_virtual*(var->bits_per_pixel/8)))
1334 return -EINVAL;
1335
1336 if ((var->xres == 0) || (var->yres == 0))
1337 return -EINVAL;
1338
1339 if ((var->xres > mfd->panel_info.xres) ||
1340 (var->yres > mfd->panel_info.yres))
1341 return -EINVAL;
1342
1343 if (var->xoffset > (var->xres_virtual - var->xres))
1344 return -EINVAL;
1345
1346 if (var->yoffset > (var->yres_virtual - var->yres))
1347 return -EINVAL;
1348
1349 return 0;
1350}
1351
1352static int msm_fb_set_par(struct fb_info *info)
1353{
1354 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
1355 struct fb_var_screeninfo *var = &info->var;
1356 int old_imgType;
1357 int blank = 0;
1358
1359 old_imgType = mfd->fb_imgType;
1360 switch (var->bits_per_pixel) {
1361 case 16:
1362 if (var->red.offset == 0)
1363 mfd->fb_imgType = MDP_BGR_565;
1364 else
1365 mfd->fb_imgType = MDP_RGB_565;
1366 break;
1367
1368 case 24:
1369 if ((var->transp.offset == 0) && (var->transp.length == 0))
1370 mfd->fb_imgType = MDP_RGB_888;
1371 else if ((var->transp.offset == 24) &&
1372 (var->transp.length == 8)) {
1373 mfd->fb_imgType = MDP_ARGB_8888;
1374 info->var.bits_per_pixel = 32;
1375 }
1376 break;
1377
1378 default:
1379 return -EINVAL;
1380 }
1381
1382 if ((mfd->var_pixclock != var->pixclock) ||
1383 (mfd->hw_refresh && ((mfd->fb_imgType != old_imgType) ||
1384 (mfd->var_pixclock != var->pixclock) ||
1385 (mfd->var_xres != var->xres) ||
1386 (mfd->var_yres != var->yres)))) {
1387 mfd->var_xres = var->xres;
1388 mfd->var_yres = var->yres;
1389 mfd->var_pixclock = var->pixclock;
1390 blank = 1;
1391 }
1392
1393 if (blank) {
1394 msm_fb_blank_sub(FB_BLANK_POWERDOWN, info, mfd->op_enable);
1395 msm_fb_blank_sub(FB_BLANK_UNBLANK, info, mfd->op_enable);
1396 }
1397
1398 return 0;
1399}
1400
1401static int msm_fb_stop_sw_refresher(struct msm_fb_data_type *mfd)
1402{
1403 if (mfd->hw_refresh)
1404 return -EPERM;
1405
1406 if (mfd->sw_currently_refreshing) {
1407 down(&mfd->sem);
1408 mfd->sw_currently_refreshing = FALSE;
1409 up(&mfd->sem);
1410
1411 /* wait until the refresher finishes the last job */
1412 wait_for_completion_killable(&mfd->refresher_comp);
1413 }
1414
1415 return 0;
1416}
1417
1418int msm_fb_resume_sw_refresher(struct msm_fb_data_type *mfd)
1419{
1420 boolean do_refresh;
1421
1422 if (mfd->hw_refresh)
1423 return -EPERM;
1424
1425 down(&mfd->sem);
1426 if ((!mfd->sw_currently_refreshing) && (mfd->sw_refreshing_enable)) {
1427 do_refresh = TRUE;
1428 mfd->sw_currently_refreshing = TRUE;
1429 } else {
1430 do_refresh = FALSE;
1431 }
1432 up(&mfd->sem);
1433
1434 if (do_refresh)
1435 mdp_refresh_screen((unsigned long)mfd);
1436
1437 return 0;
1438}
1439
1440void mdp_ppp_put_img(struct file *p_src_file, struct file *p_dst_file)
1441{
1442#ifdef CONFIG_ANDROID_PMEM
1443 if (p_src_file)
1444 put_pmem_file(p_src_file);
1445 if (p_dst_file)
1446 put_pmem_file(p_dst_file);
1447#endif
1448}
1449
1450int mdp_blit(struct fb_info *info, struct mdp_blit_req *req)
1451{
1452 int ret;
1453 struct file *p_src_file = 0, *p_dst_file = 0;
1454 if (unlikely(req->src_rect.h == 0 || req->src_rect.w == 0)) {
1455 printk(KERN_ERR "mpd_ppp: src img of zero size!\n");
1456 return -EINVAL;
1457 }
1458 if (unlikely(req->dst_rect.h == 0 || req->dst_rect.w == 0))
1459 return 0;
1460
1461 ret = mdp_ppp_blit(info, req, &p_src_file, &p_dst_file);
1462 mdp_ppp_put_img(p_src_file, p_dst_file);
1463 return ret;
1464}
1465
1466typedef void (*msm_dma_barrier_function_pointer) (void *, size_t);
1467
1468static inline void msm_fb_dma_barrier_for_rect(struct fb_info *info,
1469 struct mdp_img *img, struct mdp_rect *rect,
1470 msm_dma_barrier_function_pointer dma_barrier_fp
1471 )
1472{
1473 /*
1474 * Compute the start and end addresses of the rectangles.
1475 * NOTE: As currently implemented, the data between
1476 * the end of one row and the start of the next is
1477 * included in the address range rather than
1478 * doing multiple calls for each row.
1479 */
1480
1481 char * const pmem_start = info->screen_base;
1482/* int bytes_per_pixel = mdp_get_bytes_per_pixel(img->format);
1483 unsigned long start = (unsigned long)pmem_start + img->offset +
1484 (img->width * rect->y + rect->x) * bytes_per_pixel;
1485 size_t size = ((rect->h - 1) * img->width + rect->w) * bytes_per_pixel;
1486 (*dma_barrier_fp) ((void *) start, size);
1487*/
1488 panic("waaaaah");
1489}
1490
1491static inline void msm_dma_nc_pre(void)
1492{
1493 dmb();
1494}
1495static inline void msm_dma_wt_pre(void)
1496{
1497 dmb();
1498}
1499static inline void msm_dma_todevice_wb_pre(void *start, size_t size)
1500{
1501 #warning this
1502// dma_cache_pre_ops(start, size, DMA_TO_DEVICE);
1503}
1504
1505static inline void msm_dma_fromdevice_wb_pre(void *start, size_t size)
1506{
1507 #warning this
1508// dma_cache_pre_ops(start, size, DMA_FROM_DEVICE);
1509}
1510
1511static inline void msm_dma_nc_post(void)
1512{
1513 dmb();
1514}
1515
1516static inline void msm_dma_fromdevice_wt_post(void *start, size_t size)
1517{
1518 #warning this
1519// dma_cache_post_ops(start, size, DMA_FROM_DEVICE);
1520}
1521
1522static inline void msm_dma_todevice_wb_post(void *start, size_t size)
1523{
1524 #warning this
1525// dma_cache_post_ops(start, size, DMA_TO_DEVICE);
1526}
1527
1528static inline void msm_dma_fromdevice_wb_post(void *start, size_t size)
1529{
1530 #warning this
1531// dma_cache_post_ops(start, size, DMA_FROM_DEVICE);
1532}
1533
1534/*
1535 * Do the write barriers required to guarantee data is committed to RAM
1536 * (from CPU cache or internal buffers) before a DMA operation starts.
1537 * NOTE: As currently implemented, the data between
1538 * the end of one row and the start of the next is
1539 * included in the address range rather than
1540 * doing multiple calls for each row.
1541*/
1542static void msm_fb_ensure_memory_coherency_before_dma(struct fb_info *info,
1543 struct mdp_blit_req *req_list,
1544 int req_list_count)
1545{
1546#ifdef CONFIG_ARCH_QSD8X50
1547 int i;
1548
1549 /*
1550 * Normally, do the requested barriers for each address
1551 * range that corresponds to a rectangle.
1552 *
1553 * But if at least one write barrier is requested for data
1554 * going to or from the device but no address range is
1555 * needed for that barrier, then do the barrier, but do it
1556 * only once, no matter how many requests there are.
1557 */
1558 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
1559 switch (mfd->mdp_fb_page_protection) {
1560 default:
1561 case MDP_FB_PAGE_PROTECTION_NONCACHED:
1562 case MDP_FB_PAGE_PROTECTION_WRITECOMBINE:
1563 /*
1564 * The following barrier is only done at most once,
1565 * since further calls would be redundant.
1566 */
1567 for (i = 0; i < req_list_count; i++) {
1568 if (!(req_list[i].flags
1569 & MDP_NO_DMA_BARRIER_START)) {
1570 msm_dma_nc_pre();
1571 break;
1572 }
1573 }
1574 break;
1575
1576 case MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE:
1577 /*
1578 * The following barrier is only done at most once,
1579 * since further calls would be redundant.
1580 */
1581 for (i = 0; i < req_list_count; i++) {
1582 if (!(req_list[i].flags
1583 & MDP_NO_DMA_BARRIER_START)) {
1584 msm_dma_wt_pre();
1585 break;
1586 }
1587 }
1588 break;
1589
1590 case MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE:
1591 case MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE:
1592 for (i = 0; i < req_list_count; i++) {
1593 if (!(req_list[i].flags &
1594 MDP_NO_DMA_BARRIER_START)) {
1595
1596 msm_fb_dma_barrier_for_rect(info,
1597 &(req_list[i].src),
1598 &(req_list[i].src_rect),
1599 msm_dma_todevice_wb_pre
1600 );
1601
1602 msm_fb_dma_barrier_for_rect(info,
1603 &(req_list[i].dst),
1604 &(req_list[i].dst_rect),
1605 msm_dma_todevice_wb_pre
1606 );
1607 }
1608 }
1609 break;
1610 }
1611#else
1612 dmb();
1613#endif
1614}
1615
1616
1617/*
1618 * Do the write barriers required to guarantee data will be re-read from RAM by
1619 * the CPU after a DMA operation ends.
1620 * NOTE: As currently implemented, the data between
1621 * the end of one row and the start of the next is
1622 * included in the address range rather than
1623 * doing multiple calls for each row.
1624*/
1625static void msm_fb_ensure_memory_coherency_after_dma(struct fb_info *info,
1626 struct mdp_blit_req *req_list,
1627 int req_list_count)
1628{
1629#ifdef CONFIG_ARCH_QSD8X50
1630 int i;
1631
1632 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
1633 switch (mfd->mdp_fb_page_protection) {
1634 default:
1635 case MDP_FB_PAGE_PROTECTION_NONCACHED:
1636 case MDP_FB_PAGE_PROTECTION_WRITECOMBINE:
1637 /*
1638 * The following barrier is only done at most once,
1639 * since further calls would be redundant.
1640 */
1641 for (i = 0; i < req_list_count; i++) {
1642 if (!(req_list[i].flags
1643 & MDP_NO_DMA_BARRIER_END)) {
1644 msm_dma_nc_post();
1645 break;
1646 }
1647 }
1648 break;
1649
1650 case MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE:
1651 for (i = 0; i < req_list_count; i++) {
1652 if (!(req_list[i].flags &
1653 MDP_NO_DMA_BARRIER_END)) {
1654
1655 msm_fb_dma_barrier_for_rect(info,
1656 &(req_list[i].dst),
1657 &(req_list[i].dst_rect),
1658 msm_dma_fromdevice_wt_post
1659 );
1660 }
1661 }
1662 break;
1663 case MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE:
1664 case MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE:
1665 for (i = 0; i < req_list_count; i++) {
1666 if (!(req_list[i].flags &
1667 MDP_NO_DMA_BARRIER_END)) {
1668
1669 msm_fb_dma_barrier_for_rect(info,
1670 &(req_list[i].dst),
1671 &(req_list[i].dst_rect),
1672 msm_dma_fromdevice_wb_post
1673 );
1674 }
1675 }
1676 break;
1677 }
1678#else
1679 dmb();
1680#endif
1681}
1682
1683#ifdef CONFIG_MDP_PPP_ASYNC_OP
1684void msm_fb_ensure_mem_coherency_after_dma(struct fb_info *info,
1685 struct mdp_blit_req *req_list, int req_list_count)
1686{
1687 BUG_ON(!info);
1688
1689 /*
1690 * Ensure that CPU cache and other internal CPU state is
1691 * updated to reflect any change in memory modified by MDP blit
1692 * DMA.
1693 */
1694 msm_fb_ensure_memory_coherency_after_dma(info,
1695 req_list, req_list_count);
1696}
1697
1698static int msmfb_async_blit(struct fb_info *info, void __user *p)
1699{
1700 /*
1701 * CAUTION: The names of the struct types intentionally *DON'T* match
1702 * the names of the variables declared -- they appear to be swapped.
1703 * Read the code carefully and you should see that the variable names
1704 * make sense.
1705 */
1706 const int MAX_LIST_WINDOW = 16;
1707 struct mdp_blit_req req_list[MAX_LIST_WINDOW];
1708 struct mdp_blit_req_list req_list_header;
1709
1710 int count, i, req_list_count;
1711
1712 /* Get the count size for the total BLIT request. */
1713 if (copy_from_user(&req_list_header, p, sizeof(req_list_header)))
1714 return -EFAULT;
1715 p += sizeof(req_list_header);
1716 count = req_list_header.count;
1717 while (count > 0) {
1718 /*
1719 * Access the requests through a narrow window to decrease copy
1720 * overhead and make larger requests accessible to the
1721 * coherency management code.
1722 * NOTE: The window size is intended to be larger than the
1723 * typical request size, but not require more than 2
1724 * kbytes of stack storage.
1725 */
1726 req_list_count = count;
1727 if (req_list_count > MAX_LIST_WINDOW)
1728 req_list_count = MAX_LIST_WINDOW;
1729 if (copy_from_user(&req_list, p,
1730 sizeof(struct mdp_blit_req)*req_list_count))
1731 return -EFAULT;
1732
1733 /*
1734 * Ensure that any data CPU may have previously written to
1735 * internal state (but not yet committed to memory) is
1736 * guaranteed to be committed to memory now.
1737 */
1738 msm_fb_ensure_memory_coherency_before_dma(info,
1739 req_list, req_list_count);
1740
1741 /*
1742 * Do the blit DMA, if required -- returning early only if
1743 * there is a failure.
1744 */
1745 for (i = 0; i < req_list_count; i++) {
1746 if (!(req_list[i].flags & MDP_NO_BLIT)) {
1747 int ret = 0;
1748 struct mdp_ppp_djob *job = NULL;
1749
1750 if (unlikely(req_list[i].src_rect.h == 0 ||
1751 req_list[i].src_rect.w == 0)) {
1752 MSM_FB_ERR("mpd_ppp: "
1753 "src img of zero size!\n");
1754 return -EINVAL;
1755 }
1756
1757 if (unlikely(req_list[i].dst_rect.h == 0 ||
1758 req_list[i].dst_rect.w == 0))
1759 continue;
1760
1761 /* create a new display job */
1762 job = mdp_ppp_new_djob();
1763 if (unlikely(!job))
1764 return -ENOMEM;
1765
1766 job->info = info;
1767 memcpy(&job->req, &req_list[i],
1768 sizeof(struct mdp_blit_req));
1769
1770 /* Do the actual blit. */
1771 ret = mdp_ppp_blit(info, &job->req,
1772 &job->p_src_file, &job->p_dst_file);
1773
1774 /*
1775 * Note that early returns don't guarantee
1776 * memory coherency.
1777 */
1778 if (ret || mdp_ppp_get_ret_code()) {
1779 mdp_ppp_clear_curr_djob();
1780 return ret;
1781 }
1782 }
1783 }
1784
1785 /* Go to next window of requests. */
1786 count -= req_list_count;
1787 p += sizeof(struct mdp_blit_req)*req_list_count;
1788 }
1789 return 0;
1790}
1791#else
1792
1793/*
1794 * NOTE: The userspace issues blit operations in a sequence, the sequence
1795 * start with a operation marked START and ends in an operation marked
1796 * END. It is guranteed by the userspace that all the blit operations
1797 * between START and END are only within the regions of areas designated
1798 * by the START and END operations and that the userspace doesnt modify
1799 * those areas. Hence it would be enough to perform barrier/cache operations
1800 * only on the START and END operations.
1801 */
1802static int msmfb_blit(struct fb_info *info, void __user *p)
1803{
1804 /*
1805 * CAUTION: The names of the struct types intentionally *DON'T* match
1806 * the names of the variables declared -- they appear to be swapped.
1807 * Read the code carefully and you should see that the variable names
1808 * make sense.
1809 */
1810 const int MAX_LIST_WINDOW = 16;
1811 struct mdp_blit_req req_list[MAX_LIST_WINDOW];
1812 struct mdp_blit_req_list req_list_header;
1813
1814 int count, i, req_list_count;
1815
1816 /* Get the count size for the total BLIT request. */
1817 if (copy_from_user(&req_list_header, p, sizeof(req_list_header)))
1818 return -EFAULT;
1819 p += sizeof(req_list_header);
1820 count = req_list_header.count;
1821 while (count > 0) {
1822 /*
1823 * Access the requests through a narrow window to decrease copy
1824 * overhead and make larger requests accessible to the
1825 * coherency management code.
1826 * NOTE: The window size is intended to be larger than the
1827 * typical request size, but not require more than 2
1828 * kbytes of stack storage.
1829 */
1830 req_list_count = count;
1831 if (req_list_count > MAX_LIST_WINDOW)
1832 req_list_count = MAX_LIST_WINDOW;
1833 if (copy_from_user(&req_list, p,
1834 sizeof(struct mdp_blit_req)*req_list_count))
1835 return -EFAULT;
1836
1837 /*
1838 * Ensure that any data CPU may have previously written to
1839 * internal state (but not yet committed to memory) is
1840 * guaranteed to be committed to memory now.
1841 */
1842 msm_fb_ensure_memory_coherency_before_dma(info,
1843 req_list, req_list_count);
1844
1845 /*
1846 * Do the blit DMA, if required -- returning early only if
1847 * there is a failure.
1848 */
1849 for (i = 0; i < req_list_count; i++) {
1850 if (!(req_list[i].flags & MDP_NO_BLIT)) {
1851 /* Do the actual blit. */
1852 int ret = mdp_blit(info, &(req_list[i]));
1853
1854 /*
1855 * Note that early returns don't guarantee
1856 * memory coherency.
1857 */
1858 if (ret)
1859 return ret;
1860 }
1861 }
1862
1863 /*
1864 * Ensure that CPU cache and other internal CPU state is
1865 * updated to reflect any change in memory modified by MDP blit
1866 * DMA.
1867 */
1868 msm_fb_ensure_memory_coherency_after_dma(info,
1869 req_list,
1870 req_list_count);
1871
1872 /* Go to next window of requests. */
1873 count -= req_list_count;
1874 p += sizeof(struct mdp_blit_req)*req_list_count;
1875 }
1876 return 0;
1877}
1878#endif
1879
1880#ifdef CONFIG_FB_MSM_OVERLAY
1881static int msmfb_overlay_get(struct fb_info *info, void __user *p)
1882{
1883 struct mdp_overlay req;
1884 int ret;
1885
1886 if (copy_from_user(&req, p, sizeof(req)))
1887 return -EFAULT;
1888
1889 ret = mdp4_overlay_get(info, &req);
1890 if (ret) {
1891 printk(KERN_ERR "%s: ioctl failed \n",
1892 __func__);
1893 return ret;
1894 }
1895 if (copy_to_user(p, &req, sizeof(req))) {
1896 printk(KERN_ERR "%s: copy2user failed \n",
1897 __func__);
1898 return -EFAULT;
1899 }
1900
1901 return 0;
1902}
1903
1904static int msmfb_overlay_set(struct fb_info *info, void __user *p)
1905{
1906 struct mdp_overlay req;
1907 int ret;
1908
1909 if (copy_from_user(&req, p, sizeof(req)))
1910 return -EFAULT;
1911
1912 ret = mdp4_overlay_set(info, &req);
1913 if (ret) {
1914 printk(KERN_ERR "%s:ioctl failed \n",
1915 __func__);
1916 return ret;
1917 }
1918
1919 if (copy_to_user(p, &req, sizeof(req))) {
1920 printk(KERN_ERR "%s: copy2user failed \n",
1921 __func__);
1922 return -EFAULT;
1923 }
1924
1925 return 0;
1926}
1927
1928static int msmfb_overlay_unset(struct fb_info *info, unsigned long *argp)
1929{
1930 int ret, ndx;
1931
1932 ret = copy_from_user(&ndx, argp, sizeof(ndx));
1933 if (ret) {
1934 printk(KERN_ERR "%s:msmfb_overlay_unset ioctl failed \n",
1935 __func__);
1936 return ret;
1937 }
1938
1939 return mdp4_overlay_unset(info, ndx);
1940}
1941
1942static int msmfb_overlay_play(struct fb_info *info, unsigned long *argp)
1943{
1944 int ret;
1945 struct msmfb_overlay_data req;
1946 struct file *p_src_file = 0;
1947
1948 ret = copy_from_user(&req, argp, sizeof(req));
1949 if (ret) {
1950 printk(KERN_ERR "%s:msmfb_overlay_play ioctl failed \n",
1951 __func__);
1952 return ret;
1953 }
1954
1955 ret = mdp4_overlay_play(info, &req, &p_src_file);
1956
1957 if (p_src_file)
1958 put_pmem_file(p_src_file);
1959
1960 return ret;
1961}
1962
1963#endif
1964
1965DECLARE_MUTEX(msm_fb_ioctl_ppp_sem);
1966DEFINE_MUTEX(msm_fb_ioctl_lut_sem);
1967DEFINE_MUTEX(msm_fb_ioctl_hist_sem);
1968
1969/* Set color conversion matrix from user space */
1970
1971#ifndef CONFIG_FB_MSM_MDP40
1972static void msmfb_set_color_conv(struct mdp_ccs *p)
1973{
1974 int i;
1975
1976 if (p->direction == MDP_CCS_RGB2YUV) {
1977 /* MDP cmd block enable */
1978 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
1979
1980 /* RGB->YUV primary forward matrix */
1981 for (i = 0; i < MDP_CCS_SIZE; i++)
1982 writel(p->ccs[i], MDP_CSC_PFMVn(i));
1983
1984 #ifdef CONFIG_FB_MSM_MDP31
1985 for (i = 0; i < MDP_BV_SIZE; i++)
1986 writel(p->bv[i], MDP_CSC_POST_BV2n(i));
1987 #endif
1988
1989 /* MDP cmd block disable */
1990 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
1991 } else {
1992 /* MDP cmd block enable */
1993 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
1994
1995 /* YUV->RGB primary reverse matrix */
1996 for (i = 0; i < MDP_CCS_SIZE; i++)
1997 writel(p->ccs[i], MDP_CSC_PRMVn(i));
1998 for (i = 0; i < MDP_BV_SIZE; i++)
1999 writel(p->bv[i], MDP_CSC_PRE_BV1n(i));
2000
2001 /* MDP cmd block disable */
2002 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
2003 }
2004}
2005#endif
2006
2007
2008static int msm_fb_ioctl(struct fb_info *info, unsigned int cmd,
2009 unsigned long arg)
2010{
2011 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
2012 void __user *argp = (void __user *)arg;
2013 struct fb_cursor cursor;
2014 struct fb_cmap cmap;
2015 struct mdp_histogram hist;
2016#ifndef CONFIG_FB_MSM_MDP40
2017 struct mdp_ccs ccs_matrix;
2018#endif
2019 struct mdp_page_protection fb_page_protection;
2020 int ret = 0;
2021
2022 if (!mfd->op_enable)
2023 return -EPERM;
2024
2025 switch (cmd) {
2026#ifdef CONFIG_FB_MSM_OVERLAY
2027 case MSMFB_OVERLAY_GET:
2028 down(&msm_fb_ioctl_ppp_sem);
2029 ret = msmfb_overlay_get(info, argp);
2030 up(&msm_fb_ioctl_ppp_sem);
2031 break;
2032 case MSMFB_OVERLAY_SET:
2033 down(&msm_fb_ioctl_ppp_sem);
2034 ret = msmfb_overlay_set(info, argp);
2035 up(&msm_fb_ioctl_ppp_sem);
2036 break;
2037 case MSMFB_OVERLAY_UNSET:
2038 down(&msm_fb_ioctl_ppp_sem);
2039 ret = msmfb_overlay_unset(info, argp);
2040 up(&msm_fb_ioctl_ppp_sem);
2041 break;
2042 case MSMFB_OVERLAY_PLAY:
2043 down(&msm_fb_ioctl_ppp_sem);
2044 ret = msmfb_overlay_play(info, argp);
2045 up(&msm_fb_ioctl_ppp_sem);
2046 break;
2047#endif
2048 case MSMFB_BLIT:
2049 down(&msm_fb_ioctl_ppp_sem);
2050#ifdef CONFIG_MDP_PPP_ASYNC_OP
2051 ret = msmfb_async_blit(info, argp);
2052 mdp_ppp_wait(); /* Wait for all blits to be finished. */
2053#else
2054 ret = msmfb_blit(info, argp);
2055#endif
2056 up(&msm_fb_ioctl_ppp_sem);
2057
2058 break;
2059
2060 /* Ioctl for setting ccs matrix from user space */
2061 case MSMFB_SET_CCS_MATRIX:
2062#ifndef CONFIG_FB_MSM_MDP40
2063 ret = copy_from_user(&ccs_matrix, argp, sizeof(ccs_matrix));
2064 if (ret) {
2065 printk(KERN_ERR
2066 "%s:MSMFB_SET_CCS_MATRIX ioctl failed \n",
2067 __func__);
2068 return ret;
2069 }
2070
2071 down(&msm_fb_ioctl_ppp_sem);
2072 if (ccs_matrix.direction == MDP_CCS_RGB2YUV)
2073 mdp_ccs_rgb2yuv = ccs_matrix;
2074 else
2075 mdp_ccs_yuv2rgb = ccs_matrix;
2076
2077 msmfb_set_color_conv(&ccs_matrix) ;
2078 up(&msm_fb_ioctl_ppp_sem);
2079#else
2080 ret = -EINVAL;
2081#endif
2082
2083 break;
2084
2085 /* Ioctl for getting ccs matrix to user space */
2086 case MSMFB_GET_CCS_MATRIX:
2087#ifndef CONFIG_FB_MSM_MDP40
2088 ret = copy_from_user(&ccs_matrix, argp, sizeof(ccs_matrix)) ;
2089 if (ret) {
2090 printk(KERN_ERR
2091 "%s:MSMFB_GET_CCS_MATRIX ioctl failed \n",
2092 __func__);
2093 return ret;
2094 }
2095
2096 down(&msm_fb_ioctl_ppp_sem);
2097 if (ccs_matrix.direction == MDP_CCS_RGB2YUV)
2098 ccs_matrix = mdp_ccs_rgb2yuv;
2099 else
2100 ccs_matrix = mdp_ccs_yuv2rgb;
2101
2102 ret = copy_to_user(argp, &ccs_matrix, sizeof(ccs_matrix));
2103
2104 if (ret) {
2105 printk(KERN_ERR
2106 "%s:MSMFB_GET_CCS_MATRIX ioctl failed \n",
2107 __func__);
2108 return ret ;
2109 }
2110 up(&msm_fb_ioctl_ppp_sem);
2111#else
2112 ret = -EINVAL;
2113#endif
2114
2115 break;
2116
2117#ifdef CONFIG_MDP_PPP_ASYNC_OP
2118 case MSMFB_ASYNC_BLIT:
2119 down(&msm_fb_ioctl_ppp_sem);
2120 ret = msmfb_async_blit(info, argp);
2121 up(&msm_fb_ioctl_ppp_sem);
2122 break;
2123
2124 case MSMFB_BLIT_FLUSH:
2125 down(&msm_fb_ioctl_ppp_sem);
2126 mdp_ppp_wait();
2127 up(&msm_fb_ioctl_ppp_sem);
2128 break;
2129#endif
2130
2131 case MSMFB_GRP_DISP:
2132#ifdef CONFIG_FB_MSM_MDP22
2133 {
2134 unsigned long grp_id;
2135
2136 ret = copy_from_user(&grp_id, argp, sizeof(grp_id));
2137 if (ret)
2138 return ret;
2139
2140 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
2141 writel(grp_id, MDP_FULL_BYPASS_WORD43);
2142 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF,
2143 FALSE);
2144 break;
2145 }
2146#else
2147 return -EFAULT;
2148#endif
2149 case MSMFB_SUSPEND_SW_REFRESHER:
2150 if (!mfd->panel_power_on)
2151 return -EPERM;
2152
2153 mfd->sw_refreshing_enable = FALSE;
2154 ret = msm_fb_stop_sw_refresher(mfd);
2155 break;
2156
2157 case MSMFB_RESUME_SW_REFRESHER:
2158 if (!mfd->panel_power_on)
2159 return -EPERM;
2160
2161 mfd->sw_refreshing_enable = TRUE;
2162 ret = msm_fb_resume_sw_refresher(mfd);
2163 break;
2164
2165 case MSMFB_CURSOR:
2166 ret = copy_from_user(&cursor, argp, sizeof(cursor));
2167 if (ret)
2168 return ret;
2169
2170 ret = msm_fb_cursor(info, &cursor);
2171 break;
2172
2173 case MSMFB_SET_LUT:
2174 ret = copy_from_user(&cmap, argp, sizeof(cmap));
2175 if (ret)
2176 return ret;
2177
2178 mutex_lock(&msm_fb_ioctl_lut_sem);
2179 ret = msm_fb_set_lut(&cmap, info);
2180 mutex_unlock(&msm_fb_ioctl_lut_sem);
2181 break;
2182
2183 case MSMFB_HISTOGRAM:
2184 if (!mfd->do_histogram)
2185 return -ENODEV;
2186
2187 ret = copy_from_user(&hist, argp, sizeof(hist));
2188 if (ret)
2189 return ret;
2190
2191 mutex_lock(&msm_fb_ioctl_hist_sem);
2192 ret = mfd->do_histogram(info, &hist);
2193 mutex_unlock(&msm_fb_ioctl_hist_sem);
2194 break;
2195
2196 case MSMFB_GET_PAGE_PROTECTION:
2197 fb_page_protection.page_protection
2198 = mfd->mdp_fb_page_protection;
2199 ret = copy_to_user(argp, &fb_page_protection,
2200 sizeof(fb_page_protection));
2201 if (ret)
2202 return ret;
2203 break;
2204
2205 case MSMFB_SET_PAGE_PROTECTION:
2206#ifdef CONFIG_ARCH_QSD8X50
2207 ret = copy_from_user(&fb_page_protection, argp,
2208 sizeof(fb_page_protection));
2209 if (ret)
2210 return ret;
2211
2212 /* Validate the proposed page protection settings. */
2213 switch (fb_page_protection.page_protection) {
2214 case MDP_FB_PAGE_PROTECTION_NONCACHED:
2215 case MDP_FB_PAGE_PROTECTION_WRITECOMBINE:
2216 case MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE:
2217 /* Write-back cache (read allocate) */
2218 case MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE:
2219 /* Write-back cache (write allocate) */
2220 case MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE:
2221 mfd->mdp_fb_page_protection =
2222 fb_page_protection.page_protection;
2223 break;
2224 default:
2225 ret = -EINVAL;
2226 break;
2227 }
2228#else
2229 /*
2230 * Don't allow caching until 7k DMA cache operations are
2231 * available.
2232 */
2233 ret = -EINVAL;
2234#endif
2235 break;
2236
2237 default:
2238 MSM_FB_INFO("MDP: unknown ioctl (cmd=%d) received!\n", cmd);
2239 ret = -EINVAL;
2240 break;
2241 }
2242
2243 return ret;
2244}
2245
2246static int msm_fb_register_driver(void)
2247{
2248 return platform_driver_register(&msm_fb_driver);
2249}
2250
2251void msm_fb_add_device(struct platform_device *pdev)
2252{
2253 struct msm_fb_panel_data *pdata;
2254 struct platform_device *this_dev = NULL;
2255 struct fb_info *fbi;
2256 struct msm_fb_data_type *mfd = NULL;
2257 u32 type, id, fb_num;
2258
2259 if (!pdev)
2260 return;
2261 id = pdev->id;
2262
2263 pdata = pdev->dev.platform_data;
2264 if (!pdata)
2265 return;
2266 type = pdata->panel_info.type;
2267 fb_num = pdata->panel_info.fb_num;
2268
2269 if (fb_num <= 0)
2270 return;
2271
2272 if (fbi_list_index >= MAX_FBI_LIST) {
2273 printk(KERN_ERR "msm_fb: no more framebuffer info list!\n");
2274 return;
2275 }
2276 /*
2277 * alloc panel device data
2278 */
2279 this_dev = msm_fb_device_alloc(pdata, type, id);
2280
2281 if (!this_dev) {
2282 printk(KERN_ERR
2283 "%s: msm_fb_device_alloc failed!\n", __func__);
2284 return;
2285 }
2286
2287 /*
2288 * alloc framebuffer info + par data
2289 */
2290 fbi = framebuffer_alloc(sizeof(struct msm_fb_data_type), NULL);
2291 if (fbi == NULL) {
2292 platform_device_put(this_dev);
2293 printk(KERN_ERR "msm_fb: can't alloca framebuffer info data!\n");
2294 return;
2295 }
2296
2297 mfd = (struct msm_fb_data_type *)fbi->par;
2298 mfd->key = MFD_KEY;
2299 mfd->fbi = fbi;
2300 mfd->panel.type = type;
2301 mfd->panel.id = id;
2302 mfd->fb_page = fb_num;
2303 mfd->index = fbi_list_index;
2304 mfd->mdp_fb_page_protection = MDP_FB_PAGE_PROTECTION_WRITECOMBINE;
2305
2306 /* link to the latest pdev */
2307 mfd->pdev = this_dev;
2308
2309 mfd_list[mfd_list_index++] = mfd;
2310 fbi_list[fbi_list_index++] = fbi;
2311
2312 /*
2313 * set driver data
2314 */
2315 platform_set_drvdata(this_dev, mfd);
2316
2317 if (platform_device_add(this_dev)) {
2318 printk(KERN_ERR "msm_fb: platform_device_add failed!\n");
2319 platform_device_put(this_dev);
2320 framebuffer_release(fbi);
2321 fbi_list_index--;
2322 return;
2323 }
2324}
2325EXPORT_SYMBOL(msm_fb_add_device);
2326
2327int __init msm_fb_init(void)
2328{
2329 int rc = -ENODEV;
2330
2331 if (msm_fb_register_driver())
2332 return rc;
2333
2334#ifdef MSM_FB_ENABLE_DBGFS
2335 {
2336 struct dentry *root;
2337
2338 if ((root = msm_fb_get_debugfs_root()) != NULL) {
2339 msm_fb_debugfs_file_create(root,
2340 "msm_fb_msg_printing_level",
2341 (u32 *) &msm_fb_msg_level);
2342 msm_fb_debugfs_file_create(root,
2343 "mddi_msg_printing_level",
2344 (u32 *) &mddi_msg_level);
2345 msm_fb_debugfs_file_create(root, "msm_fb_debug_enabled",
2346 (u32 *) &msm_fb_debug_enabled);
2347 }
2348 }
2349#endif
2350
2351 return 0;
2352}
2353
2354module_init(msm_fb_init);
diff --git a/drivers/staging/msm/msm_fb.h b/drivers/staging/msm/msm_fb.h
new file mode 100644
index 000000000000..f93913800475
--- /dev/null
+++ b/drivers/staging/msm/msm_fb.h
@@ -0,0 +1,174 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are met:
5 * * Redistributions of source code must retain the above copyright
6 * notice, this list of conditions and the following disclaimer.
7 * * Redistributions in binary form must reproduce the above copyright
8 * notice, this list of conditions and the following disclaimer in the
9 * documentation and/or other materials provided with the distribution.
10 * * Neither the name of Code Aurora nor
11 * the names of its contributors may be used to endorse or promote
12 * products derived from this software without specific prior written
13 * permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 */
28
29#ifndef MSM_FB_H
30#define MSM_FB_H
31
32#include <linux/module.h>
33#include <linux/kernel.h>
34#include <linux/sched.h>
35#include <linux/time.h>
36#include <linux/init.h>
37#include <linux/interrupt.h>
38#include "linux/proc_fs.h"
39
40#include <mach/hardware.h>
41#include <linux/io.h>
42#include <mach/board.h>
43
44#include <asm/system.h>
45#include <asm/mach-types.h>
46#include <mach/memory.h>
47#include <linux/semaphore.h>
48#include <linux/spinlock.h>
49#include <linux/workqueue.h>
50#include <linux/hrtimer.h>
51
52#include <linux/fb.h>
53
54#ifdef CONFIG_HAS_EARLYSUSPEND
55#include <linux/earlysuspend.h>
56#endif
57
58#include "msm_fb_panel.h"
59#include "mdp.h"
60
61#define MSM_FB_DEFAULT_PAGE_SIZE 2
62#define MFD_KEY 0x11161126
63#define MSM_FB_MAX_DEV_LIST 32
64
65struct disp_info_type_suspend {
66 boolean op_enable;
67 boolean sw_refreshing_enable;
68 boolean panel_power_on;
69};
70
71struct msm_fb_data_type {
72 __u32 key;
73 __u32 index;
74 __u32 ref_cnt;
75 __u32 fb_page;
76
77 panel_id_type panel;
78 struct msm_panel_info panel_info;
79
80 DISP_TARGET dest;
81 struct fb_info *fbi;
82
83 boolean op_enable;
84 uint32 fb_imgType;
85 boolean sw_currently_refreshing;
86 boolean sw_refreshing_enable;
87 boolean hw_refresh;
88
89 MDPIBUF ibuf;
90 boolean ibuf_flushed;
91 struct timer_list refresh_timer;
92 struct completion refresher_comp;
93
94 boolean pan_waiting;
95 struct completion pan_comp;
96
97 /* vsync */
98 boolean use_mdp_vsync;
99 __u32 vsync_gpio;
100 __u32 total_lcd_lines;
101 __u32 total_porch_lines;
102 __u32 lcd_ref_usec_time;
103 __u32 refresh_timer_duration;
104
105 struct hrtimer dma_hrtimer;
106
107 boolean panel_power_on;
108 struct work_struct dma_update_worker;
109 struct semaphore sem;
110
111 struct timer_list vsync_resync_timer;
112 boolean vsync_handler_pending;
113 struct work_struct vsync_resync_worker;
114
115 ktime_t last_vsync_timetick;
116
117 __u32 *vsync_width_boundary;
118
119 unsigned int pmem_id;
120 struct disp_info_type_suspend suspend;
121
122 __u32 channel_irq;
123
124 struct mdp_dma_data *dma;
125 void (*dma_fnc) (struct msm_fb_data_type *mfd);
126 int (*cursor_update) (struct fb_info *info,
127 struct fb_cursor *cursor);
128 int (*lut_update) (struct fb_info *info,
129 struct fb_cmap *cmap);
130 int (*do_histogram) (struct fb_info *info,
131 struct mdp_histogram *hist);
132 void *cursor_buf;
133 void *cursor_buf_phys;
134
135 void *cmd_port;
136 void *data_port;
137 void *data_port_phys;
138
139 __u32 bl_level;
140
141 struct platform_device *pdev;
142
143 __u32 var_xres;
144 __u32 var_yres;
145 __u32 var_pixclock;
146
147#ifdef MSM_FB_ENABLE_DBGFS
148 struct dentry *sub_dir;
149#endif
150
151#ifdef CONFIG_HAS_EARLYSUSPEND
152 struct early_suspend early_suspend;
153 struct early_suspend mddi_early_suspend;
154 struct early_suspend mddi_ext_early_suspend;
155#endif
156 u32 mdp_fb_page_protection;
157 int allow_set_offset;
158};
159
160struct dentry *msm_fb_get_debugfs_root(void);
161void msm_fb_debugfs_file_create(struct dentry *root, const char *name,
162 u32 *var);
163void msm_fb_set_backlight(struct msm_fb_data_type *mfd, __u32 bkl_lvl,
164 u32 save);
165
166void msm_fb_add_device(struct platform_device *pdev);
167
168int msm_fb_detect_client(const char *name);
169
170#ifdef CONFIG_FB_BACKLIGHT
171void msm_fb_config_backlight(struct msm_fb_data_type *mfd);
172#endif
173
174#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
index 000000000000..033fc9486e01
--- /dev/null
+++ b/drivers/staging/msm/msm_fb_bl.c
@@ -0,0 +1,79 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include <linux/module.h>
19#include <linux/moduleparam.h>
20#include <linux/kernel.h>
21#include <linux/slab.h>
22#include <linux/fb.h>
23#include <linux/string.h>
24#include <linux/version.h>
25#include <linux/backlight.h>
26
27#include "msm_fb.h"
28
29static int msm_fb_bl_get_brightness(struct backlight_device *pbd)
30{
31 return pbd->props.brightness;
32}
33
34static int msm_fb_bl_update_status(struct backlight_device *pbd)
35{
36 struct msm_fb_data_type *mfd = bl_get_data(pbd);
37 __u32 bl_lvl;
38
39 bl_lvl = pbd->props.brightness;
40 bl_lvl = mfd->fbi->bl_curve[bl_lvl];
41 msm_fb_set_backlight(mfd, bl_lvl, 1);
42 return 0;
43}
44
45static struct backlight_ops msm_fb_bl_ops = {
46 .get_brightness = msm_fb_bl_get_brightness,
47 .update_status = msm_fb_bl_update_status,
48};
49
50void msm_fb_config_backlight(struct msm_fb_data_type *mfd)
51{
52 struct msm_fb_panel_data *pdata;
53 struct backlight_device *pbd;
54 struct fb_info *fbi;
55 char name[16];
56
57 fbi = mfd->fbi;
58 pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
59
60 if ((pdata) && (pdata->set_backlight)) {
61 snprintf(name, sizeof(name), "msmfb_bl%d", mfd->index);
62 pbd =
63 backlight_device_register(name, fbi->dev, mfd,
64 &msm_fb_bl_ops);
65 if (!IS_ERR(pbd)) {
66 fbi->bl_dev = pbd;
67 fb_bl_default_curve(fbi,
68 0,
69 mfd->panel_info.bl_min,
70 mfd->panel_info.bl_max);
71 pbd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
72 pbd->props.brightness = FB_BACKLIGHT_LEVELS - 1;
73 backlight_update_status(pbd);
74 } else {
75 fbi->bl_dev = NULL;
76 printk(KERN_ERR "msm_fb: backlight_device_register failed!\n");
77 }
78 }
79}
diff --git a/drivers/staging/msm/msm_fb_def.h b/drivers/staging/msm/msm_fb_def.h
new file mode 100644
index 000000000000..6de440937422
--- /dev/null
+++ b/drivers/staging/msm/msm_fb_def.h
@@ -0,0 +1,201 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are met:
5 * * Redistributions of source code must retain the above copyright
6 * notice, this list of conditions and the following disclaimer.
7 * * Redistributions in binary form must reproduce the above copyright
8 * notice, this list of conditions and the following disclaimer in the
9 * documentation and/or other materials provided with the distribution.
10 * * Neither the name of Code Aurora nor
11 * the names of its contributors may be used to endorse or promote
12 * products derived from this software without specific prior written
13 * permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 */
28
29#ifndef MSM_FB_DEF_H
30#define MSM_FB_DEF_H
31
32#include <linux/module.h>
33#include <linux/moduleparam.h>
34#include <linux/kernel.h>
35#include <linux/slab.h>
36#include <linux/delay.h>
37#include <linux/mm.h>
38#include <linux/fb.h>
39#include "msm_mdp.h"
40#include <linux/init.h>
41#include <linux/ioport.h>
42#include <linux/device.h>
43#include <linux/dma-mapping.h>
44#include <linux/uaccess.h>
45#include <linux/workqueue.h>
46#include <linux/string.h>
47#include <linux/version.h>
48#include <linux/proc_fs.h>
49#include <linux/vmalloc.h>
50#include <linux/debugfs.h>
51#include <linux/console.h>
52
53#include <linux/kernel.h>
54#include <linux/sched.h>
55#include <linux/time.h>
56#include <linux/init.h>
57#include <linux/interrupt.h>
58#include "linux/proc_fs.h"
59#include <mach/hardware.h>
60#include <linux/io.h>
61#include <linux/fb.h>
62#include <asm/system.h>
63#include <asm/mach-types.h>
64#include <linux/platform_device.h>
65
66typedef s64 int64;
67typedef s32 int32;
68typedef s16 int16;
69typedef s8 int8;
70
71typedef u64 uint64;
72typedef u32 uint32;
73typedef u16 uint16;
74typedef u8 uint8;
75
76typedef s32 int4;
77typedef s16 int2;
78typedef s8 int1;
79
80typedef u32 uint4;
81typedef u16 uint2;
82typedef u8 uint1;
83
84typedef u32 dword;
85typedef u16 word;
86typedef u8 byte;
87
88typedef unsigned int boolean;
89
90#ifndef TRUE
91#define TRUE 1
92#endif
93
94#ifndef FALSE
95#define FALSE 0
96#endif
97
98#define MSM_FB_ENABLE_DBGFS
99#define FEATURE_MDDI
100
101#define outp32(addr, val) writel(val, addr)
102#define outp16(addr, val) writew(val, addr)
103#define outp8(addr, val) writeb(val, addr)
104#define outp(addr, val) outp32(addr, val)
105
106#ifndef MAX
107#define MAX( x, y ) (((x) > (y)) ? (x) : (y))
108#endif
109
110#ifndef MIN
111#define MIN( x, y ) (((x) < (y)) ? (x) : (y))
112#endif
113
114/*--------------------------------------------------------------------------*/
115
116#define inp32(addr) readl(addr)
117#define inp16(addr) readw(addr)
118#define inp8(addr) readb(addr)
119#define inp(addr) inp32(addr)
120
121#define inpw(port) readw(port)
122#define outpw(port, val) writew(val, port)
123#define inpdw(port) readl(port)
124#define outpdw(port, val) writel(val, port)
125
126
127#define clk_busy_wait(x) msleep_interruptible((x)/1000)
128
129#define memory_barrier()
130
131#define assert(expr) \
132 if(!(expr)) { \
133 printk(KERN_ERR "msm_fb: assertion failed! %s,%s,%s,line=%d\n",\
134 #expr, __FILE__, __func__, __LINE__); \
135 }
136
137#define ASSERT(x) assert(x)
138
139#define DISP_EBI2_LOCAL_DEFINE
140#ifdef DISP_EBI2_LOCAL_DEFINE
141#define LCD_PRIM_BASE_PHYS 0x98000000
142#define LCD_SECD_BASE_PHYS 0x9c000000
143#define EBI2_PRIM_LCD_RS_PIN 0x20000
144#define EBI2_SECD_LCD_RS_PIN 0x20000
145
146#define EBI2_PRIM_LCD_CLR 0xC0
147#define EBI2_PRIM_LCD_SEL 0x40
148
149#define EBI2_SECD_LCD_CLR 0x300
150#define EBI2_SECD_LCD_SEL 0x100
151#endif
152
153extern u32 msm_fb_msg_level;
154
155/*
156 * Message printing priorities:
157 * LEVEL 0 KERN_EMERG (highest priority)
158 * LEVEL 1 KERN_ALERT
159 * LEVEL 2 KERN_CRIT
160 * LEVEL 3 KERN_ERR
161 * LEVEL 4 KERN_WARNING
162 * LEVEL 5 KERN_NOTICE
163 * LEVEL 6 KERN_INFO
164 * LEVEL 7 KERN_DEBUG (Lowest priority)
165 */
166#define MSM_FB_EMERG(msg, ...) \
167 if (msm_fb_msg_level > 0) \
168 printk(KERN_EMERG msg, ## __VA_ARGS__);
169#define MSM_FB_ALERT(msg, ...) \
170 if (msm_fb_msg_level > 1) \
171 printk(KERN_ALERT msg, ## __VA_ARGS__);
172#define MSM_FB_CRIT(msg, ...) \
173 if (msm_fb_msg_level > 2) \
174 printk(KERN_CRIT msg, ## __VA_ARGS__);
175#define MSM_FB_ERR(msg, ...) \
176 if (msm_fb_msg_level > 3) \
177 printk(KERN_ERR msg, ## __VA_ARGS__);
178#define MSM_FB_WARNING(msg, ...) \
179 if (msm_fb_msg_level > 4) \
180 printk(KERN_WARNING msg, ## __VA_ARGS__);
181#define MSM_FB_NOTICE(msg, ...) \
182 if (msm_fb_msg_level > 5) \
183 printk(KERN_NOTICE msg, ## __VA_ARGS__);
184#define MSM_FB_INFO(msg, ...) \
185 if (msm_fb_msg_level > 6) \
186 printk(KERN_INFO msg, ## __VA_ARGS__);
187#define MSM_FB_DEBUG(msg, ...) \
188 if (msm_fb_msg_level > 7) \
189 printk(KERN_DEBUG msg, ## __VA_ARGS__);
190
191#ifdef MSM_FB_C
192unsigned char *msm_mdp_base;
193unsigned char *msm_pmdh_base;
194unsigned char *msm_emdh_base;
195#else
196extern unsigned char *msm_mdp_base;
197extern unsigned char *msm_pmdh_base;
198extern unsigned char *msm_emdh_base;
199#endif
200
201#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
index 000000000000..b17a239a1bc7
--- /dev/null
+++ b/drivers/staging/msm/msm_fb_panel.c
@@ -0,0 +1,136 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include <linux/module.h>
19#include <linux/moduleparam.h>
20#include <linux/kernel.h>
21#include <linux/slab.h>
22#include <linux/delay.h>
23#include <linux/mm.h>
24#include <linux/fb.h>
25#include <linux/init.h>
26#include <linux/ioport.h>
27#include <linux/device.h>
28#include <linux/dma-mapping.h>
29#include <linux/uaccess.h>
30#include <linux/workqueue.h>
31#include <linux/string.h>
32#include <linux/version.h>
33#include <linux/proc_fs.h>
34#include <linux/vmalloc.h>
35#include <linux/debugfs.h>
36
37#include "msm_fb_panel.h"
38
39int panel_next_on(struct platform_device *pdev)
40{
41 int ret = 0;
42 struct msm_fb_panel_data *pdata;
43 struct msm_fb_panel_data *next_pdata;
44 struct platform_device *next_pdev;
45
46 pdata = (struct msm_fb_panel_data *)pdev->dev.platform_data;
47
48 if (pdata) {
49 next_pdev = pdata->next;
50 if (next_pdev) {
51 next_pdata =
52 (struct msm_fb_panel_data *)next_pdev->dev.
53 platform_data;
54 if ((next_pdata) && (next_pdata->on))
55 ret = next_pdata->on(next_pdev);
56 }
57 }
58
59 return ret;
60}
61
62int panel_next_off(struct platform_device *pdev)
63{
64 int ret = 0;
65 struct msm_fb_panel_data *pdata;
66 struct msm_fb_panel_data *next_pdata;
67 struct platform_device *next_pdev;
68
69 pdata = (struct msm_fb_panel_data *)pdev->dev.platform_data;
70
71 if (pdata) {
72 next_pdev = pdata->next;
73 if (next_pdev) {
74 next_pdata =
75 (struct msm_fb_panel_data *)next_pdev->dev.
76 platform_data;
77 if ((next_pdata) && (next_pdata->on))
78 ret = next_pdata->off(next_pdev);
79 }
80 }
81
82 return ret;
83}
84
85struct platform_device *msm_fb_device_alloc(struct msm_fb_panel_data *pdata,
86 u32 type, u32 id)
87{
88 struct platform_device *this_dev = NULL;
89 char dev_name[16];
90
91 switch (type) {
92 case EBI2_PANEL:
93 snprintf(dev_name, sizeof(dev_name), "ebi2_lcd");
94 break;
95
96 case MDDI_PANEL:
97 snprintf(dev_name, sizeof(dev_name), "mddi");
98 break;
99
100 case EXT_MDDI_PANEL:
101 snprintf(dev_name, sizeof(dev_name), "mddi_ext");
102 break;
103
104 case TV_PANEL:
105 snprintf(dev_name, sizeof(dev_name), "tvenc");
106 break;
107
108 case HDMI_PANEL:
109 case LCDC_PANEL:
110 snprintf(dev_name, sizeof(dev_name), "lcdc");
111 break;
112
113 default:
114 return NULL;
115 }
116
117 if (pdata != NULL)
118 pdata->next = NULL;
119 else
120 return NULL;
121
122 this_dev =
123 platform_device_alloc(dev_name, ((u32) type << 16) | (u32) id);
124
125 if (this_dev) {
126 if (platform_device_add_data
127 (this_dev, pdata, sizeof(struct msm_fb_panel_data))) {
128 printk
129 ("msm_fb_device_alloc: platform_device_add_data failed!\n");
130 platform_device_put(this_dev);
131 return NULL;
132 }
133 }
134
135 return this_dev;
136}
diff --git a/drivers/staging/msm/msm_fb_panel.h b/drivers/staging/msm/msm_fb_panel.h
new file mode 100644
index 000000000000..ab458310c3a2
--- /dev/null
+++ b/drivers/staging/msm/msm_fb_panel.h
@@ -0,0 +1,145 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are met:
5 * * Redistributions of source code must retain the above copyright
6 * notice, this list of conditions and the following disclaimer.
7 * * Redistributions in binary form must reproduce the above copyright
8 * notice, this list of conditions and the following disclaimer in the
9 * documentation and/or other materials provided with the distribution.
10 * * Neither the name of Code Aurora nor
11 * the names of its contributors may be used to endorse or promote
12 * products derived from this software without specific prior written
13 * permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 */
28
29#ifndef MSM_FB_PANEL_H
30#define MSM_FB_PANEL_H
31
32#include "msm_fb_def.h"
33
34struct msm_fb_data_type;
35
36typedef void (*msm_fb_vsync_handler_type) (void *arg);
37
38/* panel id type */
39typedef struct panel_id_s {
40 uint16 id;
41 uint16 type;
42} panel_id_type;
43
44/* panel type list */
45#define NO_PANEL 0xffff /* No Panel */
46#define MDDI_PANEL 1 /* MDDI */
47#define EBI2_PANEL 2 /* EBI2 */
48#define LCDC_PANEL 3 /* internal LCDC type */
49#define EXT_MDDI_PANEL 4 /* Ext.MDDI */
50#define TV_PANEL 5 /* TV */
51#define HDMI_PANEL 6 /* HDMI TV */
52
53/* panel class */
54typedef enum {
55 DISPLAY_LCD = 0, /* lcd = ebi2/mddi */
56 DISPLAY_LCDC, /* lcdc */
57 DISPLAY_TV, /* TV Out */
58 DISPLAY_EXT_MDDI, /* External MDDI */
59} DISP_TARGET;
60
61/* panel device locaiton */
62typedef enum {
63 DISPLAY_1 = 0, /* attached as first device */
64 DISPLAY_2, /* attached on second device */
65 MAX_PHYS_TARGET_NUM,
66} DISP_TARGET_PHYS;
67
68/* panel info type */
69struct lcd_panel_info {
70 __u32 vsync_enable;
71 __u32 refx100;
72 __u32 v_back_porch;
73 __u32 v_front_porch;
74 __u32 v_pulse_width;
75 __u32 hw_vsync_mode;
76 __u32 vsync_notifier_period;
77};
78
79struct lcdc_panel_info {
80 __u32 h_back_porch;
81 __u32 h_front_porch;
82 __u32 h_pulse_width;
83 __u32 v_back_porch;
84 __u32 v_front_porch;
85 __u32 v_pulse_width;
86 __u32 border_clr;
87 __u32 underflow_clr;
88 __u32 hsync_skew;
89};
90
91struct mddi_panel_info {
92 __u32 vdopkt;
93};
94
95struct msm_panel_info {
96 __u32 xres;
97 __u32 yres;
98 __u32 bpp;
99 __u32 type;
100 __u32 wait_cycle;
101 DISP_TARGET_PHYS pdest;
102 __u32 bl_max;
103 __u32 bl_min;
104 __u32 fb_num;
105 __u32 clk_rate;
106 __u32 clk_min;
107 __u32 clk_max;
108 __u32 frame_count;
109
110 union {
111 struct mddi_panel_info mddi;
112 };
113
114 union {
115 struct lcd_panel_info lcd;
116 struct lcdc_panel_info lcdc;
117 };
118};
119
120struct msm_fb_panel_data {
121 struct msm_panel_info panel_info;
122 void (*set_rect) (int x, int y, int xres, int yres);
123 void (*set_vsync_notifier) (msm_fb_vsync_handler_type, void *arg);
124 void (*set_backlight) (struct msm_fb_data_type *);
125
126 /* function entry chain */
127 int (*on) (struct platform_device *pdev);
128 int (*off) (struct platform_device *pdev);
129 struct platform_device *next;
130};
131
132/*===========================================================================
133 FUNCTIONS PROTOTYPES
134============================================================================*/
135struct platform_device *msm_fb_device_alloc(struct msm_fb_panel_data *pdata,
136 u32 type, u32 id);
137int panel_next_on(struct platform_device *pdev);
138int panel_next_off(struct platform_device *pdev);
139
140int lcdc_device_register(struct msm_panel_info *pinfo);
141
142int mddi_toshiba_device_register(struct msm_panel_info *pinfo,
143 u32 channel, u32 panel);
144
145#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
index 000000000000..2d5323f5b62d
--- /dev/null
+++ b/drivers/staging/msm/msm_mdp.h
@@ -0,0 +1,245 @@
1/* include/linux/msm_mdp.h
2 *
3 * Copyright (C) 2007 Google Incorporated
4 * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15#ifndef _MSM_MDP_H_
16#define _MSM_MDP_H_
17
18#include <linux/types.h>
19#include <linux/fb.h>
20
21#define MSMFB_IOCTL_MAGIC 'm'
22#define MSMFB_GRP_DISP _IOW(MSMFB_IOCTL_MAGIC, 1, unsigned int)
23#define MSMFB_BLIT _IOW(MSMFB_IOCTL_MAGIC, 2, unsigned int)
24#define MSMFB_SUSPEND_SW_REFRESHER _IOW(MSMFB_IOCTL_MAGIC, 128, unsigned int)
25#define MSMFB_RESUME_SW_REFRESHER _IOW(MSMFB_IOCTL_MAGIC, 129, unsigned int)
26#define MSMFB_CURSOR _IOW(MSMFB_IOCTL_MAGIC, 130, struct fb_cursor)
27#define MSMFB_SET_LUT _IOW(MSMFB_IOCTL_MAGIC, 131, struct fb_cmap)
28#define MSMFB_HISTOGRAM _IOWR(MSMFB_IOCTL_MAGIC, 132, struct mdp_histogram)
29/* new ioctls's for set/get ccs matrix */
30#define MSMFB_GET_CCS_MATRIX _IOWR(MSMFB_IOCTL_MAGIC, 133, struct mdp_ccs)
31#define MSMFB_SET_CCS_MATRIX _IOW(MSMFB_IOCTL_MAGIC, 134, struct mdp_ccs)
32#define MSMFB_OVERLAY_SET _IOWR(MSMFB_IOCTL_MAGIC, 135, \
33 struct mdp_overlay)
34#define MSMFB_OVERLAY_UNSET _IOW(MSMFB_IOCTL_MAGIC, 136, unsigned int)
35#define MSMFB_OVERLAY_PLAY _IOW(MSMFB_IOCTL_MAGIC, 137, \
36 struct msmfb_overlay_data)
37#define MSMFB_GET_PAGE_PROTECTION _IOR(MSMFB_IOCTL_MAGIC, 138, \
38 struct mdp_page_protection)
39#define MSMFB_SET_PAGE_PROTECTION _IOW(MSMFB_IOCTL_MAGIC, 139, \
40 struct mdp_page_protection)
41#define MSMFB_OVERLAY_GET _IOR(MSMFB_IOCTL_MAGIC, 140, \
42 struct mdp_overlay)
43
44/* new ioctls for async MDP ops */
45#define MSMFB_ASYNC_BLIT _IOW(MSMFB_IOCTL_MAGIC, 141, unsigned int)
46#define MSMFB_BLIT_FLUSH _IOR(MSMFB_IOCTL_MAGIC, 142, unsigned int)
47
48#define MDP_IMGTYPE2_START 0x10000
49
50enum {
51 MDP_RGB_565, /* RGB 565 planer */
52 MDP_XRGB_8888, /* RGB 888 padded */
53 MDP_Y_CBCR_H2V2, /* Y and CbCr, pseudo planer w/ Cb is in MSB */
54 MDP_ARGB_8888, /* ARGB 888 */
55 MDP_RGB_888, /* RGB 888 planer */
56 MDP_Y_CRCB_H2V2, /* Y and CrCb, pseudo planer w/ Cr is in MSB */
57 MDP_YCRYCB_H2V1, /* YCrYCb interleave */
58 MDP_Y_CRCB_H2V1, /* Y and CrCb, pseduo planer w/ Cr is in MSB */
59 MDP_Y_CBCR_H2V1, /* Y and CrCb, pseduo planer w/ Cr is in MSB */
60 MDP_RGBA_8888, /* ARGB 888 */
61 MDP_BGRA_8888, /* ABGR 888 */
62 MDP_Y_CRCB_H2V2_TILE, /* Y and CrCb, pseudo planer tile */
63 MDP_Y_CBCR_H2V2_TILE, /* Y and CbCr, pseudo planer tile */
64 MDP_IMGTYPE_LIMIT,
65 MDP_BGR_565 = MDP_IMGTYPE2_START, /* BGR 565 planer */
66 MDP_FB_FORMAT, /* framebuffer format */
67 MDP_IMGTYPE_LIMIT2 /* Non valid image type after this enum */
68};
69
70enum {
71 PMEM_IMG,
72 FB_IMG,
73};
74
75/* mdp_blit_req flag values */
76#define MDP_ROT_NOP 0
77#define MDP_FLIP_LR 0x1
78#define MDP_FLIP_UD 0x2
79#define MDP_ROT_90 0x4
80#define MDP_ROT_180 (MDP_FLIP_UD|MDP_FLIP_LR)
81#define MDP_ROT_270 (MDP_ROT_90|MDP_FLIP_UD|MDP_FLIP_LR)
82#define MDP_DITHER 0x8
83#define MDP_BLUR 0x10
84#define MDP_BLEND_FG_PREMULT 0x20000
85
86#define MDP_DEINTERLACE 0x80000000
87#define MDP_SHARPENING 0x40000000
88
89#define MDP_NO_DMA_BARRIER_START 0x20000000
90#define MDP_NO_DMA_BARRIER_END 0x10000000
91#define MDP_NO_BLIT 0x08000000
92#define MDP_BLIT_WITH_DMA_BARRIERS 0x000
93#define MDP_BLIT_WITH_NO_DMA_BARRIERS \
94 (MDP_NO_DMA_BARRIER_START | MDP_NO_DMA_BARRIER_END)
95#define MDP_TRANSP_NOP 0xffffffff
96#define MDP_ALPHA_NOP 0xff
97
98#define MDP_BLIT_SRC_GEM 0x02000000 /* set for GEM, clear for PMEM */
99#define MDP_BLIT_DST_GEM 0x01000000 /* set for GEM, clear for PMEM */
100
101#define MDP_FB_PAGE_PROTECTION_NONCACHED (0)
102#define MDP_FB_PAGE_PROTECTION_WRITECOMBINE (1)
103#define MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE (2)
104#define MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE (3)
105#define MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE (4)
106/* Sentinel: Don't use! */
107#define MDP_FB_PAGE_PROTECTION_INVALID (5)
108/* Count of the number of MDP_FB_PAGE_PROTECTION_... values. */
109#define MDP_NUM_FB_PAGE_PROTECTION_VALUES (5)
110
111struct mdp_rect {
112 uint32_t x;
113 uint32_t y;
114 uint32_t w;
115 uint32_t h;
116};
117
118struct mdp_img {
119 uint32_t width;
120 uint32_t height;
121 uint32_t format;
122 uint32_t offset;
123 int memory_id; /* the file descriptor */
124 uint32_t priv;
125};
126
127/*
128 * {3x3} + {3} ccs matrix
129 */
130
131#define MDP_CCS_RGB2YUV 0
132#define MDP_CCS_YUV2RGB 1
133
134#define MDP_CCS_SIZE 9
135#define MDP_BV_SIZE 3
136
137struct mdp_ccs {
138 int direction; /* MDP_CCS_RGB2YUV or YUV2RGB */
139 uint16_t ccs[MDP_CCS_SIZE]; /* 3x3 color coefficients */
140 uint16_t bv[MDP_BV_SIZE]; /* 1x3 bias vector */
141};
142
143/* The version of the mdp_blit_req structure so that
144 * user applications can selectively decide which functionality
145 * to include
146 */
147
148#define MDP_BLIT_REQ_VERSION 2
149
150struct mdp_blit_req {
151 struct mdp_img src;
152 struct mdp_img dst;
153 struct mdp_rect src_rect;
154 struct mdp_rect dst_rect;
155 uint32_t alpha;
156 uint32_t transp_mask;
157 uint32_t flags;
158 int sharpening_strength; /* -127 <--> 127, default 64 */
159};
160
161struct mdp_blit_req_list {
162 uint32_t count;
163 struct mdp_blit_req req[];
164};
165
166struct msmfb_data {
167 uint32_t offset;
168 int memory_id;
169 int id;
170};
171
172#define MSMFB_NEW_REQUEST -1
173
174struct msmfb_overlay_data {
175 uint32_t id;
176 struct msmfb_data data;
177};
178
179struct msmfb_img {
180 uint32_t width;
181 uint32_t height;
182 uint32_t format;
183};
184
185struct mdp_overlay {
186 struct msmfb_img src;
187 struct mdp_rect src_rect;
188 struct mdp_rect dst_rect;
189 uint32_t z_order; /* stage number */
190 uint32_t is_fg; /* control alpha & transp */
191 uint32_t alpha;
192 uint32_t transp_mask;
193 uint32_t flags;
194 uint32_t id;
195 uint32_t user_data[8];
196};
197
198struct mdp_histogram {
199 uint32_t frame_cnt;
200 uint32_t bin_cnt;
201 uint32_t *r;
202 uint32_t *g;
203 uint32_t *b;
204};
205
206struct mdp_page_protection {
207 uint32_t page_protection;
208};
209
210
211struct msm_panel_common_pdata {
212 int gpio;
213 int (*backlight_level)(int level, int max, int min);
214 int (*pmic_backlight)(int level);
215 int (*panel_num)(void);
216 void (*panel_config_gpio)(int);
217 int *gpio_num;
218};
219
220struct lcdc_platform_data {
221 int (*lcdc_gpio_config)(int on);
222 void (*lcdc_power_save)(int);
223};
224
225struct tvenc_platform_data {
226 int (*pm_vid_en)(int on);
227};
228
229struct mddi_platform_data {
230 void (*mddi_power_save)(int on);
231 int (*mddi_sel_clk)(u32 *clk_rate);
232};
233
234struct msm_fb_platform_data {
235 int (*detect_client)(const char *name);
236 int mddi_prescan;
237 int (*allow_set_offset)(void);
238};
239
240struct msm_hdmi_platform_data {
241 int irq;
242 int (*cable_detect)(int insert);
243};
244
245#endif /*_MSM_MDP_H_*/
diff --git a/drivers/staging/msm/staging-devices.c b/drivers/staging/msm/staging-devices.c
new file mode 100644
index 000000000000..0f8ec3e26013
--- /dev/null
+++ b/drivers/staging/msm/staging-devices.c
@@ -0,0 +1,323 @@
1#include <linux/kernel.h>
2#include <linux/irq.h>
3#include <linux/gpio.h>
4#include <linux/platform_device.h>
5#include <linux/bootmem.h>
6#include <linux/delay.h>
7
8#include <asm/mach-types.h>
9#include <asm/mach/arch.h>
10#include <asm/io.h>
11#include <asm/setup.h>
12
13#include <mach/board.h>
14#include <mach/irqs.h>
15#include <mach/sirc.h>
16#include <mach/gpio.h>
17
18#include "msm_mdp.h"
19#include "memory_ll.h"
20//#include "android_pmem.h"
21#include <mach/board.h>
22
23#ifdef CONFIG_MSM_SOC_REV_A
24#define MSM_SMI_BASE 0xE0000000
25#else
26#define MSM_SMI_BASE 0x00000000
27#endif
28
29
30#define TOUCHPAD_SUSPEND 34
31#define TOUCHPAD_IRQ 38
32
33#define MSM_PMEM_MDP_SIZE 0x1591000
34
35#ifdef CONFIG_MSM_SOC_REV_A
36#define SMEM_SPINLOCK_I2C "D:I2C02000021"
37#else
38#define SMEM_SPINLOCK_I2C "S:6"
39#endif
40
41#define MSM_PMEM_ADSP_SIZE 0x1C00000
42
43#define MSM_FB_SIZE 0x500000
44#define MSM_FB_SIZE_ST15 0x800000
45#define MSM_AUDIO_SIZE 0x80000
46#define MSM_GPU_PHYS_SIZE SZ_2M
47
48#ifdef CONFIG_MSM_SOC_REV_A
49#define MSM_SMI_BASE 0xE0000000
50#else
51#define MSM_SMI_BASE 0x00000000
52#endif
53
54#define MSM_SHARED_RAM_PHYS (MSM_SMI_BASE + 0x00100000)
55
56#define MSM_PMEM_SMI_BASE (MSM_SMI_BASE + 0x02B00000)
57#define MSM_PMEM_SMI_SIZE 0x01500000
58
59#define MSM_FB_BASE MSM_PMEM_SMI_BASE
60#define MSM_GPU_PHYS_BASE (MSM_FB_BASE + MSM_FB_SIZE)
61#define MSM_PMEM_SMIPOOL_BASE (MSM_GPU_PHYS_BASE + MSM_GPU_PHYS_SIZE)
62#define MSM_PMEM_SMIPOOL_SIZE (MSM_PMEM_SMI_SIZE - MSM_FB_SIZE \
63 - MSM_GPU_PHYS_SIZE)
64
65#if defined(CONFIG_FB_MSM_MDP40)
66#define MDP_BASE 0xA3F00000
67#define PMDH_BASE 0xAD600000
68#define EMDH_BASE 0xAD700000
69#define TVENC_BASE 0xAD400000
70#else
71#define MDP_BASE 0xAA200000
72#define PMDH_BASE 0xAA600000
73#define EMDH_BASE 0xAA700000
74#define TVENC_BASE 0xAA400000
75#endif
76
77#define PMEM_KERNEL_EBI1_SIZE (CONFIG_PMEM_KERNEL_SIZE * 1024 * 1024)
78
79static struct resource msm_fb_resources[] = {
80 {
81 .flags = IORESOURCE_DMA,
82 }
83};
84
85static struct resource msm_mdp_resources[] = {
86 {
87 .name = "mdp",
88 .start = MDP_BASE,
89 .end = MDP_BASE + 0x000F0000 - 1,
90 .flags = IORESOURCE_MEM,
91 }
92};
93
94static struct platform_device msm_mdp_device = {
95 .name = "mdp",
96 .id = 0,
97 .num_resources = ARRAY_SIZE(msm_mdp_resources),
98 .resource = msm_mdp_resources,
99};
100
101static struct platform_device msm_lcdc_device = {
102 .name = "lcdc",
103 .id = 0,
104};
105
106static int msm_fb_detect_panel(const char *name)
107{
108 int ret = -EPERM;
109
110 if (machine_is_qsd8x50_ffa() || machine_is_qsd8x50a_ffa()) {
111 if (!strncmp(name, "mddi_toshiba_wvga_pt", 20))
112 ret = 0;
113 else
114 ret = -ENODEV;
115 } else if ((machine_is_qsd8x50_surf() || machine_is_qsd8x50a_surf())
116 && !strcmp(name, "lcdc_external"))
117 ret = 0;
118 else if (0 /*machine_is_qsd8x50_grapefruit() */) {
119 if (!strcmp(name, "lcdc_grapefruit_vga"))
120 ret = 0;
121 else
122 ret = -ENODEV;
123 } else if (machine_is_qsd8x50_st1()) {
124 if (!strcmp(name, "lcdc_st1_wxga"))
125 ret = 0;
126 else
127 ret = -ENODEV;
128 } else if (machine_is_qsd8x50a_st1_5()) {
129 if (!strcmp(name, "lcdc_st15") ||
130 !strcmp(name, "hdmi_sii9022"))
131 ret = 0;
132 else
133 ret = -ENODEV;
134 }
135
136 return ret;
137}
138
139/* Only allow a small subset of machines to set the offset via
140 FB PAN_DISPLAY */
141
142static int msm_fb_allow_set_offset(void)
143{
144 return (machine_is_qsd8x50_st1() ||
145 machine_is_qsd8x50a_st1_5()) ? 1 : 0;
146}
147
148
149static struct msm_fb_platform_data msm_fb_pdata = {
150 .detect_client = msm_fb_detect_panel,
151 .allow_set_offset = msm_fb_allow_set_offset,
152};
153
154static struct platform_device msm_fb_device = {
155 .name = "msm_fb",
156 .id = 0,
157 .num_resources = ARRAY_SIZE(msm_fb_resources),
158 .resource = msm_fb_resources,
159 .dev = {
160 .platform_data = &msm_fb_pdata,
161 }
162};
163
164static void __init qsd8x50_allocate_memory_regions(void)
165{
166 void *addr;
167 unsigned long size;
168 if (machine_is_qsd8x50a_st1_5())
169 size = MSM_FB_SIZE_ST15;
170 else
171 size = MSM_FB_SIZE;
172
173 addr = alloc_bootmem(size); // (void *)MSM_FB_BASE;
174 if (!addr)
175 printk("Failed to allocate bootmem for framebuffer\n");
176
177
178 msm_fb_resources[0].start = __pa(addr);
179 msm_fb_resources[0].end = msm_fb_resources[0].start + size - 1;
180 pr_info(KERN_ERR "using %lu bytes of SMI at %lx physical for fb\n",
181 size, (unsigned long)addr);
182}
183
184static int msm_fb_lcdc_gpio_config(int on)
185{
186// return 0;
187 if (machine_is_qsd8x50_st1()) {
188 if (on) {
189 gpio_set_value(32, 1);
190 mdelay(100);
191 gpio_set_value(20, 1);
192 gpio_set_value(17, 1);
193 gpio_set_value(19, 1);
194 } else {
195 gpio_set_value(17, 0);
196 gpio_set_value(19, 0);
197 gpio_set_value(20, 0);
198 mdelay(100);
199 gpio_set_value(32, 0);
200 }
201 } else if (machine_is_qsd8x50a_st1_5()) {
202 if (on) {
203 gpio_set_value(17, 1);
204 gpio_set_value(19, 1);
205 gpio_set_value(20, 1);
206 gpio_set_value(22, 0);
207 gpio_set_value(32, 1);
208 gpio_set_value(155, 1);
209 //st15_hdmi_power(1);
210 gpio_set_value(22, 1);
211
212 } else {
213 gpio_set_value(17, 0);
214 gpio_set_value(19, 0);
215 gpio_set_value(22, 0);
216 gpio_set_value(32, 0);
217 gpio_set_value(155, 0);
218 // st15_hdmi_power(0);
219 }
220 }
221 return 0;
222}
223
224
225static struct lcdc_platform_data lcdc_pdata = {
226 .lcdc_gpio_config = msm_fb_lcdc_gpio_config,
227};
228
229static struct msm_gpio msm_fb_st15_gpio_config_data[] = {
230 { GPIO_CFG(17, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "lcdc_en0" },
231 { GPIO_CFG(19, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "dat_pwr_sv" },
232 { GPIO_CFG(20, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "lvds_pwr_dn" },
233 { GPIO_CFG(22, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "lcdc_en1" },
234 { GPIO_CFG(32, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "lcdc_en2" },
235 { GPIO_CFG(103, 0, GPIO_INPUT, GPIO_NO_PULL, GPIO_2MA), "hdmi_irq" },
236 { GPIO_CFG(155, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "hdmi_3v3" },
237};
238
239static struct msm_panel_common_pdata mdp_pdata = {
240 .gpio = 98,
241};
242
243static struct platform_device *devices[] __initdata = {
244 &msm_fb_device,
245};
246
247
248static void __init msm_register_device(struct platform_device *pdev, void *data)
249{
250 int ret;
251
252 pdev->dev.platform_data = data;
253
254 ret = platform_device_register(pdev);
255 if (ret)
256 dev_err(&pdev->dev,
257 "%s: platform_device_register() failed = %d\n",
258 __func__, ret);
259}
260
261void __init msm_fb_register_device(char *name, void *data)
262{
263 if (!strncmp(name, "mdp", 3))
264 msm_register_device(&msm_mdp_device, data);
265/*
266 else if (!strncmp(name, "pmdh", 4))
267 msm_register_device(&msm_mddi_device, data);
268 else if (!strncmp(name, "emdh", 4))
269 msm_register_device(&msm_mddi_ext_device, data);
270 else if (!strncmp(name, "ebi2", 4))
271 msm_register_device(&msm_ebi2_lcd_device, data);
272 else if (!strncmp(name, "tvenc", 5))
273 msm_register_device(&msm_tvenc_device, data);
274 else */
275
276 if (!strncmp(name, "lcdc", 4))
277 msm_register_device(&msm_lcdc_device, data);
278 /*else
279 printk(KERN_ERR "%s: unknown device! %s\n", __func__, name);
280*/
281}
282
283static void __init msm_fb_add_devices(void)
284{
285 int rc;
286 msm_fb_register_device("mdp", &mdp_pdata);
287// msm_fb_register_device("pmdh", &mddi_pdata);
288// msm_fb_register_device("emdh", &mddi_pdata);
289// msm_fb_register_device("tvenc", 0);
290
291 if (machine_is_qsd8x50a_st1_5()) {
292/* rc = st15_hdmi_vreg_init();
293 if (rc)
294 return;
295*/
296 rc = msm_gpios_request_enable(
297 msm_fb_st15_gpio_config_data,
298 ARRAY_SIZE(msm_fb_st15_gpio_config_data));
299 if (rc) {
300 printk(KERN_ERR "%s: unable to init lcdc gpios\n",
301 __func__);
302 return;
303 }
304 msm_fb_register_device("lcdc", &lcdc_pdata);
305 } else
306 msm_fb_register_device("lcdc", 0);
307}
308
309int __init staging_init_pmem(void)
310{
311 qsd8x50_allocate_memory_regions();
312 return 0;
313}
314
315int __init staging_init_devices(void)
316{
317 platform_add_devices(devices, ARRAY_SIZE(devices));
318 msm_fb_add_devices();
319 return 0;
320}
321
322arch_initcall(staging_init_pmem);
323arch_initcall(staging_init_devices);
diff --git a/drivers/staging/msm/tv_ntsc.c b/drivers/staging/msm/tv_ntsc.c
new file mode 100644
index 000000000000..5eb67611661a
--- /dev/null
+++ b/drivers/staging/msm/tv_ntsc.c
@@ -0,0 +1,163 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/sched.h>
21#include <linux/time.h>
22#include <linux/init.h>
23#include <linux/interrupt.h>
24#include <linux/spinlock.h>
25#include <linux/delay.h>
26#include <mach/hardware.h>
27#include <linux/io.h>
28
29#include <asm/system.h>
30#include <asm/mach-types.h>
31#include <linux/semaphore.h>
32#include <linux/uaccess.h>
33#include <linux/clk.h>
34
35#include "msm_fb.h"
36#include "tvenc.h"
37
38#define NTSC_TV_DIMENSION_WIDTH 720
39#define NTSC_TV_DIMENSION_HEIGHT 480
40
41static int ntsc_off(struct platform_device *pdev);
42static int ntsc_on(struct platform_device *pdev);
43
44static int ntsc_on(struct platform_device *pdev)
45{
46 uint32 reg = 0;
47 int ret = 0;
48 struct msm_fb_data_type *mfd;
49
50 mfd = platform_get_drvdata(pdev);
51
52 if (!mfd)
53 return -ENODEV;
54
55 if (mfd->key != MFD_KEY)
56 return -EINVAL;
57
58 TV_OUT(TV_ENC_CTL, 0); /* disable TV encoder */
59
60 if (mfd->panel.id == NTSC_M) {
61 /* Cr gain 11, Cb gain C6, y_gain 97 */
62 TV_OUT(TV_GAIN, 0x0081B697);
63 } else {
64 /* Cr gain 11, Cb gain C6, y_gain 97 */
65 TV_OUT(TV_GAIN, 0x008bc4a3);
66 reg |= TVENC_CTL_NTSCJ_MODE;
67 }
68
69 TV_OUT(TV_CGMS, 0x0);
70 /* NTSC Timing */
71 TV_OUT(TV_SYNC_1, 0x0020009e);
72 TV_OUT(TV_SYNC_2, 0x011306B4);
73 TV_OUT(TV_SYNC_3, 0x0006000C);
74 TV_OUT(TV_SYNC_4, 0x0028020D);
75 TV_OUT(TV_SYNC_5, 0x005E02FB);
76 TV_OUT(TV_SYNC_6, 0x0006000C);
77 TV_OUT(TV_SYNC_7, 0x00000012);
78 TV_OUT(TV_BURST_V1, 0x0013020D);
79 TV_OUT(TV_BURST_V2, 0x0014020C);
80 TV_OUT(TV_BURST_V3, 0x0013020D);
81 TV_OUT(TV_BURST_V4, 0x0014020C);
82 TV_OUT(TV_BURST_H, 0x00AE00F2);
83 TV_OUT(TV_SOL_REQ_ODD, 0x00280208);
84 TV_OUT(TV_SOL_REQ_EVEN, 0x00290209);
85
86 reg |= TVENC_CTL_TV_MODE_NTSC_M_PAL60;
87
88 reg |= TVENC_CTL_Y_FILTER_EN |
89 TVENC_CTL_CR_FILTER_EN |
90 TVENC_CTL_CB_FILTER_EN | TVENC_CTL_SINX_FILTER_EN;
91#ifdef CONFIG_FB_MSM_TVOUT_SVIDEO
92 reg |= TVENC_CTL_S_VIDEO_EN;
93#endif
94
95 TV_OUT(TV_LEVEL, 0x00000000); /* DC offset to 0. */
96 TV_OUT(TV_OFFSET, 0x008080f0);
97
98#ifdef CONFIG_FB_MSM_MDP31
99 TV_OUT(TV_DAC_INTF, 0x29);
100#endif
101 TV_OUT(TV_ENC_CTL, reg);
102
103 reg |= TVENC_CTL_ENC_EN;
104 TV_OUT(TV_ENC_CTL, reg);
105
106 return ret;
107}
108
109static int ntsc_off(struct platform_device *pdev)
110{
111 TV_OUT(TV_ENC_CTL, 0); /* disable TV encoder */
112 return 0;
113}
114
115static int __init ntsc_probe(struct platform_device *pdev)
116{
117 msm_fb_add_device(pdev);
118
119 return 0;
120}
121
122static struct platform_driver this_driver = {
123 .probe = ntsc_probe,
124 .driver = {
125 .name = "tv_ntsc",
126 },
127};
128
129static struct msm_fb_panel_data ntsc_panel_data = {
130 .panel_info.xres = NTSC_TV_DIMENSION_WIDTH,
131 .panel_info.yres = NTSC_TV_DIMENSION_HEIGHT,
132 .panel_info.type = TV_PANEL,
133 .panel_info.pdest = DISPLAY_1,
134 .panel_info.wait_cycle = 0,
135 .panel_info.bpp = 16,
136 .panel_info.fb_num = 2,
137 .on = ntsc_on,
138 .off = ntsc_off,
139};
140
141static struct platform_device this_device = {
142 .name = "tv_ntsc",
143 .id = 0,
144 .dev = {
145 .platform_data = &ntsc_panel_data,
146 }
147};
148
149static int __init ntsc_init(void)
150{
151 int ret;
152
153 ret = platform_driver_register(&this_driver);
154 if (!ret) {
155 ret = platform_device_register(&this_device);
156 if (ret)
157 platform_driver_unregister(&this_driver);
158 }
159
160 return ret;
161}
162
163module_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
index 000000000000..204da514660e
--- /dev/null
+++ b/drivers/staging/msm/tv_pal.c
@@ -0,0 +1,213 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17#include <linux/module.h>
18#include <linux/kernel.h>
19#include <linux/sched.h>
20#include <linux/time.h>
21#include <linux/init.h>
22#include <linux/interrupt.h>
23#include <linux/spinlock.h>
24#include <linux/delay.h>
25#include <mach/hardware.h>
26#include <linux/io.h>
27
28#include <asm/system.h>
29#include <asm/mach-types.h>
30#include <linux/semaphore.h>
31#include <linux/uaccess.h>
32#include <linux/clk.h>
33
34#include "msm_fb.h"
35#include "tvenc.h"
36
37#ifdef CONFIG_FB_MSM_TVOUT_PAL_M
38#define PAL_TV_DIMENSION_WIDTH 720
39#define PAL_TV_DIMENSION_HEIGHT 480
40#else
41#define PAL_TV_DIMENSION_WIDTH 720
42#define PAL_TV_DIMENSION_HEIGHT 576
43#endif
44
45static int pal_on(struct platform_device *pdev)
46{
47 uint32 reg = 0;
48 int ret = 0;
49 struct msm_fb_data_type *mfd;
50
51 mfd = platform_get_drvdata(pdev);
52
53 if (!mfd)
54 return -ENODEV;
55
56 if (mfd->key != MFD_KEY)
57 return -EINVAL;
58
59 TV_OUT(TV_ENC_CTL, 0); /* disable TV encoder */
60
61 switch (mfd->panel.id) {
62 case PAL_BDGHIN:
63 /* Cr gain 11, Cb gain C6, y_gain 97 */
64 TV_OUT(TV_GAIN, 0x0088c1a0);
65 TV_OUT(TV_CGMS, 0x00012345);
66 TV_OUT(TV_TEST_MUX, 0x0);
67 /* PAL Timing */
68 TV_OUT(TV_SYNC_1, 0x00180097);
69 TV_OUT(TV_SYNC_2, 0x011f06c0);
70 TV_OUT(TV_SYNC_3, 0x0005000a);
71 TV_OUT(TV_SYNC_4, 0x00320271);
72 TV_OUT(TV_SYNC_5, 0x005602f9);
73 TV_OUT(TV_SYNC_6, 0x0005000a);
74 TV_OUT(TV_SYNC_7, 0x0000000f);
75 TV_OUT(TV_BURST_V1, 0x0012026e);
76 TV_OUT(TV_BURST_V2, 0x0011026d);
77 TV_OUT(TV_BURST_V3, 0x00100270);
78 TV_OUT(TV_BURST_V4, 0x0013026f);
79 TV_OUT(TV_BURST_H, 0x00af00ea);
80 TV_OUT(TV_SOL_REQ_ODD, 0x0030026e);
81 TV_OUT(TV_SOL_REQ_EVEN, 0x0031026f);
82
83 reg |= TVENC_CTL_TV_MODE_PAL_BDGHIN;
84 break;
85 case PAL_M:
86 /* Cr gain 11, Cb gain C6, y_gain 97 */
87 TV_OUT(TV_GAIN, 0x0081b697);
88 TV_OUT(TV_CGMS, 0x000af317);
89 TV_OUT(TV_TEST_MUX, 0x000001c3);
90 TV_OUT(TV_TEST_MODE, 0x00000002);
91 /* PAL Timing */
92 TV_OUT(TV_SYNC_1, 0x0020009e);
93 TV_OUT(TV_SYNC_2, 0x011306b4);
94 TV_OUT(TV_SYNC_3, 0x0006000c);
95 TV_OUT(TV_SYNC_4, 0x0028020D);
96 TV_OUT(TV_SYNC_5, 0x005e02fb);
97 TV_OUT(TV_SYNC_6, 0x0006000c);
98 TV_OUT(TV_SYNC_7, 0x00000012);
99 TV_OUT(TV_BURST_V1, 0x0012020b);
100 TV_OUT(TV_BURST_V2, 0x0016020c);
101 TV_OUT(TV_BURST_V3, 0x00150209);
102 TV_OUT(TV_BURST_V4, 0x0013020c);
103 TV_OUT(TV_BURST_H, 0x00bf010b);
104 TV_OUT(TV_SOL_REQ_ODD, 0x00280208);
105 TV_OUT(TV_SOL_REQ_EVEN, 0x00290209);
106
107 reg |= TVENC_CTL_TV_MODE_PAL_M;
108 break;
109 case PAL_N:
110 /* Cr gain 11, Cb gain C6, y_gain 97 */
111 TV_OUT(TV_GAIN, 0x0081b697);
112 TV_OUT(TV_CGMS, 0x000af317);
113 TV_OUT(TV_TEST_MUX, 0x000001c3);
114 TV_OUT(TV_TEST_MODE, 0x00000002);
115 /* PAL Timing */
116 TV_OUT(TV_SYNC_1, 0x00180097);
117 TV_OUT(TV_SYNC_2, 0x12006c0);
118 TV_OUT(TV_SYNC_3, 0x0005000a);
119 TV_OUT(TV_SYNC_4, 0x00320271);
120 TV_OUT(TV_SYNC_5, 0x005602f9);
121 TV_OUT(TV_SYNC_6, 0x0005000a);
122 TV_OUT(TV_SYNC_7, 0x0000000f);
123 TV_OUT(TV_BURST_V1, 0x0012026e);
124 TV_OUT(TV_BURST_V2, 0x0011026d);
125 TV_OUT(TV_BURST_V3, 0x00100270);
126 TV_OUT(TV_BURST_V4, 0x0013026f);
127 TV_OUT(TV_BURST_H, 0x00af00fa);
128 TV_OUT(TV_SOL_REQ_ODD, 0x0030026e);
129 TV_OUT(TV_SOL_REQ_EVEN, 0x0031026f);
130
131 reg |= TVENC_CTL_TV_MODE_PAL_N;
132 break;
133
134 default:
135 return -ENODEV;
136 }
137
138 reg |= TVENC_CTL_Y_FILTER_EN |
139 TVENC_CTL_CR_FILTER_EN |
140 TVENC_CTL_CB_FILTER_EN | TVENC_CTL_SINX_FILTER_EN;
141#ifdef CONFIG_FB_MSM_TVOUT_SVIDEO
142 reg |= TVENC_CTL_S_VIDEO_EN;
143#endif
144
145 TV_OUT(TV_LEVEL, 0x00000000); /* DC offset to 0. */
146 TV_OUT(TV_OFFSET, 0x008080f0);
147
148#ifdef CONFIG_FB_MSM_MDP31
149 TV_OUT(TV_DAC_INTF, 0x29);
150#endif
151 TV_OUT(TV_ENC_CTL, reg);
152
153 reg |= TVENC_CTL_ENC_EN;
154 TV_OUT(TV_ENC_CTL, reg);
155
156 return ret;
157}
158
159static int pal_off(struct platform_device *pdev)
160{
161 TV_OUT(TV_ENC_CTL, 0); /* disable TV encoder */
162 return 0;
163}
164
165static int __init pal_probe(struct platform_device *pdev)
166{
167 msm_fb_add_device(pdev);
168
169 return 0;
170}
171
172static struct platform_driver this_driver = {
173 .probe = pal_probe,
174 .driver = {
175 .name = "tv_pal",
176 },
177};
178
179static struct msm_fb_panel_data pal_panel_data = {
180 .panel_info.xres = PAL_TV_DIMENSION_WIDTH,
181 .panel_info.yres = PAL_TV_DIMENSION_HEIGHT,
182 .panel_info.type = TV_PANEL,
183 .panel_info.pdest = DISPLAY_1,
184 .panel_info.wait_cycle = 0,
185 .panel_info.bpp = 16,
186 .panel_info.fb_num = 2,
187 .on = pal_on,
188 .off = pal_off,
189};
190
191static struct platform_device this_device = {
192 .name = "tv_pal",
193 .id = 0,
194 .dev = {
195 .platform_data = &pal_panel_data,
196 }
197};
198
199static int __init pal_init(void)
200{
201 int ret;
202
203 ret = platform_driver_register(&this_driver);
204 if (!ret) {
205 ret = platform_device_register(&this_device);
206 if (ret)
207 platform_driver_unregister(&this_driver);
208 }
209
210 return ret;
211}
212
213module_init(pal_init);
diff --git a/drivers/staging/msm/tvenc.c b/drivers/staging/msm/tvenc.c
new file mode 100644
index 000000000000..f41c5ac22f25
--- /dev/null
+++ b/drivers/staging/msm/tvenc.c
@@ -0,0 +1,295 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/sched.h>
21#include <linux/time.h>
22#include <linux/init.h>
23#include <linux/interrupt.h>
24#include <linux/spinlock.h>
25#include <linux/delay.h>
26#include <mach/hardware.h>
27#include <linux/io.h>
28
29#include <asm/system.h>
30#include <asm/mach-types.h>
31#include <linux/semaphore.h>
32#include <linux/uaccess.h>
33#include <linux/clk.h>
34#include <linux/platform_device.h>
35#include <linux/pm_qos_params.h>
36
37#define TVENC_C
38#include "tvenc.h"
39#include "msm_fb.h"
40
41static int tvenc_probe(struct platform_device *pdev);
42static int tvenc_remove(struct platform_device *pdev);
43
44static int tvenc_off(struct platform_device *pdev);
45static int tvenc_on(struct platform_device *pdev);
46
47static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
48static int pdev_list_cnt;
49
50static struct clk *tvenc_clk;
51static struct clk *tvdac_clk;
52
53static struct platform_driver tvenc_driver = {
54 .probe = tvenc_probe,
55 .remove = tvenc_remove,
56 .suspend = NULL,
57// .suspend_late = NULL,
58// .resume_early = NULL,
59 .resume = NULL,
60 .shutdown = NULL,
61 .driver = {
62 .name = "tvenc",
63 },
64};
65
66static struct tvenc_platform_data *tvenc_pdata;
67
68static int tvenc_off(struct platform_device *pdev)
69{
70 int ret = 0;
71
72 ret = panel_next_off(pdev);
73
74 clk_disable(tvenc_clk);
75 clk_disable(tvdac_clk);
76
77 if (tvenc_pdata && tvenc_pdata->pm_vid_en)
78 ret = tvenc_pdata->pm_vid_en(0);
79
80 //pm_qos_update_requirement(PM_QOS_SYSTEM_BUS_FREQ , "tvenc",
81 // PM_QOS_DEFAULT_VALUE);
82
83 if (ret)
84 printk(KERN_ERR "%s: pm_vid_en(off) failed! %d\n",
85 __func__, ret);
86
87 return ret;
88}
89
90static int tvenc_on(struct platform_device *pdev)
91{
92 int ret = 0;
93
94// pm_qos_update_requirement(PM_QOS_SYSTEM_BUS_FREQ , "tvenc",
95// 128000);
96 if (tvenc_pdata && tvenc_pdata->pm_vid_en)
97 ret = tvenc_pdata->pm_vid_en(1);
98
99 if (ret) {
100 printk(KERN_ERR "%s: pm_vid_en(on) failed! %d\n",
101 __func__, ret);
102 return ret;
103 }
104
105 clk_enable(tvenc_clk);
106 clk_enable(tvdac_clk);
107
108 ret = panel_next_on(pdev);
109
110 return ret;
111}
112
113void tvenc_gen_test_pattern(struct msm_fb_data_type *mfd)
114{
115 uint32 reg = 0, i;
116
117 reg = readl(MSM_TV_ENC_CTL);
118 reg |= TVENC_CTL_TEST_PATT_EN;
119
120 for (i = 0; i < 3; i++) {
121 TV_OUT(TV_ENC_CTL, 0); /* disable TV encoder */
122
123 switch (i) {
124 /*
125 * TV Encoder - Color Bar Test Pattern
126 */
127 case 0:
128 reg |= TVENC_CTL_TPG_CLRBAR;
129 break;
130 /*
131 * TV Encoder - Red Frame Test Pattern
132 */
133 case 1:
134 reg |= TVENC_CTL_TPG_REDCLR;
135 break;
136 /*
137 * TV Encoder - Modulated Ramp Test Pattern
138 */
139 default:
140 reg |= TVENC_CTL_TPG_MODRAMP;
141 break;
142 }
143
144 TV_OUT(TV_ENC_CTL, reg);
145 mdelay(5000);
146
147 switch (i) {
148 /*
149 * TV Encoder - Color Bar Test Pattern
150 */
151 case 0:
152 reg &= ~TVENC_CTL_TPG_CLRBAR;
153 break;
154 /*
155 * TV Encoder - Red Frame Test Pattern
156 */
157 case 1:
158 reg &= ~TVENC_CTL_TPG_REDCLR;
159 break;
160 /*
161 * TV Encoder - Modulated Ramp Test Pattern
162 */
163 default:
164 reg &= ~TVENC_CTL_TPG_MODRAMP;
165 break;
166 }
167 }
168}
169
170static int tvenc_resource_initialized;
171
172static int tvenc_probe(struct platform_device *pdev)
173{
174 struct msm_fb_data_type *mfd;
175 struct platform_device *mdp_dev = NULL;
176 struct msm_fb_panel_data *pdata = NULL;
177 int rc;
178
179 if (pdev->id == 0) {
180 tvenc_base = ioremap(pdev->resource[0].start,
181 pdev->resource[0].end -
182 pdev->resource[0].start + 1);
183 if (!tvenc_base) {
184 printk(KERN_ERR
185 "tvenc_base ioremap failed!\n");
186 return -ENOMEM;
187 }
188 tvenc_pdata = pdev->dev.platform_data;
189 tvenc_resource_initialized = 1;
190 return 0;
191 }
192
193 if (!tvenc_resource_initialized)
194 return -EPERM;
195
196 mfd = platform_get_drvdata(pdev);
197
198 if (!mfd)
199 return -ENODEV;
200
201 if (mfd->key != MFD_KEY)
202 return -EINVAL;
203
204 if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
205 return -ENOMEM;
206
207 if (tvenc_base == NULL)
208 return -ENOMEM;
209
210 mdp_dev = platform_device_alloc("mdp", pdev->id);
211 if (!mdp_dev)
212 return -ENOMEM;
213
214 /*
215 * link to the latest pdev
216 */
217 mfd->pdev = mdp_dev;
218 mfd->dest = DISPLAY_TV;
219
220 /*
221 * alloc panel device data
222 */
223 if (platform_device_add_data
224 (mdp_dev, pdev->dev.platform_data,
225 sizeof(struct msm_fb_panel_data))) {
226 printk(KERN_ERR "tvenc_probe: platform_device_add_data failed!\n");
227 platform_device_put(mdp_dev);
228 return -ENOMEM;
229 }
230 /*
231 * data chain
232 */
233 pdata = mdp_dev->dev.platform_data;
234 pdata->on = tvenc_on;
235 pdata->off = tvenc_off;
236 pdata->next = pdev;
237
238 /*
239 * get/set panel specific fb info
240 */
241 mfd->panel_info = pdata->panel_info;
242 mfd->fb_imgType = MDP_YCRYCB_H2V1;
243
244 /*
245 * set driver data
246 */
247 platform_set_drvdata(mdp_dev, mfd);
248
249 /*
250 * register in mdp driver
251 */
252 rc = platform_device_add(mdp_dev);
253 if (rc)
254 goto tvenc_probe_err;
255
256 pdev_list[pdev_list_cnt++] = pdev;
257 return 0;
258
259tvenc_probe_err:
260 platform_device_put(mdp_dev);
261 return rc;
262}
263
264static int tvenc_remove(struct platform_device *pdev)
265{
266// pm_qos_remove_requirement(PM_QOS_SYSTEM_BUS_FREQ , "tvenc");
267 return 0;
268}
269
270static int tvenc_register_driver(void)
271{
272 return platform_driver_register(&tvenc_driver);
273}
274
275static int __init tvenc_driver_init(void)
276{
277 tvenc_clk = clk_get(NULL, "tv_enc_clk");
278 tvdac_clk = clk_get(NULL, "tv_dac_clk");
279
280 if (IS_ERR(tvenc_clk)) {
281 printk(KERN_ERR "error: can't get tvenc_clk!\n");
282 return IS_ERR(tvenc_clk);
283 }
284
285 if (IS_ERR(tvdac_clk)) {
286 printk(KERN_ERR "error: can't get tvdac_clk!\n");
287 return IS_ERR(tvdac_clk);
288 }
289
290// pm_qos_add_requirement(PM_QOS_SYSTEM_BUS_FREQ , "tvenc",
291// PM_QOS_DEFAULT_VALUE);
292 return tvenc_register_driver();
293}
294
295module_init(tvenc_driver_init);
diff --git a/drivers/staging/msm/tvenc.h b/drivers/staging/msm/tvenc.h
new file mode 100644
index 000000000000..a682dbebcf7d
--- /dev/null
+++ b/drivers/staging/msm/tvenc.h
@@ -0,0 +1,117 @@
1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are met:
5 * * Redistributions of source code must retain the above copyright
6 * notice, this list of conditions and the following disclaimer.
7 * * Redistributions in binary form must reproduce the above copyright
8 * notice, this list of conditions and the following disclaimer in the
9 * documentation and/or other materials provided with the distribution.
10 * * Neither the name of Code Aurora nor
11 * the names of its contributors may be used to endorse or promote
12 * products derived from this software without specific prior written
13 * permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 */
28
29#ifndef TVENC_H
30#define TVENC_H
31
32#include <linux/kernel.h>
33#include <linux/sched.h>
34#include <linux/time.h>
35#include <linux/init.h>
36#include <linux/interrupt.h>
37#include <linux/fb.h>
38
39#include <mach/hardware.h>
40#include <linux/io.h>
41
42#include <asm/system.h>
43#include <asm/mach-types.h>
44
45#include "msm_fb_panel.h"
46
47#define NTSC_M 0 /* North America, Korea */
48#define NTSC_J 1 /* Japan */
49#define PAL_BDGHIN 2 /* Non-argentina PAL-N */
50#define PAL_M 3 /* PAL-M */
51#define PAL_N 4 /* Argentina PAL-N */
52
53/* 3.57954545 Mhz */
54#define TVENC_CTL_TV_MODE_NTSC_M_PAL60 0
55/* 3.57961149 Mhz */
56#define TVENC_CTL_TV_MODE_PAL_M BIT(0)
57/*non-Argintina = 4.3361875 Mhz */
58#define TVENC_CTL_TV_MODE_PAL_BDGHIN BIT(1)
59/*Argentina = 3.582055625 Mhz */
60#define TVENC_CTL_TV_MODE_PAL_N (BIT(1)|BIT(0))
61
62#define TVENC_CTL_ENC_EN BIT(2)
63#define TVENC_CTL_CC_EN BIT(3)
64#define TVENC_CTL_CGMS_EN BIT(4)
65#define TVENC_CTL_MACRO_EN BIT(5)
66#define TVENC_CTL_Y_FILTER_W_NOTCH BIT(6)
67#define TVENC_CTL_Y_FILTER_WO_NOTCH 0
68#define TVENC_CTL_Y_FILTER_EN BIT(7)
69#define TVENC_CTL_CR_FILTER_EN BIT(8)
70#define TVENC_CTL_CB_FILTER_EN BIT(9)
71#define TVENC_CTL_SINX_FILTER_EN BIT(10)
72#define TVENC_CTL_TEST_PATT_EN BIT(11)
73#define TVENC_CTL_OUTPUT_INV BIT(12)
74#define TVENC_CTL_PAL60_MODE BIT(13)
75#define TVENC_CTL_NTSCJ_MODE BIT(14)
76#define TVENC_CTL_TPG_CLRBAR 0
77#define TVENC_CTL_TPG_MODRAMP BIT(15)
78#define TVENC_CTL_TPG_REDCLR BIT(16)
79#define TVENC_CTL_S_VIDEO_EN BIT(19)
80
81#ifdef TVENC_C
82void *tvenc_base;
83#else
84extern void *tvenc_base;
85#endif
86
87#define TV_OUT(reg, v) writel(v, tvenc_base + MSM_##reg)
88
89#define MSM_TV_ENC_CTL 0x00
90#define MSM_TV_LEVEL 0x04
91#define MSM_TV_GAIN 0x08
92#define MSM_TV_OFFSET 0x0c
93#define MSM_TV_CGMS 0x10
94#define MSM_TV_SYNC_1 0x14
95#define MSM_TV_SYNC_2 0x18
96#define MSM_TV_SYNC_3 0x1c
97#define MSM_TV_SYNC_4 0x20
98#define MSM_TV_SYNC_5 0x24
99#define MSM_TV_SYNC_6 0x28
100#define MSM_TV_SYNC_7 0x2c
101#define MSM_TV_BURST_V1 0x30
102#define MSM_TV_BURST_V2 0x34
103#define MSM_TV_BURST_V3 0x38
104#define MSM_TV_BURST_V4 0x3c
105#define MSM_TV_BURST_H 0x40
106#define MSM_TV_SOL_REQ_ODD 0x44
107#define MSM_TV_SOL_REQ_EVEN 0x48
108#define MSM_TV_DAC_CTL 0x4c
109#define MSM_TV_TEST_MUX 0x50
110#define MSM_TV_TEST_MODE 0x54
111#define MSM_TV_TEST_MISR_RESET 0x58
112#define MSM_TV_TEST_EXPORT_MISR 0x5c
113#define MSM_TV_TEST_MISR_CURR_VAL 0x60
114#define MSM_TV_TEST_SOF_CFG 0x64
115#define MSM_TV_DAC_INTF 0x100
116
117#endif /* TVENC_H */
diff --git a/drivers/staging/phison/Kconfig b/drivers/staging/phison/Kconfig
index d3c65d315a2e..1b56119a7657 100644
--- a/drivers/staging/phison/Kconfig
+++ b/drivers/staging/phison/Kconfig
@@ -1,5 +1,5 @@
1config IDE_PHISON 1config IDE_PHISON
2 tristate "PCIE ATA PS5000 IDE support" 2 tristate "PCIE ATA PS5000 IDE support"
3 depends on PCI && ATA && ATA_SFF 3 depends on PCI && ATA && ATA_SFF && ATA_BMDMA
4 ---help--- 4 ---help---
5 This is an experimental driver for PS5000 IDE driver. 5 This is an experimental driver for PS5000 IDE driver.
diff --git a/drivers/staging/pohmelfs/inode.c b/drivers/staging/pohmelfs/inode.c
index 9286e863b0e7..643b413d9f0f 100644
--- a/drivers/staging/pohmelfs/inode.c
+++ b/drivers/staging/pohmelfs/inode.c
@@ -29,7 +29,6 @@
29#include <linux/slab.h> 29#include <linux/slab.h>
30#include <linux/statfs.h> 30#include <linux/statfs.h>
31#include <linux/writeback.h> 31#include <linux/writeback.h>
32#include <linux/quotaops.h>
33 32
34#include "netfs.h" 33#include "netfs.h"
35 34
@@ -880,7 +879,7 @@ static struct inode *pohmelfs_alloc_inode(struct super_block *sb)
880/* 879/*
881 * We want fsync() to work on POHMELFS. 880 * We want fsync() to work on POHMELFS.
882 */ 881 */
883static int pohmelfs_fsync(struct file *file, struct dentry *dentry, int datasync) 882static int pohmelfs_fsync(struct file *file, int datasync)
884{ 883{
885 struct inode *inode = file->f_mapping->host; 884 struct inode *inode = file->f_mapping->host;
886 struct writeback_control wbc = { 885 struct writeback_control wbc = {
@@ -969,13 +968,6 @@ int pohmelfs_setattr_raw(struct inode *inode, struct iattr *attr)
969 goto err_out_exit; 968 goto err_out_exit;
970 } 969 }
971 970
972 if ((attr->ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
973 (attr->ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) {
974 err = dquot_transfer(inode, attr);
975 if (err)
976 goto err_out_exit;
977 }
978
979 err = inode_setattr(inode, attr); 971 err = inode_setattr(inode, attr);
980 if (err) { 972 if (err) {
981 dprintk("%s: ino: %llu, failed to set the attributes.\n", __func__, POHMELFS_I(inode)->ino); 973 dprintk("%s: ino: %llu, failed to set the attributes.\n", __func__, POHMELFS_I(inode)->ino);
diff --git a/drivers/staging/rt2860/sta_ioctl.c b/drivers/staging/rt2860/sta_ioctl.c
index 112da7a6c417..6b8268d3dc75 100644
--- a/drivers/staging/rt2860/sta_ioctl.c
+++ b/drivers/staging/rt2860/sta_ioctl.c
@@ -2522,6 +2522,8 @@ int rt28xx_sta_ioctl(IN struct net_device *net_dev,
2522 Status = 2522 Status =
2523 copy_to_user(erq->pointer, pAd->nickname, 2523 copy_to_user(erq->pointer, pAd->nickname,
2524 erq->length); 2524 erq->length);
2525 if (Status)
2526 Status = -EFAULT;
2525 break; 2527 break;
2526 } 2528 }
2527 case SIOCGIWRATE: /*get default bit rate (bps) */ 2529 case SIOCGIWRATE: /*get default bit rate (bps) */
diff --git a/drivers/staging/sep/sep_driver.c b/drivers/staging/sep/sep_driver.c
index 0332c370fd82..ecbde3467b1b 100644
--- a/drivers/staging/sep/sep_driver.c
+++ b/drivers/staging/sep/sep_driver.c
@@ -594,8 +594,10 @@ static int sep_allocate_data_pool_memory_handler(struct sep_device *sep,
594 dbg("SEP Driver:--------> sep_allocate_data_pool_memory_handler start\n"); 594 dbg("SEP Driver:--------> sep_allocate_data_pool_memory_handler start\n");
595 595
596 error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_alloc_t)); 596 error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_alloc_t));
597 if (error) 597 if (error) {
598 error = -EFAULT;
598 goto end_function; 599 goto end_function;
600 }
599 601
600 /* allocate memory */ 602 /* allocate memory */
601 if ((sep->data_pool_bytes_allocated + command_args.num_bytes) > SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES) { 603 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,
609 611
610 /* write the memory back to the user space */ 612 /* write the memory back to the user space */
611 error = copy_to_user((void *) arg, (void *) &command_args, sizeof(struct sep_driver_alloc_t)); 613 error = copy_to_user((void *) arg, (void *) &command_args, sizeof(struct sep_driver_alloc_t));
612 if (error) 614 if (error) {
615 error = -EFAULT;
613 goto end_function; 616 goto end_function;
617 }
614 618
615 /* set the allocation */ 619 /* set the allocation */
616 sep->data_pool_bytes_allocated += command_args.num_bytes; 620 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
661 } 665 }
662 /* copy the application data */ 666 /* copy the application data */
663 error = copy_from_user(virt_address, (void *) app_in_address, num_bytes); 667 error = copy_from_user(virt_address, (void *) app_in_address, num_bytes);
668 if (error)
669 error = -EFAULT;
664end_function: 670end_function:
665 dbg("SEP Driver:<-------- sep_write_into_data_pool_handler end\n"); 671 dbg("SEP Driver:<-------- sep_write_into_data_pool_handler end\n");
666 return error; 672 return error;
@@ -711,6 +717,8 @@ static int sep_read_from_data_pool_handler(struct sep_device *sep, unsigned long
711 717
712 /* copy the application data */ 718 /* copy the application data */
713 error = copy_to_user((void *) app_out_address, virt_address, num_bytes); 719 error = copy_to_user((void *) app_out_address, virt_address, num_bytes);
720 if (error)
721 error = -EFAULT;
714end_function: 722end_function:
715 dbg("SEP Driver:<-------- sep_read_from_data_pool_handler end\n"); 723 dbg("SEP Driver:<-------- sep_read_from_data_pool_handler end\n");
716 return error; 724 return error;
@@ -1448,8 +1456,10 @@ static int sep_create_sync_dma_tables_handler(struct sep_device *sep,
1448 dbg("SEP Driver:--------> sep_create_sync_dma_tables_handler start\n"); 1456 dbg("SEP Driver:--------> sep_create_sync_dma_tables_handler start\n");
1449 1457
1450 error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_build_sync_table_t)); 1458 error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_build_sync_table_t));
1451 if (error) 1459 if (error) {
1460 error = -EFAULT;
1452 goto end_function; 1461 goto end_function;
1462 }
1453 1463
1454 edbg("app_in_address is %08lx\n", command_args.app_in_address); 1464 edbg("app_in_address is %08lx\n", command_args.app_in_address);
1455 edbg("app_out_address is %08lx\n", command_args.app_out_address); 1465 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,
1799 goto end_function; 1809 goto end_function;
1800 1810
1801 error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_build_flow_table_t)); 1811 error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_build_flow_table_t));
1802 if (error) 1812 if (error) {
1813 error = -EFAULT;
1803 goto end_function; 1814 goto end_function;
1815 }
1804 1816
1805 /* create flow tables */ 1817 /* create flow tables */
1806 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); 1818 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,
1819 1831
1820 /* send the parameters to user application */ 1832 /* send the parameters to user application */
1821 error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_build_flow_table_t)); 1833 error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_build_flow_table_t));
1822 if (error) 1834 if (error) {
1835 error = -EFAULT;
1823 goto end_function_with_error; 1836 goto end_function_with_error;
1837 }
1824 1838
1825 /* all the flow created - update the flow entry with temp id */ 1839 /* all the flow created - update the flow entry with temp id */
1826 flow_context_ptr->flow_id = SEP_TEMP_FLOW_ID; 1840 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
1861 1875
1862 /* get input parameters */ 1876 /* get input parameters */
1863 error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_add_flow_table_t)); 1877 error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_add_flow_table_t));
1864 if (error) 1878 if (error) {
1879 error = -EFAULT;
1865 goto end_function; 1880 goto end_function;
1881 }
1866 1882
1867 /* find the flow structure for the flow id */ 1883 /* find the flow structure for the flow id */
1868 flow_context_ptr = sep_find_flow_context(sep, command_args.flow_id); 1884 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
1933 1949
1934 /* send the parameters to user application */ 1950 /* send the parameters to user application */
1935 error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_add_flow_table_t)); 1951 error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_add_flow_table_t));
1952 if (error)
1953 error = -EFAULT;
1936end_function_with_error: 1954end_function_with_error:
1937 /* free the allocated tables */ 1955 /* free the allocated tables */
1938 sep_deallocated_flow_tables(&first_table_data); 1956 sep_deallocated_flow_tables(&first_table_data);
@@ -1953,8 +1971,10 @@ static int sep_add_flow_tables_message_handler(struct sep_device *sep, unsigned
1953 dbg("SEP Driver:--------> sep_add_flow_tables_message_handler start\n"); 1971 dbg("SEP Driver:--------> sep_add_flow_tables_message_handler start\n");
1954 1972
1955 error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_add_message_t)); 1973 error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_add_message_t));
1956 if (error) 1974 if (error) {
1975 error = -EFAULT;
1957 goto end_function; 1976 goto end_function;
1977 }
1958 1978
1959 /* check input */ 1979 /* check input */
1960 if (command_args.message_size_in_bytes > SEP_MAX_ADD_MESSAGE_LENGTH_IN_BYTES) { 1980 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
1970 /* copy the message into context */ 1990 /* copy the message into context */
1971 flow_context_ptr->message_size_in_bytes = command_args.message_size_in_bytes; 1991 flow_context_ptr->message_size_in_bytes = command_args.message_size_in_bytes;
1972 error = copy_from_user(flow_context_ptr->message, (void *) command_args.message_address, command_args.message_size_in_bytes); 1992 error = copy_from_user(flow_context_ptr->message, (void *) command_args.message_address, command_args.message_size_in_bytes);
1993 if (error)
1994 error = -EFAULT;
1973end_function: 1995end_function:
1974 dbg("SEP Driver:<-------- sep_add_flow_tables_message_handler end\n"); 1996 dbg("SEP Driver:<-------- sep_add_flow_tables_message_handler end\n");
1975 return error; 1997 return error;
@@ -1994,6 +2016,8 @@ static int sep_get_static_pool_addr_handler(struct sep_device *sep, unsigned lon
1994 2016
1995 /* send the parameters to user application */ 2017 /* send the parameters to user application */
1996 error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_static_pool_addr_t)); 2018 error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_static_pool_addr_t));
2019 if (error)
2020 error = -EFAULT;
1997 dbg("SEP Driver:<-------- sep_get_static_pool_addr_handler end\n"); 2021 dbg("SEP Driver:<-------- sep_get_static_pool_addr_handler end\n");
1998 return error; 2022 return error;
1999} 2023}
@@ -2010,8 +2034,10 @@ static int sep_get_physical_mapped_offset_handler(struct sep_device *sep, unsign
2010 dbg("SEP Driver:--------> sep_get_physical_mapped_offset_handler start\n"); 2034 dbg("SEP Driver:--------> sep_get_physical_mapped_offset_handler start\n");
2011 2035
2012 error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_get_mapped_offset_t)); 2036 error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_get_mapped_offset_t));
2013 if (error) 2037 if (error) {
2038 error = -EFAULT;
2014 goto end_function; 2039 goto end_function;
2040 }
2015 2041
2016 if (command_args.physical_address < sep->shared_bus) { 2042 if (command_args.physical_address < sep->shared_bus) {
2017 error = -EINVAL; 2043 error = -EINVAL;
@@ -2025,6 +2051,8 @@ static int sep_get_physical_mapped_offset_handler(struct sep_device *sep, unsign
2025 2051
2026 /* send the parameters to user application */ 2052 /* send the parameters to user application */
2027 error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_get_mapped_offset_t)); 2053 error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_get_mapped_offset_t));
2054 if (error)
2055 error = -EFAULT;
2028end_function: 2056end_function:
2029 dbg("SEP Driver:<-------- sep_get_physical_mapped_offset_handler end\n"); 2057 dbg("SEP Driver:<-------- sep_get_physical_mapped_offset_handler end\n");
2030 return error; 2058 return error;
@@ -2070,11 +2098,11 @@ static int sep_init_handler(struct sep_device *sep, unsigned long arg)
2070 error = 0; 2098 error = 0;
2071 2099
2072 error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_init_t)); 2100 error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_init_t));
2073 2101 if (error) {
2074 dbg("SEP Driver:--------> sep_init_handler - finished copy_from_user \n"); 2102 error = -EFAULT;
2075
2076 if (error)
2077 goto end_function; 2103 goto end_function;
2104 }
2105 dbg("SEP Driver:--------> sep_init_handler - finished copy_from_user\n");
2078 2106
2079 /* PATCH - configure the DMA to single -burst instead of multi-burst */ 2107 /* PATCH - configure the DMA to single -burst instead of multi-burst */
2080 /*sep_configure_dma_burst(); */ 2108 /*sep_configure_dma_burst(); */
diff --git a/drivers/staging/tm6000/Kconfig b/drivers/staging/tm6000/Kconfig
index 5fe759cc2ee9..3657e33e8817 100644
--- a/drivers/staging/tm6000/Kconfig
+++ b/drivers/staging/tm6000/Kconfig
@@ -2,7 +2,8 @@ config VIDEO_TM6000
2 tristate "TV Master TM5600/6000/6010 driver" 2 tristate "TV Master TM5600/6000/6010 driver"
3 depends on VIDEO_DEV && I2C && INPUT && USB && EXPERIMENTAL 3 depends on VIDEO_DEV && I2C && INPUT && USB && EXPERIMENTAL
4 select VIDEO_TUNER 4 select VIDEO_TUNER
5 select TUNER_XC2028 5 select MEDIA_TUNER_XC2028
6 select MEDIA_TUNER_XC5000
6 select VIDEOBUF_VMALLOC 7 select VIDEOBUF_VMALLOC
7 help 8 help
8 Support for TM5600/TM6000/TM6010 USB Device 9 Support for TM5600/TM6000/TM6010 USB Device
diff --git a/drivers/staging/tm6000/tm6000-alsa.c b/drivers/staging/tm6000/tm6000-alsa.c
index bc89f9d28002..ce081cd44ad4 100644
--- a/drivers/staging/tm6000/tm6000-alsa.c
+++ b/drivers/staging/tm6000/tm6000-alsa.c
@@ -410,5 +410,28 @@ error:
410 snd_card_free(card); 410 snd_card_free(card);
411 return rc; 411 return rc;
412} 412}
413EXPORT_SYMBOL_GPL(tm6000_audio_init);
414 413
414static int tm6000_audio_fini(struct tm6000_core *dev)
415{
416 return 0;
417}
418
419struct tm6000_ops audio_ops = {
420 .id = TM6000_AUDIO,
421 .name = "TM6000 Audio Extension",
422 .init = tm6000_audio_init,
423 .fini = tm6000_audio_fini,
424};
425
426static int __init tm6000_alsa_register(void)
427{
428 return tm6000_register_extension(&audio_ops);
429}
430
431static void __exit tm6000_alsa_unregister(void)
432{
433 tm6000_unregister_extension(&audio_ops);
434}
435
436module_init(tm6000_alsa_register);
437module_exit(tm6000_alsa_unregister);
diff --git a/drivers/staging/tm6000/tm6000-cards.c b/drivers/staging/tm6000/tm6000-cards.c
index 6143e20d139d..cedd9044022f 100644
--- a/drivers/staging/tm6000/tm6000-cards.c
+++ b/drivers/staging/tm6000/tm6000-cards.c
@@ -363,13 +363,7 @@ int tm6000_tuner_callback(void *ptr, int component, int command, int arg)
363 tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 363 tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT,
364 0x02, arg); 364 0x02, arg);
365 msleep(10); 365 msleep(10);
366 rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, 366 rc = tm6000_i2c_reset(dev, 10);
367 TM6000_GPIO_CLK, 0);
368 if (rc < 0)
369 return rc;
370 msleep(10);
371 rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
372 TM6000_GPIO_CLK, 1);
373 break; 367 break;
374 case XC2028_TUNER_RESET: 368 case XC2028_TUNER_RESET:
375 /* Reset codes during load firmware */ 369 /* Reset codes during load firmware */
@@ -423,14 +417,7 @@ int tm6000_tuner_callback(void *ptr, int component, int command, int arg)
423 break; 417 break;
424 418
425 case 2: 419 case 2:
426 rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, 420 rc = tm6000_i2c_reset(dev, 100);
427 TM6000_GPIO_CLK, 0);
428 if (rc < 0)
429 return rc;
430 msleep(100);
431 rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
432 TM6000_GPIO_CLK, 1);
433 msleep(100);
434 break; 421 break;
435 } 422 }
436 } 423 }
@@ -563,7 +550,7 @@ static void tm6000_config_tuner(struct tm6000_core *dev)
563 550
564 switch (dev->tuner_type) { 551 switch (dev->tuner_type) {
565 case TUNER_XC2028: 552 case TUNER_XC2028:
566 tun_setup.tuner_callback = tm6000_tuner_callback;; 553 tun_setup.tuner_callback = tm6000_tuner_callback;
567 break; 554 break;
568 case TUNER_XC5000: 555 case TUNER_XC5000:
569 tun_setup.tuner_callback = tm6000_xc5000_callback; 556 tun_setup.tuner_callback = tm6000_xc5000_callback;
@@ -692,6 +679,10 @@ static int tm6000_init_dev(struct tm6000_core *dev)
692 if (rc < 0) 679 if (rc < 0)
693 goto err; 680 goto err;
694 681
682 tm6000_add_into_devlist(dev);
683
684 tm6000_init_extension(dev);
685
695 if (dev->caps.has_dvb) { 686 if (dev->caps.has_dvb) {
696 dev->dvb = kzalloc(sizeof(*(dev->dvb)), GFP_KERNEL); 687 dev->dvb = kzalloc(sizeof(*(dev->dvb)), GFP_KERNEL);
697 if (!dev->dvb) { 688 if (!dev->dvb) {
@@ -921,6 +912,25 @@ static void tm6000_usb_disconnect(struct usb_interface *interface)
921 } 912 }
922#endif 913#endif
923 914
915 if (dev->gpio.power_led) {
916 switch (dev->model) {
917 case TM6010_BOARD_HAUPPAUGE_900H:
918 case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
919 case TM6010_BOARD_TWINHAN_TU501:
920 /* Power led off */
921 tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
922 dev->gpio.power_led, 0x01);
923 msleep(15);
924 break;
925 case TM6010_BOARD_BEHOLD_WANDER:
926 case TM6010_BOARD_BEHOLD_VOYAGER:
927 /* Power led off */
928 tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
929 dev->gpio.power_led, 0x00);
930 msleep(15);
931 break;
932 }
933 }
924 tm6000_v4l2_unregister(dev); 934 tm6000_v4l2_unregister(dev);
925 935
926 tm6000_i2c_unregister(dev); 936 tm6000_i2c_unregister(dev);
@@ -931,6 +941,9 @@ static void tm6000_usb_disconnect(struct usb_interface *interface)
931 941
932 usb_put_dev(dev->udev); 942 usb_put_dev(dev->udev);
933 943
944 tm6000_remove_from_devlist(dev);
945 tm6000_close_extension(dev);
946
934 mutex_unlock(&dev->lock); 947 mutex_unlock(&dev->lock);
935 kfree(dev); 948 kfree(dev);
936} 949}
diff --git a/drivers/staging/tm6000/tm6000-core.c b/drivers/staging/tm6000/tm6000-core.c
index bfbc53bd2912..27f3f551b545 100644
--- a/drivers/staging/tm6000/tm6000-core.c
+++ b/drivers/staging/tm6000/tm6000-core.c
@@ -153,6 +153,22 @@ int tm6000_get_reg32 (struct tm6000_core *dev, u8 req, u16 value, u16 index)
153 return buf[3] | buf[2] << 8 | buf[1] << 16 | buf[0] << 24; 153 return buf[3] | buf[2] << 8 | buf[1] << 16 | buf[0] << 24;
154} 154}
155 155
156int tm6000_i2c_reset(struct tm6000_core *dev, u16 tsleep)
157{
158 int rc;
159
160 rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 0);
161 if (rc < 0)
162 return rc;
163
164 msleep(tsleep);
165
166 rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 1);
167 msleep(tsleep);
168
169 return rc;
170}
171
156void tm6000_set_fourcc_format(struct tm6000_core *dev) 172void tm6000_set_fourcc_format(struct tm6000_core *dev)
157{ 173{
158 if (dev->dev_type == TM6010) { 174 if (dev->dev_type == TM6010) {
@@ -323,6 +339,12 @@ int tm6000_init_analog_mode (struct tm6000_core *dev)
323 tm6000_set_standard (dev, &dev->norm); 339 tm6000_set_standard (dev, &dev->norm);
324 tm6000_set_audio_bitrate (dev,48000); 340 tm6000_set_audio_bitrate (dev,48000);
325 341
342 /* switch dvb led off */
343 if (dev->gpio.dvb_led) {
344 tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
345 dev->gpio.dvb_led, 0x01);
346 }
347
326 return 0; 348 return 0;
327} 349}
328 350
@@ -375,6 +397,13 @@ int tm6000_init_digital_mode (struct tm6000_core *dev)
375 tm6000_set_reg (dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x00); 397 tm6000_set_reg (dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x00);
376 msleep(100); 398 msleep(100);
377 } 399 }
400
401 /* switch dvb led on */
402 if (dev->gpio.dvb_led) {
403 tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
404 dev->gpio.dvb_led, 0x00);
405 }
406
378 return 0; 407 return 0;
379} 408}
380 409
@@ -600,3 +629,95 @@ printk("Original value=%d\n",val);
600 return val; 629 return val;
601} 630}
602EXPORT_SYMBOL_GPL(tm6000_set_audio_bitrate); 631EXPORT_SYMBOL_GPL(tm6000_set_audio_bitrate);
632
633static LIST_HEAD(tm6000_devlist);
634static DEFINE_MUTEX(tm6000_devlist_mutex);
635
636/*
637 * tm6000_realease_resource()
638 */
639
640void tm6000_remove_from_devlist(struct tm6000_core *dev)
641{
642 mutex_lock(&tm6000_devlist_mutex);
643 list_del(&dev->devlist);
644 mutex_unlock(&tm6000_devlist_mutex);
645};
646
647void tm6000_add_into_devlist(struct tm6000_core *dev)
648{
649 mutex_lock(&tm6000_devlist_mutex);
650 list_add_tail(&dev->devlist, &tm6000_devlist);
651 mutex_unlock(&tm6000_devlist_mutex);
652};
653
654/*
655 * Extension interface
656 */
657
658static LIST_HEAD(tm6000_extension_devlist);
659static DEFINE_MUTEX(tm6000_extension_devlist_lock);
660
661int tm6000_register_extension(struct tm6000_ops *ops)
662{
663 struct tm6000_core *dev = NULL;
664
665 mutex_lock(&tm6000_devlist_mutex);
666 mutex_lock(&tm6000_extension_devlist_lock);
667 list_add_tail(&ops->next, &tm6000_extension_devlist);
668 list_for_each_entry(dev, &tm6000_devlist, devlist) {
669 if (dev)
670 ops->init(dev);
671 }
672 printk(KERN_INFO "tm6000: Initialized (%s) extension\n", ops->name);
673 mutex_unlock(&tm6000_extension_devlist_lock);
674 mutex_unlock(&tm6000_devlist_mutex);
675 return 0;
676}
677EXPORT_SYMBOL(tm6000_register_extension);
678
679void tm6000_unregister_extension(struct tm6000_ops *ops)
680{
681 struct tm6000_core *dev = NULL;
682
683 mutex_lock(&tm6000_devlist_mutex);
684 list_for_each_entry(dev, &tm6000_devlist, devlist) {
685 if (dev)
686 ops->fini(dev);
687 }
688
689 mutex_lock(&tm6000_extension_devlist_lock);
690 printk(KERN_INFO "tm6000: Remove (%s) extension\n", ops->name);
691 list_del(&ops->next);
692 mutex_unlock(&tm6000_extension_devlist_lock);
693 mutex_unlock(&tm6000_devlist_mutex);
694}
695EXPORT_SYMBOL(tm6000_unregister_extension);
696
697void tm6000_init_extension(struct tm6000_core *dev)
698{
699 struct tm6000_ops *ops = NULL;
700
701 mutex_lock(&tm6000_extension_devlist_lock);
702 if (!list_empty(&tm6000_extension_devlist)) {
703 list_for_each_entry(ops, &tm6000_extension_devlist, next) {
704 if (ops->init)
705 ops->init(dev);
706 }
707 }
708 mutex_unlock(&tm6000_extension_devlist_lock);
709}
710
711void tm6000_close_extension(struct tm6000_core *dev)
712{
713 struct tm6000_ops *ops = NULL;
714
715 mutex_lock(&tm6000_extension_devlist_lock);
716 if (!list_empty(&tm6000_extension_devlist)) {
717 list_for_each_entry(ops, &tm6000_extension_devlist, next) {
718 if (ops->fini)
719 ops->fini(dev);
720 }
721 }
722 mutex_unlock(&tm6000_extension_devlist_lock);
723}
diff --git a/drivers/staging/tm6000/tm6000-dvb.c b/drivers/staging/tm6000/tm6000-dvb.c
index eafc89c22b6b..261e66acbe46 100644
--- a/drivers/staging/tm6000/tm6000-dvb.c
+++ b/drivers/staging/tm6000/tm6000-dvb.c
@@ -28,6 +28,7 @@
28#include <media/tuner.h> 28#include <media/tuner.h>
29 29
30#include "tuner-xc2028.h" 30#include "tuner-xc2028.h"
31#include "xc5000.h"
31 32
32static void inline print_err_status (struct tm6000_core *dev, 33static void inline print_err_status (struct tm6000_core *dev,
33 int packet, int status) 34 int packet, int status)
@@ -100,7 +101,10 @@ int tm6000_start_stream(struct tm6000_core *dev)
100 101
101 printk(KERN_INFO "tm6000: got start stream request %s\n",__FUNCTION__); 102 printk(KERN_INFO "tm6000: got start stream request %s\n",__FUNCTION__);
102 103
103 tm6000_init_digital_mode(dev); 104 if (dev->mode != TM6000_MODE_DIGITAL) {
105 tm6000_init_digital_mode(dev);
106 dev->mode = TM6000_MODE_DIGITAL;
107 }
104 108
105 dvb->bulk_urb = usb_alloc_urb(0, GFP_KERNEL); 109 dvb->bulk_urb = usb_alloc_urb(0, GFP_KERNEL);
106 if(dvb->bulk_urb == NULL) { 110 if(dvb->bulk_urb == NULL) {
@@ -254,27 +258,55 @@ int tm6000_dvb_register(struct tm6000_core *dev)
254 dvb->adapter.priv = dev; 258 dvb->adapter.priv = dev;
255 259
256 if (dvb->frontend) { 260 if (dvb->frontend) {
257 struct xc2028_config cfg = { 261 switch (dev->tuner_type) {
258 .i2c_adap = &dev->i2c_adap, 262 case TUNER_XC2028: {
259 .i2c_addr = dev->tuner_addr, 263 struct xc2028_config cfg = {
260 }; 264 .i2c_adap = &dev->i2c_adap,
261 265 .i2c_addr = dev->tuner_addr,
262 dvb->frontend->callback = tm6000_tuner_callback; 266 };
263 ret = dvb_register_frontend(&dvb->adapter, dvb->frontend); 267
264 if (ret < 0) { 268 dvb->frontend->callback = tm6000_tuner_callback;
265 printk(KERN_ERR 269 ret = dvb_register_frontend(&dvb->adapter, dvb->frontend);
266 "tm6000: couldn't register frontend\n"); 270 if (ret < 0) {
267 goto adapter_err; 271 printk(KERN_ERR
268 } 272 "tm6000: couldn't register frontend\n");
269 273 goto adapter_err;
270 if (!dvb_attach(xc2028_attach, dvb->frontend, &cfg)) { 274 }
271 printk(KERN_ERR "tm6000: couldn't register " 275
272 "frontend (xc3028)\n"); 276 if (!dvb_attach(xc2028_attach, dvb->frontend, &cfg)) {
273 ret = -EINVAL; 277 printk(KERN_ERR "tm6000: couldn't register "
274 goto frontend_err; 278 "frontend (xc3028)\n");
279 ret = -EINVAL;
280 goto frontend_err;
281 }
282 printk(KERN_INFO "tm6000: XC2028/3028 asked to be "
283 "attached to frontend!\n");
284 break;
285 }
286 case TUNER_XC5000: {
287 struct xc5000_config cfg = {
288 .i2c_address = dev->tuner_addr,
289 };
290
291 dvb->frontend->callback = tm6000_xc5000_callback;
292 ret = dvb_register_frontend(&dvb->adapter, dvb->frontend);
293 if (ret < 0) {
294 printk(KERN_ERR
295 "tm6000: couldn't register frontend\n");
296 goto adapter_err;
297 }
298
299 if (!dvb_attach(xc5000_attach, dvb->frontend, &dev->i2c_adap, &cfg)) {
300 printk(KERN_ERR "tm6000: couldn't register "
301 "frontend (xc5000)\n");
302 ret = -EINVAL;
303 goto frontend_err;
304 }
305 printk(KERN_INFO "tm6000: XC5000 asked to be "
306 "attached to frontend!\n");
307 break;
308 }
275 } 309 }
276 printk(KERN_INFO "tm6000: XC2028/3028 asked to be "
277 "attached to frontend!\n");
278 } else { 310 } else {
279 printk(KERN_ERR "tm6000: no frontend found\n"); 311 printk(KERN_ERR "tm6000: no frontend found\n");
280 } 312 }
diff --git a/drivers/staging/tm6000/tm6000-video.c b/drivers/staging/tm6000/tm6000-video.c
index f2b7fe4a3581..56fa371e08c8 100644
--- a/drivers/staging/tm6000/tm6000-video.c
+++ b/drivers/staging/tm6000/tm6000-video.c
@@ -48,7 +48,7 @@
48#define TM6000_MIN_BUF 4 48#define TM6000_MIN_BUF 4
49#define TM6000_DEF_BUF 8 49#define TM6000_DEF_BUF 8
50 50
51#define TM6000_MAX_ISO_PACKETS 40 /* Max number of ISO packets */ 51#define TM6000_MAX_ISO_PACKETS 46 /* Max number of ISO packets */
52 52
53/* Declare static vars that will be used as parameters */ 53/* Declare static vars that will be used as parameters */
54static unsigned int vid_limit = 16; /* Video memory limit, in Mb */ 54static 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,
205 c = (header >> 24) & 0xff; 205 c = (header >> 24) & 0xff;
206 206
207 /* split the header fields */ 207 /* split the header fields */
208 size = (((header & 0x7e) << 1) -1) *4; 208 size = ((header & 0x7e) << 1);
209
210 if (size > 0)
211 size -= 4;
212
209 block = (header >> 7) & 0xf; 213 block = (header >> 7) & 0xf;
210 field = (header >> 11) & 0x1; 214 field = (header >> 11) & 0x1;
211 line = (header >> 12) & 0x1ff; 215 line = (header >> 12) & 0x1ff;
@@ -307,10 +311,12 @@ static int copy_packet(struct urb *urb, u32 header, u8 **ptr, u8 *endp,
307 case TM6000_URB_MSG_PTS: 311 case TM6000_URB_MSG_PTS:
308 break; 312 break;
309 case TM6000_URB_MSG_AUDIO: 313 case TM6000_URB_MSG_AUDIO:
310/* Need some code to process audio */ 314 /* Need some code to process audio */
311printk ("%ld: cmd=%s, size=%d\n", jiffies, 315 printk ("%ld: cmd=%s, size=%d\n", jiffies,
312 tm6000_msg_type[cmd],size); 316 tm6000_msg_type[cmd],size);
313 break; 317 break;
318 case TM6000_URB_MSG_VBI:
319 break;
314 default: 320 default:
315 dprintk (dev, V4L2_DEBUG_ISOC, "cmd=%s, size=%d\n", 321 dprintk (dev, V4L2_DEBUG_ISOC, "cmd=%s, size=%d\n",
316 tm6000_msg_type[cmd],size); 322 tm6000_msg_type[cmd],size);
@@ -333,14 +339,23 @@ printk ("%ld: cmd=%s, size=%d\n", jiffies,
333 return rc; 339 return rc;
334} 340}
335 341
336static int copy_streams(u8 *data, u8 *out_p, unsigned long len, 342static int copy_streams(u8 *data, unsigned long len,
337 struct urb *urb, struct tm6000_buffer **buf) 343 struct urb *urb)
338{ 344{
339 struct tm6000_dmaqueue *dma_q = urb->context; 345 struct tm6000_dmaqueue *dma_q = urb->context;
340 struct tm6000_core *dev= container_of(dma_q,struct tm6000_core,vidq); 346 struct tm6000_core *dev= container_of(dma_q,struct tm6000_core,vidq);
341 u8 *ptr=data, *endp=data+len; 347 u8 *ptr=data, *endp=data+len;
342 unsigned long header=0; 348 unsigned long header=0;
343 int rc=0; 349 int rc=0;
350 struct tm6000_buffer *buf;
351 char *outp = NULL;
352
353 get_next_buf(dma_q, &buf);
354 if (buf)
355 outp = videobuf_to_vmalloc(&buf->vb);
356
357 if (!outp)
358 return 0;
344 359
345 for (ptr=data; ptr<endp;) { 360 for (ptr=data; ptr<endp;) {
346 if (!dev->isoc_ctl.cmd) { 361 if (!dev->isoc_ctl.cmd) {
@@ -388,14 +403,14 @@ static int copy_streams(u8 *data, u8 *out_p, unsigned long len,
388 } 403 }
389HEADER: 404HEADER:
390 /* Copy or continue last copy */ 405 /* Copy or continue last copy */
391 rc=copy_packet(urb,header,&ptr,endp,out_p,buf); 406 rc=copy_packet(urb,header,&ptr,endp,outp,&buf);
392 if (rc<0) { 407 if (rc<0) {
393 buf=NULL; 408 buf=NULL;
394 printk(KERN_ERR "tm6000: buffer underrun at %ld\n", 409 printk(KERN_ERR "tm6000: buffer underrun at %ld\n",
395 jiffies); 410 jiffies);
396 return rc; 411 return rc;
397 } 412 }
398 if (!*buf) 413 if (!buf)
399 return 0; 414 return 0;
400 } 415 }
401 416
@@ -404,31 +419,40 @@ HEADER:
404/* 419/*
405 * Identify the tm5600/6000 buffer header type and properly handles 420 * Identify the tm5600/6000 buffer header type and properly handles
406 */ 421 */
407static int copy_multiplexed(u8 *ptr, u8 *out_p, unsigned long len, 422static int copy_multiplexed(u8 *ptr, unsigned long len,
408 struct urb *urb, struct tm6000_buffer **buf) 423 struct urb *urb)
409{ 424{
410 struct tm6000_dmaqueue *dma_q = urb->context; 425 struct tm6000_dmaqueue *dma_q = urb->context;
411 struct tm6000_core *dev= container_of(dma_q,struct tm6000_core,vidq); 426 struct tm6000_core *dev= container_of(dma_q,struct tm6000_core,vidq);
412 unsigned int pos=dev->isoc_ctl.pos,cpysize; 427 unsigned int pos=dev->isoc_ctl.pos,cpysize;
413 int rc=1; 428 int rc=1;
429 struct tm6000_buffer *buf;
430 char *outp = NULL;
431
432 get_next_buf(dma_q, &buf);
433 if (buf)
434 outp = videobuf_to_vmalloc(&buf->vb);
435
436 if (!outp)
437 return 0;
414 438
415 while (len>0) { 439 while (len>0) {
416 cpysize=min(len,(*buf)->vb.size-pos); 440 cpysize=min(len,buf->vb.size-pos);
417//printk("Copying %d bytes (max=%lu) from %p to %p[%u]\n",cpysize,(*buf)->vb.size,ptr,out_p,pos); 441 //printk("Copying %d bytes (max=%lu) from %p to %p[%u]\n",cpysize,(*buf)->vb.size,ptr,out_p,pos);
418 memcpy(&out_p[pos], ptr, cpysize); 442 memcpy(&outp[pos], ptr, cpysize);
419 pos+=cpysize; 443 pos+=cpysize;
420 ptr+=cpysize; 444 ptr+=cpysize;
421 len-=cpysize; 445 len-=cpysize;
422 if (pos >= (*buf)->vb.size) { 446 if (pos >= buf->vb.size) {
423 pos=0; 447 pos=0;
424 /* Announces that a new buffer were filled */ 448 /* Announces that a new buffer were filled */
425 buffer_filled (dev, dma_q, *buf); 449 buffer_filled (dev, dma_q, buf);
426 dprintk(dev, V4L2_DEBUG_ISOC, "new buffer filled\n"); 450 dprintk(dev, V4L2_DEBUG_ISOC, "new buffer filled\n");
427 get_next_buf (dma_q, buf); 451 get_next_buf (dma_q, &buf);
428 if (!*buf) 452 if (!buf)
429 break; 453 break;
430 out_p = videobuf_to_vmalloc(&((*buf)->vb)); 454 outp = videobuf_to_vmalloc(&(buf->vb));
431 if (!out_p) 455 if (!outp)
432 return rc; 456 return rc;
433 pos = 0; 457 pos = 0;
434 } 458 }
@@ -487,52 +511,36 @@ static inline int tm6000_isoc_copy(struct urb *urb)
487 struct tm6000_dmaqueue *dma_q = urb->context; 511 struct tm6000_dmaqueue *dma_q = urb->context;
488 struct tm6000_core *dev= container_of(dma_q,struct tm6000_core,vidq); 512 struct tm6000_core *dev= container_of(dma_q,struct tm6000_core,vidq);
489 struct tm6000_buffer *buf; 513 struct tm6000_buffer *buf;
490 int i, len=0, rc=1; 514 int i, len=0, rc=1, status;
491 int size; 515 char *p;
492 char *outp = NULL, *p;
493 unsigned long copied;
494
495 get_next_buf(dma_q, &buf);
496 if (buf)
497 outp = videobuf_to_vmalloc(&buf->vb);
498 516
499 if (!outp) 517 if (urb->status < 0) {
500 return 0; 518 print_err_status (dev, -1, urb->status);
501
502 size = buf->vb.size;
503
504 copied=0;
505
506 if (urb->status<0) {
507 print_err_status (dev,-1,urb->status);
508 return 0; 519 return 0;
509 } 520 }
510 521
511 for (i = 0; i < urb->number_of_packets; i++) { 522 for (i = 0; i < urb->number_of_packets; i++) {
512 int status = urb->iso_frame_desc[i].status; 523 status = urb->iso_frame_desc[i].status;
513 524
514 if (status<0) { 525 if (status<0) {
515 print_err_status (dev,i,status); 526 print_err_status (dev,i,status);
516 continue; 527 continue;
517 } 528 }
518 529
519 len=urb->iso_frame_desc[i].actual_length; 530 len = urb->iso_frame_desc[i].actual_length;
520 531
521// if (len>=TM6000_URB_MSG_LEN) { 532 if (len > 0) {
522 p=urb->transfer_buffer + urb->iso_frame_desc[i].offset; 533 p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
523 if (!urb->iso_frame_desc[i].status) { 534 if (!urb->iso_frame_desc[i].status) {
524 if ((buf->fmt->fourcc)==V4L2_PIX_FMT_TM6000) { 535 if ((dev->fourcc)==V4L2_PIX_FMT_TM6000) {
525 rc=copy_multiplexed(p, outp, len, urb, &buf); 536 rc=copy_multiplexed(p, len, urb);
526 if (rc<=0) 537 if (rc<=0)
527 return rc; 538 return rc;
528 } else { 539 } else {
529 copy_streams(p, outp, len, urb, &buf); 540 copy_streams(p, len, urb);
530 } 541 }
531 } 542 }
532 copied += len; 543 }
533 if (copied >= size || !buf)
534 break;
535// }
536 } 544 }
537 return rc; 545 return rc;
538} 546}
@@ -612,7 +620,7 @@ static void tm6000_uninit_isoc(struct tm6000_core *dev)
612static int tm6000_prepare_isoc(struct tm6000_core *dev, unsigned int framesize) 620static int tm6000_prepare_isoc(struct tm6000_core *dev, unsigned int framesize)
613{ 621{
614 struct tm6000_dmaqueue *dma_q = &dev->vidq; 622 struct tm6000_dmaqueue *dma_q = &dev->vidq;
615 int i, j, sb_size, pipe, size, max_packets, num_bufs = 5; 623 int i, j, sb_size, pipe, size, max_packets, num_bufs = 8;
616 struct urb *urb; 624 struct urb *urb;
617 625
618 /* De-allocates all pending stuff */ 626 /* De-allocates all pending stuff */
diff --git a/drivers/staging/tm6000/tm6000.h b/drivers/staging/tm6000/tm6000.h
index 6812d6867d57..7bbaf26dea14 100644
--- a/drivers/staging/tm6000/tm6000.h
+++ b/drivers/staging/tm6000/tm6000.h
@@ -168,6 +168,10 @@ struct tm6000_core {
168 struct i2c_adapter i2c_adap; 168 struct i2c_adapter i2c_adap;
169 struct i2c_client i2c_client; 169 struct i2c_client i2c_client;
170 170
171
172 /* extension */
173 struct list_head devlist;
174
171 /* video for linux */ 175 /* video for linux */
172 int users; 176 int users;
173 177
@@ -203,6 +207,16 @@ struct tm6000_core {
203 spinlock_t slock; 207 spinlock_t slock;
204}; 208};
205 209
210#define TM6000_AUDIO 0x10
211
212struct tm6000_ops {
213 struct list_head next;
214 char *name;
215 int id;
216 int (*init)(struct tm6000_core *);
217 int (*fini)(struct tm6000_core *);
218};
219
206struct tm6000_fh { 220struct tm6000_fh {
207 struct tm6000_core *dev; 221 struct tm6000_core *dev;
208 222
@@ -232,6 +246,8 @@ int tm6000_get_reg (struct tm6000_core *dev, u8 req, u16 value, u16 index);
232int tm6000_get_reg16(struct tm6000_core *dev, u8 req, u16 value, u16 index); 246int tm6000_get_reg16(struct tm6000_core *dev, u8 req, u16 value, u16 index);
233int tm6000_get_reg32(struct tm6000_core *dev, u8 req, u16 value, u16 index); 247int tm6000_get_reg32(struct tm6000_core *dev, u8 req, u16 value, u16 index);
234int tm6000_set_reg (struct tm6000_core *dev, u8 req, u16 value, u16 index); 248int tm6000_set_reg (struct tm6000_core *dev, u8 req, u16 value, u16 index);
249int tm6000_i2c_reset(struct tm6000_core *dev, u16 tsleep);
250
235int tm6000_init (struct tm6000_core *dev); 251int tm6000_init (struct tm6000_core *dev);
236 252
237int tm6000_init_analog_mode (struct tm6000_core *dev); 253int tm6000_init_analog_mode (struct tm6000_core *dev);
@@ -246,6 +262,13 @@ int tm6000_v4l2_unregister(struct tm6000_core *dev);
246int tm6000_v4l2_exit(void); 262int tm6000_v4l2_exit(void);
247void tm6000_set_fourcc_format(struct tm6000_core *dev); 263void tm6000_set_fourcc_format(struct tm6000_core *dev);
248 264
265void tm6000_remove_from_devlist(struct tm6000_core *dev);
266void tm6000_add_into_devlist(struct tm6000_core *dev);
267int tm6000_register_extension(struct tm6000_ops *ops);
268void tm6000_unregister_extension(struct tm6000_ops *ops);
269void tm6000_init_extension(struct tm6000_core *dev);
270void tm6000_close_extension(struct tm6000_core *dev);
271
249/* In tm6000-stds.c */ 272/* In tm6000-stds.c */
250void tm6000_get_std_res(struct tm6000_core *dev); 273void tm6000_get_std_res(struct tm6000_core *dev);
251int tm6000_set_standard (struct tm6000_core *dev, v4l2_std_id *norm); 274int tm6000_set_standard (struct tm6000_core *dev, v4l2_std_id *norm);
@@ -275,7 +298,7 @@ unsigned int tm6000_v4l2_poll(struct file *file,
275int tm6000_queue_init(struct tm6000_core *dev); 298int tm6000_queue_init(struct tm6000_core *dev);
276 299
277/* In tm6000-alsa.c */ 300/* In tm6000-alsa.c */
278int tm6000_audio_init(struct tm6000_core *dev, int idx); 301/*int tm6000_audio_init(struct tm6000_core *dev, int idx);*/
279 302
280 303
281/* Debug stuff */ 304/* Debug stuff */
diff --git a/drivers/staging/vme/bridges/vme_ca91cx42.c b/drivers/staging/vme/bridges/vme_ca91cx42.c
index 0c82eb47a28d..0f9ea58ff717 100644
--- a/drivers/staging/vme/bridges/vme_ca91cx42.c
+++ b/drivers/staging/vme/bridges/vme_ca91cx42.c
@@ -523,7 +523,7 @@ static int ca91cx42_alloc_resource(struct vme_master_resource *image,
523 } 523 }
524 524
525 if (image->bus_resource.name == NULL) { 525 if (image->bus_resource.name == NULL) {
526 image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_KERNEL); 526 image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_ATOMIC);
527 if (image->bus_resource.name == NULL) { 527 if (image->bus_resource.name == NULL) {
528 dev_err(ca91cx42_bridge->parent, "Unable to allocate " 528 dev_err(ca91cx42_bridge->parent, "Unable to allocate "
529 "memory for resource name\n"); 529 "memory for resource name\n");
diff --git a/drivers/staging/vme/bridges/vme_tsi148.c b/drivers/staging/vme/bridges/vme_tsi148.c
index abe88a380b72..f09cac163139 100644
--- a/drivers/staging/vme/bridges/vme_tsi148.c
+++ b/drivers/staging/vme/bridges/vme_tsi148.c
@@ -828,7 +828,7 @@ static int tsi148_alloc_resource(struct vme_master_resource *image,
828 return 0; 828 return 0;
829 829
830 if (image->bus_resource.name == NULL) { 830 if (image->bus_resource.name == NULL) {
831 image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_KERNEL); 831 image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_ATOMIC);
832 if (image->bus_resource.name == NULL) { 832 if (image->bus_resource.name == NULL) {
833 dev_err(tsi148_bridge->parent, "Unable to allocate " 833 dev_err(tsi148_bridge->parent, "Unable to allocate "
834 "memory for resource name\n"); 834 "memory for resource name\n");
diff --git a/drivers/staging/wlags49_h2/Kconfig b/drivers/staging/wlags49_h2/Kconfig
index b6fc2ca7d85c..3efcbf8afedf 100644
--- a/drivers/staging/wlags49_h2/Kconfig
+++ b/drivers/staging/wlags49_h2/Kconfig
@@ -1,9 +1,11 @@
1config WLAGS49_H2 1config WLAGS49_H2
2 tristate "Agere Systems HERMES II Wireless PC Card Model 0110" 2 tristate "Agere Systems HERMES II Wireless PC Card Model 0110"
3 depends on WLAN && WIRELESS_EXT && PCMCIA 3 depends on WLAN && PCMCIA
4 select WIRELESS_EXT
4 select WEXT_SPY 5 select WEXT_SPY
6 select WEXT_PRIV
5 ---help--- 7 ---help---
6 Driver for wireless cards using Agere's HERMES II chipset 8 Driver for wireless cards using Agere's HERMES II chipset
7 which are identified with Manufacture ID: 0156,0003 9 which are identified with Manufacture ID: 0156,0003
8 The software is a modified version of wl_lkm_722_abg.tar.gz 10 The software is a modified version of wl_lkm_722_abg.tar.gz
9 from the Agere Systems website, addapted for Ubuntu 9.04. 11 from the Agere Systems website, addapted for Ubuntu 9.04.
diff --git a/drivers/staging/wlags49_h25/Kconfig b/drivers/staging/wlags49_h25/Kconfig
index dcc170929c13..bf5664a51cd4 100644
--- a/drivers/staging/wlags49_h25/Kconfig
+++ b/drivers/staging/wlags49_h25/Kconfig
@@ -1,9 +1,11 @@
1config WLAGS49_H25 1config WLAGS49_H25
2 tristate "Linksys HERMES II.5 WCF54G_Wireless-G_CompactFlash_Card" 2 tristate "Linksys HERMES II.5 WCF54G_Wireless-G_CompactFlash_Card"
3 depends on WLAN && WIRELESS_EXT && PCMCIA 3 depends on WLAN && PCMCIA
4 select WIRELESS_EXT
4 select WEXT_SPY 5 select WEXT_SPY
6 select WEXT_PRIV
5 ---help--- 7 ---help---
6 Driver for wireless cards using Agere's HERMES II.5 chipset 8 Driver for wireless cards using Agere's HERMES II.5 chipset
7 which are identified with Manufacture ID: 0156,0004 9 which are identified with Manufacture ID: 0156,0004
8 The software is a modified version of wl_lkm_722_abg.tar.gz 10 The software is a modified version of wl_lkm_722_abg.tar.gz
9 from the Agere Systems website, addapted for Ubuntu 9.04. 11 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
index 000000000000..bb0ca5974ea0
--- /dev/null
+++ b/drivers/staging/xgifb/Kconfig
@@ -0,0 +1,11 @@
1config FB_XGI
2 tristate "XGI display support"
3 depends on FB && PCI
4 select FB_CFB_FILLRECT
5 select FB_CFB_COPYAREA
6 select FB_CFB_IMAGEBLIT
7 help
8 This driver supports notebooks with XGI Z7,Z9,Z11 PCI chips.
9 Say Y if you have such a graphics card.
10 To compile this driver as a module, choose M here: the
11 module will be called xgifb.ko
diff --git a/drivers/staging/xgifb/Makefile b/drivers/staging/xgifb/Makefile
new file mode 100644
index 000000000000..2a317707de0f
--- /dev/null
+++ b/drivers/staging/xgifb/Makefile
@@ -0,0 +1,4 @@
1obj-$(CONFIG_FB_XGI) += xgifb.o
2
3xgifb-objs := XGI_main_26.o XGI_accel.o vb_init.o vb_setmode.o vb_util.o vb_ext.o
4
diff --git a/drivers/staging/xgifb/TODO b/drivers/staging/xgifb/TODO
new file mode 100644
index 000000000000..7d71019b84c2
--- /dev/null
+++ b/drivers/staging/xgifb/TODO
@@ -0,0 +1,15 @@
1This drivers still need a lot of work. I can list all cleanups to do but it's
2going to be long. So, I'm writing "cleanups" and not the list.
3
4Arnaud
5
6TODO:
7- clean ups
8- fix build warnings when module
9- sort out dup ids with SiS driver
10- remove useless/wrong/unused #ifdef/code/...
11- fix printk usages
12- get rid of non-linux related stuff
13
14Please send patches to:
15Arnaud Patard <apatard@mandriva.com>
diff --git a/drivers/staging/xgifb/XGI.h b/drivers/staging/xgifb/XGI.h
new file mode 100644
index 000000000000..87803dd032de
--- /dev/null
+++ b/drivers/staging/xgifb/XGI.h
@@ -0,0 +1,10 @@
1#ifndef _XGI_H
2#define _XGI_H
3
4#if 1
5#define TWDEBUG(x)
6#else
7#define TWDEBUG(x) printk(KERN_INFO x "\n");
8#endif
9
10#endif
diff --git a/drivers/staging/xgifb/XGI_accel.c b/drivers/staging/xgifb/XGI_accel.c
new file mode 100644
index 000000000000..86ec3421942f
--- /dev/null
+++ b/drivers/staging/xgifb/XGI_accel.c
@@ -0,0 +1,596 @@
1/*
2 * XGI 300/630/730/540/315/550/650/740 frame buffer driver
3 * for Linux kernels 2.4.x and 2.5.x
4 *
5 * 2D acceleration part
6 *
7 * Based on the X driver's XGI300_accel.c which is
8 * Copyright Xavier Ducoin <x.ducoin@lectra.com>
9 * Copyright 2002 by Thomas Winischhofer, Vienna, Austria
10 * and XGI310_accel.c which is
11 * Copyright 2002 by Thomas Winischhofer, Vienna, Austria
12 *
13 * Author: Thomas Winischhofer <thomas@winischhofer.net>
14 * (see http://www.winischhofer.net/
15 * for more information and updates)
16 */
17
18//#include <linux/config.h>
19#include <linux/version.h>
20#include <linux/module.h>
21#include <linux/kernel.h>
22#include <linux/errno.h>
23#include <linux/string.h>
24#include <linux/mm.h>
25#include <linux/tty.h>
26#include <linux/slab.h>
27#include <linux/delay.h>
28#include <linux/fb.h>
29#include <linux/console.h>
30#include <linux/selection.h>
31#include <linux/ioport.h>
32#include <linux/init.h>
33#include <linux/pci.h>
34#include <linux/vt_kern.h>
35#include <linux/capability.h>
36#include <linux/fs.h>
37#include <linux/agp_backend.h>
38
39#include <linux/types.h>
40/*
41#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
42#include <linux/XGIfb.h>
43#else
44#include <video/XGIfb.h>
45#endif
46*/
47#include <asm/io.h>
48
49#ifdef CONFIG_MTRR
50#include <asm/mtrr.h>
51#endif
52
53#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
54#include <video/fbcon.h>
55#include <video/fbcon-cfb8.h>
56#include <video/fbcon-cfb16.h>
57#include <video/fbcon-cfb24.h>
58#include <video/fbcon-cfb32.h>
59#endif
60
61#include "osdef.h"
62#include "vgatypes.h"
63#include "vb_struct.h"
64#include "XGIfb.h"
65#include "XGI_accel.h"
66
67
68extern struct video_info xgi_video_info;
69extern int XGIfb_accel;
70
71static const int XGIALUConv[] =
72{
73 0x00, /* dest = 0; 0, GXclear, 0 */
74 0x88, /* dest &= src; DSa, GXand, 0x1 */
75 0x44, /* dest = src & ~dest; SDna, GXandReverse, 0x2 */
76 0xCC, /* dest = src; S, GXcopy, 0x3 */
77 0x22, /* dest &= ~src; DSna, GXandInverted, 0x4 */
78 0xAA, /* dest = dest; D, GXnoop, 0x5 */
79 0x66, /* dest = ^src; DSx, GXxor, 0x6 */
80 0xEE, /* dest |= src; DSo, GXor, 0x7 */
81 0x11, /* dest = ~src & ~dest; DSon, GXnor, 0x8 */
82 0x99, /* dest ^= ~src ; DSxn, GXequiv, 0x9 */
83 0x55, /* dest = ~dest; Dn, GXInvert, 0xA */
84 0xDD, /* dest = src|~dest ; SDno, GXorReverse, 0xB */
85 0x33, /* dest = ~src; Sn, GXcopyInverted, 0xC */
86 0xBB, /* dest |= ~src; DSno, GXorInverted, 0xD */
87 0x77, /* dest = ~src|~dest; DSan, GXnand, 0xE */
88 0xFF, /* dest = 0xFF; 1, GXset, 0xF */
89};
90/* same ROP but with Pattern as Source */
91static const int XGIPatALUConv[] =
92{
93 0x00, /* dest = 0; 0, GXclear, 0 */
94 0xA0, /* dest &= src; DPa, GXand, 0x1 */
95 0x50, /* dest = src & ~dest; PDna, GXandReverse, 0x2 */
96 0xF0, /* dest = src; P, GXcopy, 0x3 */
97 0x0A, /* dest &= ~src; DPna, GXandInverted, 0x4 */
98 0xAA, /* dest = dest; D, GXnoop, 0x5 */
99 0x5A, /* dest = ^src; DPx, GXxor, 0x6 */
100 0xFA, /* dest |= src; DPo, GXor, 0x7 */
101 0x05, /* dest = ~src & ~dest; DPon, GXnor, 0x8 */
102 0xA5, /* dest ^= ~src ; DPxn, GXequiv, 0x9 */
103 0x55, /* dest = ~dest; Dn, GXInvert, 0xA */
104 0xF5, /* dest = src|~dest ; PDno, GXorReverse, 0xB */
105 0x0F, /* dest = ~src; Pn, GXcopyInverted, 0xC */
106 0xAF, /* dest |= ~src; DPno, GXorInverted, 0xD */
107 0x5F, /* dest = ~src|~dest; DPan, GXnand, 0xE */
108 0xFF, /* dest = 0xFF; 1, GXset, 0xF */
109};
110
111#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34)
112static const unsigned char myrops[] = {
113 3, 10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
114 };
115#endif
116
117/* 300 series */
118#if 0
119static void
120XGI300Sync(void)
121{
122 XGI300Idle
123}
124#endif
125static void
126XGI310Sync(void)
127{
128 XGI310Idle
129}
130#if 0
131static void
132XGI300SetupForScreenToScreenCopy(int xdir, int ydir, int rop,
133 unsigned int planemask, int trans_color)
134{
135 XGI300SetupDSTColorDepth(xgi_video_info.DstColor);
136 XGI300SetupSRCPitch(xgi_video_info.video_linelength)
137 XGI300SetupDSTRect(xgi_video_info.video_linelength, 0xFFF)
138
139 if(trans_color != -1) {
140 XGI300SetupROP(0x0A)
141 XGI300SetupSRCTrans(trans_color)
142 XGI300SetupCMDFlag(TRANSPARENT_BITBLT)
143 } else {
144 XGI300SetupROP(XGIALUConv[rop])
145 }
146 if(xdir > 0) {
147 XGI300SetupCMDFlag(X_INC)
148 }
149 if(ydir > 0) {
150 XGI300SetupCMDFlag(Y_INC)
151 }
152}
153
154static void
155XGI300SubsequentScreenToScreenCopy(int src_x, int src_y, int dst_x, int dst_y,
156 int width, int height)
157{
158 long srcbase, dstbase;
159
160 srcbase = dstbase = 0;
161 if (src_y >= 2048) {
162 srcbase = xgi_video_info.video_linelength * src_y;
163 src_y = 0;
164 }
165 if (dst_y >= 2048) {
166 dstbase = xgi_video_info.video_linelength * dst_y;
167 dst_y = 0;
168 }
169
170 XGI300SetupSRCBase(srcbase);
171 XGI300SetupDSTBase(dstbase);
172
173 if(!(xgi_video_info.CommandReg & X_INC)) {
174 src_x += width-1;
175 dst_x += width-1;
176 }
177 if(!(xgi_video_info.CommandReg & Y_INC)) {
178 src_y += height-1;
179 dst_y += height-1;
180 }
181 XGI300SetupRect(width, height)
182 XGI300SetupSRCXY(src_x, src_y)
183 XGI300SetupDSTXY(dst_x, dst_y)
184 XGI300DoCMD
185}
186
187static void
188XGI300SetupForSolidFill(int color, int rop, unsigned int planemask)
189{
190 XGI300SetupPATFG(color)
191 XGI300SetupDSTRect(xgi_video_info.video_linelength, 0xFFF)
192 XGI300SetupDSTColorDepth(xgi_video_info.DstColor);
193 XGI300SetupROP(XGIPatALUConv[rop])
194 XGI300SetupCMDFlag(PATFG)
195}
196
197static void
198XGI300SubsequentSolidFillRect(int x, int y, int w, int h)
199{
200 long dstbase;
201
202 dstbase = 0;
203 if(y >= 2048) {
204 dstbase = xgi_video_info.video_linelength * y;
205 y = 0;
206 }
207 XGI300SetupDSTBase(dstbase)
208 XGI300SetupDSTXY(x,y)
209 XGI300SetupRect(w,h)
210 XGI300SetupCMDFlag(X_INC | Y_INC | BITBLT)
211 XGI300DoCMD
212}
213#endif
214/* 310/325 series ------------------------------------------------ */
215
216static void
217XGI310SetupForScreenToScreenCopy(int xdir, int ydir, int rop,
218 unsigned int planemask, int trans_color)
219{
220 XGI310SetupDSTColorDepth(xgi_video_info.DstColor);
221 XGI310SetupSRCPitch(xgi_video_info.video_linelength)
222 XGI310SetupDSTRect(xgi_video_info.video_linelength, 0xFFF)
223 if (trans_color != -1) {
224 XGI310SetupROP(0x0A)
225 XGI310SetupSRCTrans(trans_color)
226 XGI310SetupCMDFlag(TRANSPARENT_BITBLT)
227 } else {
228 XGI310SetupROP(XGIALUConv[rop])
229 /* Set command - not needed, both 0 */
230 /* XGISetupCMDFlag(BITBLT | SRCVIDEO) */
231 }
232 XGI310SetupCMDFlag(xgi_video_info.XGI310_AccelDepth)
233 /* TW: The 310/325 series is smart enough to know the direction */
234}
235
236static void
237XGI310SubsequentScreenToScreenCopy(int src_x, int src_y, int dst_x, int dst_y,
238 int width, int height)
239{
240 long srcbase, dstbase;
241 int mymin, mymax;
242
243 srcbase = dstbase = 0;
244 mymin = min(src_y, dst_y);
245 mymax = max(src_y, dst_y);
246
247 /* Although the chip knows the direction to use
248 * if the source and destination areas overlap,
249 * that logic fails if we fiddle with the bitmap
250 * addresses. Therefore, we check if the source
251 * and destination blitting areas overlap and
252 * adapt the bitmap addresses synchronously
253 * if the coordinates exceed the valid range.
254 * The the areas do not overlap, we do our
255 * normal check.
256 */
257 if((mymax - mymin) < height) {
258 if((src_y >= 2048) || (dst_y >= 2048)) {
259 srcbase = xgi_video_info.video_linelength * mymin;
260 dstbase = xgi_video_info.video_linelength * mymin;
261 src_y -= mymin;
262 dst_y -= mymin;
263 }
264 } else {
265 if(src_y >= 2048) {
266 srcbase = xgi_video_info.video_linelength * src_y;
267 src_y = 0;
268 }
269 if(dst_y >= 2048) {
270 dstbase = xgi_video_info.video_linelength * dst_y;
271 dst_y = 0;
272 }
273 }
274
275 XGI310SetupSRCBase(srcbase);
276 XGI310SetupDSTBase(dstbase);
277 XGI310SetupRect(width, height)
278 XGI310SetupSRCXY(src_x, src_y)
279 XGI310SetupDSTXY(dst_x, dst_y)
280 XGI310DoCMD
281}
282
283static void
284XGI310SetupForSolidFill(int color, int rop, unsigned int planemask)
285{
286 XGI310SetupPATFG(color)
287 XGI310SetupDSTRect(xgi_video_info.video_linelength, 0xFFF)
288 XGI310SetupDSTColorDepth(xgi_video_info.DstColor);
289 XGI310SetupROP(XGIPatALUConv[rop])
290 XGI310SetupCMDFlag(PATFG | xgi_video_info.XGI310_AccelDepth)
291}
292
293static void
294XGI310SubsequentSolidFillRect(int x, int y, int w, int h)
295{
296 long dstbase;
297
298 dstbase = 0;
299 if(y >= 2048) {
300 dstbase = xgi_video_info.video_linelength * y;
301 y = 0;
302 }
303 XGI310SetupDSTBase(dstbase)
304 XGI310SetupDSTXY(x,y)
305 XGI310SetupRect(w,h)
306 XGI310SetupCMDFlag(BITBLT)
307 XGI310DoCMD
308}
309
310/* --------------------------------------------------------------------- */
311
312/* The exported routines */
313
314int XGIfb_initaccel(void)
315{
316#ifdef XGIFB_USE_SPINLOCKS
317 spin_lock_init(&xgi_video_info.lockaccel);
318#endif
319 return(0);
320}
321
322void XGIfb_syncaccel(void)
323{
324
325 XGI310Sync();
326
327}
328
329#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34) /* --- KERNEL 2.5.34 and later --- */
330
331int fbcon_XGI_sync(struct fb_info *info)
332{
333 if(!XGIfb_accel) return 0;
334 CRITFLAGS
335
336 XGI310Sync();
337
338 CRITEND
339 return 0;
340}
341
342void fbcon_XGI_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
343{
344 int col=0;
345 CRITFLAGS
346
347
348 if(!rect->width || !rect->height)
349 return;
350
351 if(!XGIfb_accel) {
352 cfb_fillrect(info, rect);
353 return;
354 }
355
356 switch(info->var.bits_per_pixel) {
357 case 8: col = rect->color;
358 break;
359 case 16: col = ((u32 *)(info->pseudo_palette))[rect->color];
360 break;
361 case 32: col = ((u32 *)(info->pseudo_palette))[rect->color];
362 break;
363 }
364
365
366 CRITBEGIN
367 XGI310SetupForSolidFill(col, myrops[rect->rop], 0);
368 XGI310SubsequentSolidFillRect(rect->dx, rect->dy, rect->width, rect->height);
369 CRITEND
370 XGI310Sync();
371
372
373}
374
375void fbcon_XGI_copyarea(struct fb_info *info, const struct fb_copyarea *area)
376{
377 int xdir, ydir;
378 CRITFLAGS
379
380
381 if(!XGIfb_accel) {
382 cfb_copyarea(info, area);
383 return;
384 }
385
386 if(!area->width || !area->height)
387 return;
388
389 if(area->sx < area->dx) xdir = 0;
390 else xdir = 1;
391 if(area->sy < area->dy) ydir = 0;
392 else ydir = 1;
393
394 CRITBEGIN
395 XGI310SetupForScreenToScreenCopy(xdir, ydir, 3, 0, -1);
396 XGI310SubsequentScreenToScreenCopy(area->sx, area->sy, area->dx, area->dy, area->width, area->height);
397 CRITEND
398 XGI310Sync();
399
400}
401
402#endif
403
404#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,33) /* ------ KERNEL <2.5.34 ------ */
405
406void fbcon_XGI_bmove(struct display *p, int srcy, int srcx,
407 int dsty, int dstx, int height, int width)
408{
409 int xdir, ydir;
410 CRITFLAGS
411
412 if(!xgi_video_info.accel) {
413 switch(xgi_video_info.video_bpp) {
414 case 8:
415#ifdef FBCON_HAS_CFB8
416 fbcon_cfb8_bmove(p, srcy, srcx, dsty, dstx, height, width);
417#endif
418 break;
419 case 16:
420#ifdef FBCON_HAS_CFB16
421 fbcon_cfb16_bmove(p, srcy, srcx, dsty, dstx, height, width);
422#endif
423 break;
424 case 32:
425#ifdef FBCON_HAS_CFB32
426 fbcon_cfb32_bmove(p, srcy, srcx, dsty, dstx, height, width);
427#endif
428 break;
429 }
430 return;
431 }
432
433 srcx *= fontwidth(p);
434 srcy *= fontheight(p);
435 dstx *= fontwidth(p);
436 dsty *= fontheight(p);
437 width *= fontwidth(p);
438 height *= fontheight(p);
439
440 if(srcx < dstx) xdir = 0;
441 else xdir = 1;
442 if(srcy < dsty) ydir = 0;
443 else ydir = 1;
444
445
446 CRITBEGIN
447 XGI310SetupForScreenToScreenCopy(xdir, ydir, 3, 0, -1);
448 XGI310SubsequentScreenToScreenCopy(srcx, srcy, dstx, dsty, width, height);
449 CRITEND
450 XGI310Sync();
451#if 0
452 printk(KERN_INFO "XGI_bmove sx %d sy %d dx %d dy %d w %d h %d\n",
453 srcx, srcy, dstx, dsty, width, height);
454#endif
455
456}
457
458
459static void fbcon_XGI_clear(struct vc_data *conp, struct display *p,
460 int srcy, int srcx, int height, int width, int color)
461{
462 CRITFLAGS
463
464 srcx *= fontwidth(p);
465 srcy *= fontheight(p);
466 width *= fontwidth(p);
467 height *= fontheight(p);
468
469
470 CRITBEGIN
471 XGI310SetupForSolidFill(color, 3, 0);
472 XGI310SubsequentSolidFillRect(srcx, srcy, width, height);
473 CRITEND
474 XGI310Sync();
475
476}
477
478void fbcon_XGI_clear8(struct vc_data *conp, struct display *p,
479 int srcy, int srcx, int height, int width)
480{
481 u32 bgx;
482
483 if(!xgi_video_info.accel) {
484#ifdef FBCON_HAS_CFB8
485 fbcon_cfb8_clear(conp, p, srcy, srcx, height, width);
486#endif
487 return;
488 }
489
490 bgx = attr_bgcol_ec(p, conp);
491 fbcon_XGI_clear(conp, p, srcy, srcx, height, width, bgx);
492}
493
494void fbcon_XGI_clear16(struct vc_data *conp, struct display *p,
495 int srcy, int srcx, int height, int width)
496{
497 u32 bgx;
498 if(!xgi_video_info.accel) {
499#ifdef FBCON_HAS_CFB16
500 fbcon_cfb16_clear(conp, p, srcy, srcx, height, width);
501#endif
502 return;
503 }
504
505 bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)];
506 fbcon_XGI_clear(conp, p, srcy, srcx, height, width, bgx);
507}
508
509void fbcon_XGI_clear32(struct vc_data *conp, struct display *p,
510 int srcy, int srcx, int height, int width)
511{
512 u32 bgx;
513
514 if(!xgi_video_info.accel) {
515#ifdef FBCON_HAS_CFB32
516 fbcon_cfb32_clear(conp, p, srcy, srcx, height, width);
517#endif
518 return;
519 }
520
521 bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)];
522 fbcon_XGI_clear(conp, p, srcy, srcx, height, width, bgx);
523}
524
525void fbcon_XGI_revc(struct display *p, int srcx, int srcy)
526{
527 CRITFLAGS
528
529 if(!xgi_video_info.accel) {
530 switch(xgi_video_info.video_bpp) {
531 case 16:
532#ifdef FBCON_HAS_CFB16
533 fbcon_cfb16_revc(p, srcx, srcy);
534#endif
535 break;
536 case 32:
537#ifdef FBCON_HAS_CFB32
538 fbcon_cfb32_revc(p, srcx, srcy);
539#endif
540 break;
541 }
542 return;
543 }
544
545 srcx *= fontwidth(p);
546 srcy *= fontheight(p);
547
548
549 CRITBEGIN
550 XGI310SetupForSolidFill(0, 0x0a, 0);
551 XGI310SubsequentSolidFillRect(srcx, srcy, fontwidth(p), fontheight(p));
552 CRITEND
553 XGI310Sync();
554
555}
556
557#ifdef FBCON_HAS_CFB8
558struct display_switch fbcon_XGI8 = {
559 setup: fbcon_cfb8_setup,
560 bmove: fbcon_XGI_bmove,
561 clear: fbcon_XGI_clear8,
562 putc: fbcon_cfb8_putc,
563 putcs: fbcon_cfb8_putcs,
564 revc: fbcon_cfb8_revc,
565 clear_margins: fbcon_cfb8_clear_margins,
566 fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
567};
568#endif
569#ifdef FBCON_HAS_CFB16
570struct display_switch fbcon_XGI16 = {
571 setup: fbcon_cfb16_setup,
572 bmove: fbcon_XGI_bmove,
573 clear: fbcon_XGI_clear16,
574 putc: fbcon_cfb16_putc,
575 putcs: fbcon_cfb16_putcs,
576 revc: fbcon_XGI_revc,
577 clear_margins: fbcon_cfb16_clear_margins,
578 fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
579};
580#endif
581#ifdef FBCON_HAS_CFB32
582struct display_switch fbcon_XGI32 = {
583 setup: fbcon_cfb32_setup,
584 bmove: fbcon_XGI_bmove,
585 clear: fbcon_XGI_clear32,
586 putc: fbcon_cfb32_putc,
587 putcs: fbcon_cfb32_putcs,
588 revc: fbcon_XGI_revc,
589 clear_margins: fbcon_cfb32_clear_margins,
590 fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
591};
592#endif
593
594#endif /* KERNEL VERSION */
595
596
diff --git a/drivers/staging/xgifb/XGI_accel.h b/drivers/staging/xgifb/XGI_accel.h
new file mode 100644
index 000000000000..04e126772bb8
--- /dev/null
+++ b/drivers/staging/xgifb/XGI_accel.h
@@ -0,0 +1,511 @@
1/*
2 * XGI 300/630/730/540/315/550/650/740 frame buffer driver
3 * for Linux kernels 2.4.x and 2.5.x
4 *
5 * 2D acceleration part
6 *
7 * Based on the X driver's XGI300_accel.h which is
8 * Copyright Xavier Ducoin <x.ducoin@lectra.com>
9 * Copyright 2002 by Thomas Winischhofer, Vienna, Austria
10 * and XGI310_accel.h which is
11 * Copyright 2002 by Thomas Winischhofer, Vienna, Austria
12 *
13 * Author: Thomas Winischhofer <thomas@winischhofer.net>:
14 * (see http://www.winischhofer.net/
15 * for more information and updates)
16 */
17
18#ifndef _XGIFB_ACCEL_H
19#define _XGIFB_ACCEL_H
20
21/* Guard accelerator accesses with spin_lock_irqsave? Works well without. */
22#undef XGIFB_USE_SPINLOCKS
23
24#ifdef XGIFB_USE_SPINLOCKS
25#include <linux/spinlock.h>
26#define CRITBEGIN spin_lock_irqsave(&xgi_video_info.lockaccel), critflags);
27#define CRITEND spin_unlock_irqrestore(&xgi_video_info.lockaccel), critflags);
28#define CRITFLAGS unsigned long critflags;
29#else
30#define CRITBEGIN
31#define CRITEND
32#define CRITFLAGS
33#endif
34
35/* Definitions for the XGI engine communication. */
36
37#define PATREGSIZE 384 /* Pattern register size. 384 bytes @ 0x8300 */
38#define BR(x) (0x8200 | (x) << 2)
39#define PBR(x) (0x8300 | (x) << 2)
40
41/* XGI300 engine commands */
42#define BITBLT 0x00000000 /* Blit */
43#define COLOREXP 0x00000001 /* Color expand */
44#define ENCOLOREXP 0x00000002 /* Enhanced color expand */
45#define MULTIPLE_SCANLINE 0x00000003 /* ? */
46#define LINE 0x00000004 /* Draw line */
47#define TRAPAZOID_FILL 0x00000005 /* Fill trapezoid */
48#define TRANSPARENT_BITBLT 0x00000006 /* Transparent Blit */
49
50/* Additional engine commands for 310/325 */
51#define ALPHA_BLEND 0x00000007 /* Alpha blend ? */
52#define A3D_FUNCTION 0x00000008 /* 3D command ? */
53#define CLEAR_Z_BUFFER 0x00000009 /* ? */
54#define GRADIENT_FILL 0x0000000A /* Gradient fill */
55#define STRETCH_BITBLT 0x0000000B /* Stretched Blit */
56
57/* source select */
58#define SRCVIDEO 0x00000000 /* source is video RAM */
59#define SRCSYSTEM 0x00000010 /* source is system memory */
60#define SRCCPUBLITBUF SRCSYSTEM /* source is CPU-driven BitBuffer (for color expand) */
61#define SRCAGP 0x00000020 /* source is AGP memory (?) */
62
63/* Pattern flags */
64#define PATFG 0x00000000 /* foreground color */
65#define PATPATREG 0x00000040 /* pattern in pattern buffer (0x8300) */
66#define PATMONO 0x00000080 /* mono pattern */
67
68/* blitting direction (300 series only) */
69#define X_INC 0x00010000
70#define X_DEC 0x00000000
71#define Y_INC 0x00020000
72#define Y_DEC 0x00000000
73
74/* Clipping flags */
75#define NOCLIP 0x00000000
76#define NOMERGECLIP 0x04000000
77#define CLIPENABLE 0x00040000
78#define CLIPWITHOUTMERGE 0x04040000
79
80/* Transparency */
81#define OPAQUE 0x00000000
82#define TRANSPARENT 0x00100000
83
84/* ? */
85#define DSTAGP 0x02000000
86#define DSTVIDEO 0x02000000
87
88/* Line */
89#define LINE_STYLE 0x00800000
90#define NO_RESET_COUNTER 0x00400000
91#define NO_LAST_PIXEL 0x00200000
92
93/* Subfunctions for Color/Enhanced Color Expansion (310/325 only) */
94#define COLOR_TO_MONO 0x00100000
95#define AA_TEXT 0x00200000
96
97/* Some general registers for 310/325 series */
98#define SRC_ADDR 0x8200
99#define SRC_PITCH 0x8204
100#define AGP_BASE 0x8206 /* color-depth dependent value */
101#define SRC_Y 0x8208
102#define SRC_X 0x820A
103#define DST_Y 0x820C
104#define DST_X 0x820E
105#define DST_ADDR 0x8210
106#define DST_PITCH 0x8214
107#define DST_HEIGHT 0x8216
108#define RECT_WIDTH 0x8218
109#define RECT_HEIGHT 0x821A
110#define PAT_FGCOLOR 0x821C
111#define PAT_BGCOLOR 0x8220
112#define SRC_FGCOLOR 0x8224
113#define SRC_BGCOLOR 0x8228
114#define MONO_MASK 0x822C
115#define LEFT_CLIP 0x8234
116#define TOP_CLIP 0x8236
117#define RIGHT_CLIP 0x8238
118#define BOTTOM_CLIP 0x823A
119#define COMMAND_READY 0x823C
120#define FIRE_TRIGGER 0x8240
121
122#define PATTERN_REG 0x8300 /* 384 bytes pattern buffer */
123
124/* Line registers */
125#define LINE_X0 SRC_Y
126#define LINE_X1 DST_Y
127#define LINE_Y0 SRC_X
128#define LINE_Y1 DST_X
129#define LINE_COUNT RECT_WIDTH
130#define LINE_STYLE_PERIOD RECT_HEIGHT
131#define LINE_STYLE_0 MONO_MASK
132#define LINE_STYLE_1 0x8230
133#define LINE_XN PATTERN_REG
134#define LINE_YN PATTERN_REG+2
135
136/* Transparent bitblit registers */
137#define TRANS_DST_KEY_HIGH PAT_FGCOLOR
138#define TRANS_DST_KEY_LOW PAT_BGCOLOR
139#define TRANS_SRC_KEY_HIGH SRC_FGCOLOR
140#define TRANS_SRC_KEY_LOW SRC_BGCOLOR
141
142/* Queue */
143#define Q_BASE_ADDR 0x85C0 /* Base address of software queue (?) */
144#define Q_WRITE_PTR 0x85C4 /* Current write pointer (?) */
145#define Q_READ_PTR 0x85C8 /* Current read pointer (?) */
146#define Q_STATUS 0x85CC /* queue status */
147
148
149#define MMIO_IN8(base, offset) \
150 *(volatile u8 *)(((u8*)(base)) + (offset))
151#define MMIO_IN16(base, offset) \
152 *(volatile u16 *)(void *)(((u8*)(base)) + (offset))
153#define MMIO_IN32(base, offset) \
154 *(volatile u32 *)(void *)(((u8*)(base)) + (offset))
155#define MMIO_OUT8(base, offset, val) \
156 *(volatile u8 *)(((u8*)(base)) + (offset)) = (val)
157#define MMIO_OUT16(base, offset, val) \
158 *(volatile u16 *)(void *)(((u8*)(base)) + (offset)) = (val)
159#define MMIO_OUT32(base, offset, val) \
160 *(volatile u32 *)(void *)(((u8*)(base)) + (offset)) = (val)
161
162
163
164/* ------------- XGI 300 series -------------- */
165
166/* Macros to do useful things with the XGI BitBLT engine */
167
168/* BR(16) (0x8420):
169
170 bit 31 2D engine: 1 is idle,
171 bit 30 3D engine: 1 is idle,
172 bit 29 Command queue: 1 is empty
173
174 bits 28:24: Current CPU driven BitBlt buffer stage bit[4:0]
175
176 bits 15:0: Current command queue length
177
178*/
179
180/* TW: BR(16)+2 = 0x8242 */
181
182int xgiCmdQueLen;
183
184#define XGI300Idle \
185 { \
186 while( (MMIO_IN16(xgi_video_info.mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \
187 while( (MMIO_IN16(xgi_video_info.mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \
188 while( (MMIO_IN16(xgi_video_info.mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \
189 xgiCmdQueLen=MMIO_IN16(xgi_video_info.mmio_vbase, 0x8240); \
190 }
191/* TW: (do three times, because 2D engine seems quite unsure about whether or not it's idle) */
192
193#define XGI300SetupSRCBase(base) \
194 if (xgiCmdQueLen <= 0) XGI300Idle;\
195 MMIO_OUT32(xgi_video_info.mmio_vbase, BR(0), base);\
196 xgiCmdQueLen --;
197
198#define XGI300SetupSRCPitch(pitch) \
199 if (xgiCmdQueLen <= 0) XGI300Idle;\
200 MMIO_OUT16(xgi_video_info.mmio_vbase, BR(1), pitch);\
201 xgiCmdQueLen --;
202
203#define XGI300SetupSRCXY(x,y) \
204 if (xgiCmdQueLen <= 0) XGI300Idle;\
205 MMIO_OUT32(xgi_video_info.mmio_vbase, BR(2), (x)<<16 | (y) );\
206 xgiCmdQueLen --;
207
208#define XGI300SetupDSTBase(base) \
209 if (xgiCmdQueLen <= 0) XGI300Idle;\
210 MMIO_OUT32(xgi_video_info.mmio_vbase, BR(4), base);\
211 xgiCmdQueLen --;
212
213#define XGI300SetupDSTXY(x,y) \
214 if (xgiCmdQueLen <= 0) XGI300Idle;\
215 MMIO_OUT32(xgi_video_info.mmio_vbase, BR(3), (x)<<16 | (y) );\
216 xgiCmdQueLen --;
217
218#define XGI300SetupDSTRect(x,y) \
219 if (xgiCmdQueLen <= 0) XGI300Idle;\
220 MMIO_OUT32(xgi_video_info.mmio_vbase, BR(5), (y)<<16 | (x) );\
221 xgiCmdQueLen --;
222
223#define XGI300SetupDSTColorDepth(bpp) \
224 if (xgiCmdQueLen <= 0) XGI300Idle;\
225 MMIO_OUT16(xgi_video_info.mmio_vbase, BR(1)+2, bpp);\
226 xgiCmdQueLen --;
227
228#define XGI300SetupRect(w,h) \
229 if (xgiCmdQueLen <= 0) XGI300Idle;\
230 MMIO_OUT32(xgi_video_info.mmio_vbase, BR(6), (h)<<16 | (w) );\
231 xgiCmdQueLen --;
232
233#define XGI300SetupPATFG(color) \
234 if (xgiCmdQueLen <= 0) XGI300Idle;\
235 MMIO_OUT32(xgi_video_info.mmio_vbase, BR(7), color);\
236 xgiCmdQueLen --;
237
238#define XGI300SetupPATBG(color) \
239 if (xgiCmdQueLen <= 0) XGI300Idle;\
240 MMIO_OUT32(xgi_video_info.mmio_vbase, BR(8), color);\
241 xgiCmdQueLen --;
242
243#define XGI300SetupSRCFG(color) \
244 if (xgiCmdQueLen <= 0) XGI300Idle;\
245 MMIO_OUT32(xgi_video_info.mmio_vbase, BR(9), color);\
246 xgiCmdQueLen --;
247
248#define XGI300SetupSRCBG(color) \
249 if (xgiCmdQueLen <= 0) XGI300Idle;\
250 MMIO_OUT32(xgi_video_info.mmio_vbase, BR(10), color);\
251 xgiCmdQueLen --;
252
253/* 0x8224 src colorkey high */
254/* 0x8228 src colorkey low */
255/* 0x821c dest colorkey high */
256/* 0x8220 dest colorkey low */
257#define XGI300SetupSRCTrans(color) \
258 if (xgiCmdQueLen <= 1) XGI300Idle;\
259 MMIO_OUT32(xgi_video_info.mmio_vbase, 0x8224, color);\
260 MMIO_OUT32(xgi_video_info.mmio_vbase, 0x8228, color);\
261 xgiCmdQueLen -= 2;
262
263#define XGI300SetupDSTTrans(color) \
264 if (xgiCmdQueLen <= 1) XGI300Idle;\
265 MMIO_OUT32(xgi_video_info.mmio_vbase, 0x821C, color); \
266 MMIO_OUT32(xgi_video_info.mmio_vbase, 0x8220, color); \
267 xgiCmdQueLen -= 2;
268
269#define XGI300SetupMONOPAT(p0,p1) \
270 if (xgiCmdQueLen <= 1) XGI300Idle;\
271 MMIO_OUT32(xgi_video_info.mmio_vbase, BR(11), p0);\
272 MMIO_OUT32(xgi_video_info.mmio_vbase, BR(12), p1);\
273 xgiCmdQueLen -= 2;
274
275#define XGI300SetupClipLT(left,top) \
276 if (xgiCmdQueLen <= 0) XGI300Idle;\
277 MMIO_OUT32(xgi_video_info.mmio_vbase, BR(13), ((left) & 0xFFFF) | (top)<<16 );\
278 xgiCmdQueLen--;
279
280#define XGI300SetupClipRB(right,bottom) \
281 if (xgiCmdQueLen <= 0) XGI300Idle;\
282 MMIO_OUT32(xgi_video_info.mmio_vbase, BR(14), ((right) & 0xFFFF) | (bottom)<<16 );\
283 xgiCmdQueLen--;
284
285/* General */
286#define XGI300SetupROP(rop) \
287 xgi_video_info.CommandReg = (rop) << 8;
288
289#define XGI300SetupCMDFlag(flags) \
290 xgi_video_info.CommandReg |= (flags);
291
292#define XGI300DoCMD \
293 if (xgiCmdQueLen <= 1) XGI300Idle;\
294 MMIO_OUT32(xgi_video_info.mmio_vbase, BR(15), xgi_video_info.CommandReg); \
295 MMIO_OUT32(xgi_video_info.mmio_vbase, BR(16), 0);\
296 xgiCmdQueLen -= 2;
297
298/* Line */
299#define XGI300SetupX0Y0(x,y) \
300 if (xgiCmdQueLen <= 0) XGI300Idle;\
301 MMIO_OUT32(xgi_video_info.mmio_vbase, BR(2), (y)<<16 | (x) );\
302 xgiCmdQueLen--;
303
304#define XGI300SetupX1Y1(x,y) \
305 if (xgiCmdQueLen <= 0) XGI300Idle;\
306 MMIO_OUT32(xgi_video_info.mmio_vbase, BR(3), (y)<<16 | (x) );\
307 xgiCmdQueLen--;
308
309#define XGI300SetupLineCount(c) \
310 if (xgiCmdQueLen <= 0) XGI300Idle;\
311 MMIO_OUT16(xgi_video_info.mmio_vbase, BR(6), c);\
312 xgiCmdQueLen--;
313
314#define XGI300SetupStylePeriod(p) \
315 if (xgiCmdQueLen <= 0) XGI300Idle;\
316 MMIO_OUT16(xgi_video_info.mmio_vbase, BR(6)+2, p);\
317 xgiCmdQueLen--;
318
319#define XGI300SetupStyleLow(ls) \
320 if (xgiCmdQueLen <= 0) XGI300Idle;\
321 MMIO_OUT32(xgi_video_info.mmio_vbase, BR(11), ls);\
322 xgiCmdQueLen--;
323
324#define XGI300SetupStyleHigh(ls) \
325 if (xgiCmdQueLen <= 0) XGI300Idle;\
326 MMIO_OUT32(xgi_video_info.mmio_vbase, BR(12), ls);\
327 xgiCmdQueLen--;
328
329
330
331/* ----------- XGI 310/325 series --------------- */
332
333/* Q_STATUS:
334 bit 31 = 1: All engines idle and all queues empty
335 bit 30 = 1: Hardware Queue (=HW CQ, 2D queue, 3D queue) empty
336 bit 29 = 1: 2D engine is idle
337 bit 28 = 1: 3D engine is idle
338 bit 27 = 1: HW command queue empty
339 bit 26 = 1: 2D queue empty
340 bit 25 = 1: 3D queue empty
341 bit 24 = 1: SW command queue empty
342 bits 23:16: 2D counter 3
343 bits 15:8: 2D counter 2
344 bits 7:0: 2D counter 1
345
346 Where is the command queue length (current amount of commands the queue
347 can accept) on the 310/325 series? (The current implementation is taken
348 from 300 series and certainly wrong...)
349*/
350
351/* TW: FIXME: xgiCmdQueLen is... where....? */
352#define XGI310Idle \
353 { \
354 while( (MMIO_IN16(xgi_video_info.mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
355 while( (MMIO_IN16(xgi_video_info.mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
356 xgiCmdQueLen=MMIO_IN16(xgi_video_info.mmio_vbase, Q_STATUS); \
357 }
358
359#define XGI310SetupSRCBase(base) \
360 if (xgiCmdQueLen <= 0) XGI310Idle;\
361 MMIO_OUT32(xgi_video_info.mmio_vbase, SRC_ADDR, base);\
362 xgiCmdQueLen--;
363
364#define XGI310SetupSRCPitch(pitch) \
365 if (xgiCmdQueLen <= 0) XGI310Idle;\
366 MMIO_OUT16(xgi_video_info.mmio_vbase, SRC_PITCH, pitch);\
367 xgiCmdQueLen--;
368
369#define XGI310SetupSRCXY(x,y) \
370 if (xgiCmdQueLen <= 0) XGI310Idle;\
371 MMIO_OUT32(xgi_video_info.mmio_vbase, SRC_Y, (x)<<16 | (y) );\
372 xgiCmdQueLen--;
373
374#define XGI310SetupDSTBase(base) \
375 if (xgiCmdQueLen <= 0) XGI310Idle;\
376 MMIO_OUT32(xgi_video_info.mmio_vbase, DST_ADDR, base);\
377 xgiCmdQueLen--;
378
379#define XGI310SetupDSTXY(x,y) \
380 if (xgiCmdQueLen <= 0) XGI310Idle;\
381 MMIO_OUT32(xgi_video_info.mmio_vbase, DST_Y, (x)<<16 | (y) );\
382 xgiCmdQueLen--;
383
384#define XGI310SetupDSTRect(x,y) \
385 if (xgiCmdQueLen <= 0) XGI310Idle;\
386 MMIO_OUT32(xgi_video_info.mmio_vbase, DST_PITCH, (y)<<16 | (x) );\
387 xgiCmdQueLen--;
388
389#define XGI310SetupDSTColorDepth(bpp) \
390 if (xgiCmdQueLen <= 0) XGI310Idle;\
391 MMIO_OUT16(xgi_video_info.mmio_vbase, AGP_BASE, bpp);\
392 xgiCmdQueLen--;
393
394#define XGI310SetupRect(w,h) \
395 if (xgiCmdQueLen <= 0) XGI310Idle;\
396 MMIO_OUT32(xgi_video_info.mmio_vbase, RECT_WIDTH, (h)<<16 | (w) );\
397 xgiCmdQueLen--;
398
399#define XGI310SetupPATFG(color) \
400 if (xgiCmdQueLen <= 0) XGI310Idle;\
401 MMIO_OUT32(xgi_video_info.mmio_vbase, PAT_FGCOLOR, color);\
402 xgiCmdQueLen--;
403
404#define XGI310SetupPATBG(color) \
405 if (xgiCmdQueLen <= 0) XGI310Idle;\
406 MMIO_OUT32(xgi_video_info.mmio_vbase, PAT_BGCOLOR, color);\
407 xgiCmdQueLen--;
408
409#define XGI310SetupSRCFG(color) \
410 if (xgiCmdQueLen <= 0) XGI310Idle;\
411 MMIO_OUT32(xgi_video_info.mmio_vbase, SRC_FGCOLOR, color);\
412 xgiCmdQueLen--;
413
414#define XGI310SetupSRCBG(color) \
415 if (xgiCmdQueLen <= 0) XGI310Idle;\
416 MMIO_OUT32(xgi_video_info.mmio_vbase, SRC_BGCOLOR, color);\
417 xgiCmdQueLen--;
418
419#define XGI310SetupSRCTrans(color) \
420 if (xgiCmdQueLen <= 1) XGI310Idle;\
421 MMIO_OUT32(xgi_video_info.mmio_vbase, TRANS_SRC_KEY_HIGH, color);\
422 MMIO_OUT32(xgi_video_info.mmio_vbase, TRANS_SRC_KEY_LOW, color);\
423 xgiCmdQueLen -= 2;
424
425#define XGI310SetupDSTTrans(color) \
426 if (xgiCmdQueLen <= 1) XGI310Idle;\
427 MMIO_OUT32(xgi_video_info.mmio_vbase, TRANS_DST_KEY_HIGH, color); \
428 MMIO_OUT32(xgi_video_info.mmio_vbase, TRANS_DST_KEY_LOW, color); \
429 xgiCmdQueLen -= 2;
430
431#define XGI310SetupMONOPAT(p0,p1) \
432 if (xgiCmdQueLen <= 1) XGI310Idle;\
433 MMIO_OUT32(xgi_video_info.mmio_vbase, MONO_MASK, p0);\
434 MMIO_OUT32(xgi_video_info.mmio_vbase, MONO_MASK+4, p1);\
435 xgiCmdQueLen -= 2;
436
437#define XGI310SetupClipLT(left,top) \
438 if (xgiCmdQueLen <= 0) XGI310Idle;\
439 MMIO_OUT32(xgi_video_info.mmio_vbase, LEFT_CLIP, ((left) & 0xFFFF) | (top)<<16 );\
440 xgiCmdQueLen--;
441
442#define XGI310SetupClipRB(right,bottom) \
443 if (xgiCmdQueLen <= 0) XGI310Idle;\
444 MMIO_OUT32(xgi_video_info.mmio_vbase, RIGHT_CLIP, ((right) & 0xFFFF) | (bottom)<<16 );\
445 xgiCmdQueLen--;
446
447#define XGI310SetupROP(rop) \
448 xgi_video_info.CommandReg = (rop) << 8;
449
450#define XGI310SetupCMDFlag(flags) \
451 xgi_video_info.CommandReg |= (flags);
452
453#define XGI310DoCMD \
454 if (xgiCmdQueLen <= 1) XGI310Idle;\
455 MMIO_OUT32(xgi_video_info.mmio_vbase, COMMAND_READY, xgi_video_info.CommandReg); \
456 MMIO_OUT32(xgi_video_info.mmio_vbase, FIRE_TRIGGER, 0); \
457 xgiCmdQueLen -= 2;
458
459#define XGI310SetupX0Y0(x,y) \
460 if (xgiCmdQueLen <= 0) XGI310Idle;\
461 MMIO_OUT32(xgi_video_info.mmio_vbase, LINE_X0, (y)<<16 | (x) );\
462 xgiCmdQueLen--;
463
464#define XGI310SetupX1Y1(x,y) \
465 if (xgiCmdQueLen <= 0) XGI310Idle;\
466 MMIO_OUT32(xgi_video_info.mmio_vbase, LINE_X1, (y)<<16 | (x) );\
467 xgiCmdQueLen--;
468
469#define XGI310SetupLineCount(c) \
470 if (xgiCmdQueLen <= 0) XGI310Idle;\
471 MMIO_OUT16(xgi_video_info.mmio_vbase, LINE_COUNT, c);\
472 xgiCmdQueLen--;
473
474#define XGI310SetupStylePeriod(p) \
475 if (xgiCmdQueLen <= 0) XGI310Idle;\
476 MMIO_OUT16(xgi_video_info.mmio_vbase, LINE_STYLE_PERIOD, p);\
477 xgiCmdQueLen--;
478
479#define XGI310SetupStyleLow(ls) \
480 if (xgiCmdQueLen <= 0) XGI310Idle;\
481 MMIO_OUT32(xgi_video_info.mmio_vbase, LINE_STYLE_0, ls);\
482 xgiCmdQueLen--;
483
484#define XGI310SetupStyleHigh(ls) \
485 if (xgiCmdQueLen <= 0) XGI310Idle;\
486 MMIO_OUT32(xgi_video_info.mmio_vbase, LINE_STYLE_1, ls);\
487 xgiCmdQueLen--;
488
489int XGIfb_initaccel(void);
490void XGIfb_syncaccel(void);
491
492extern struct video_info xgi_video_info;
493
494#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,33)
495void fbcon_XGI_bmove(struct display *p, int srcy, int srcx, int dsty,
496 int dstx, int height, int width);
497void fbcon_XGI_revc(struct display *p, int srcy, int srcx);
498void fbcon_XGI_clear8(struct vc_data *conp, struct display *p, int srcy,
499 int srcx, int height, int width);
500void fbcon_XGI_clear16(struct vc_data *conp, struct display *p, int srcy,
501 int srcx, int height, int width);
502void fbcon_XGI_clear32(struct vc_data *conp, struct display *p, int srcy,
503 int srcx, int height, int width);
504#endif
505#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34)
506extern int XGIfb_accel;
507void fbcon_XGI_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
508void fbcon_XGI_copyarea(struct fb_info *info, const struct fb_copyarea *area);
509#endif
510
511#endif
diff --git a/drivers/staging/xgifb/XGI_main.h b/drivers/staging/xgifb/XGI_main.h
new file mode 100644
index 000000000000..4f4171e8a68a
--- /dev/null
+++ b/drivers/staging/xgifb/XGI_main.h
@@ -0,0 +1,1023 @@
1#ifndef _XGIFB_MAIN
2#define _XGIFB_MAIN
3
4
5/* ------------------- Constant Definitions ------------------------- */
6
7
8#include "XGIfb.h"
9#include "vb_struct.h"
10#include "vb_def.h"
11
12//#define LINUXBIOS /* turn this on when compiling for LINUXBIOS */
13#define AGPOFF /* default is turn off AGP */
14
15#define XGIFAIL(x) do { printk(x "\n"); return -EINVAL; } while(0)
16
17#define VER_MAJOR 0
18#define VER_MINOR 8
19#define VER_LEVEL 1
20
21#define DRIVER_DESC "XGI Volari Frame Buffer Module Version 0.8.1"
22
23#ifndef PCI_VENDOR_ID_XG
24#define PCI_VENDOR_ID_XG 0x18CA
25#endif
26
27#ifndef PCI_DEVICE_ID_XG_40
28#define PCI_DEVICE_ID_XG_40 0x040
29#endif
30#ifndef PCI_DEVICE_ID_XG_41
31#define PCI_DEVICE_ID_XG_41 0x041
32#endif
33#ifndef PCI_DEVICE_ID_XG_42
34#define PCI_DEVICE_ID_XG_42 0x042
35#endif
36#ifndef PCI_DEVICE_ID_XG_20
37#define PCI_DEVICE_ID_XG_20 0x020
38#endif
39#ifndef PCI_DEVICE_ID_XG_27
40#define PCI_DEVICE_ID_XG_27 0x027
41#endif
42
43
44
45#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
46#define XGI_IOTYPE1 void __iomem
47#define XGI_IOTYPE2 __iomem
48#define XGIINITSTATIC static
49#else
50#define XGI_IOTYPE1 unsigned char
51#define XGI_IOTYPE2
52#define XGIINITSTATIC
53#endif
54
55#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
56static struct pci_device_id __devinitdata xgifb_pci_table[] = {
57
58 { PCI_VENDOR_ID_XG, PCI_DEVICE_ID_XG_20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
59 { PCI_VENDOR_ID_XG, PCI_DEVICE_ID_XG_27, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
60 { PCI_VENDOR_ID_XG, PCI_DEVICE_ID_XG_40, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
61 { PCI_VENDOR_ID_XG, PCI_DEVICE_ID_XG_42, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3},
62 { 0 }
63};
64
65MODULE_DEVICE_TABLE(pci, xgifb_pci_table);
66#endif
67/* To be included in fb.h */
68#ifndef FB_ACCEL_XGI_GLAMOUR_2
69#define FB_ACCEL_XGI_GLAMOUR_2 40 /* XGI 315, 650, 740 */
70#endif
71#ifndef FB_ACCEL_XGI_XABRE
72#define FB_ACCEL_XGI_XABRE 41 /* XGI 330 ("Xabre") */
73#endif
74
75#define MAX_ROM_SCAN 0x10000
76
77#define HW_CURSOR_CAP 0x80
78#define TURBO_QUEUE_CAP 0x40
79#define AGP_CMD_QUEUE_CAP 0x20
80#define VM_CMD_QUEUE_CAP 0x10
81#define MMIO_CMD_QUEUE_CAP 0x08
82
83
84
85/* For 315 series */
86
87#define COMMAND_QUEUE_AREA_SIZE 0x80000 /* 512K */
88#define COMMAND_QUEUE_THRESHOLD 0x1F
89
90
91/* TW */
92#define HW_CURSOR_AREA_SIZE_315 0x4000 /* 16K */
93#define HW_CURSOR_AREA_SIZE_300 0x1000 /* 4K */
94
95#define OH_ALLOC_SIZE 4000
96#define SENTINEL 0x7fffffff
97
98#define SEQ_ADR 0x14
99#define SEQ_DATA 0x15
100#define DAC_ADR 0x18
101#define DAC_DATA 0x19
102#define CRTC_ADR 0x24
103#define CRTC_DATA 0x25
104#define DAC2_ADR (0x16-0x30)
105#define DAC2_DATA (0x17-0x30)
106#define VB_PART1_ADR (0x04-0x30)
107#define VB_PART1_DATA (0x05-0x30)
108#define VB_PART2_ADR (0x10-0x30)
109#define VB_PART2_DATA (0x11-0x30)
110#define VB_PART3_ADR (0x12-0x30)
111#define VB_PART3_DATA (0x13-0x30)
112#define VB_PART4_ADR (0x14-0x30)
113#define VB_PART4_DATA (0x15-0x30)
114
115#define XGISR XGI_Pr.P3c4
116#define XGICR XGI_Pr.P3d4
117#define XGIDACA XGI_Pr.P3c8
118#define XGIDACD XGI_Pr.P3c9
119#define XGIPART1 XGI_Pr.Part1Port
120#define XGIPART2 XGI_Pr.Part2Port
121#define XGIPART3 XGI_Pr.Part3Port
122#define XGIPART4 XGI_Pr.Part4Port
123#define XGIPART5 XGI_Pr.Part5Port
124#define XGIDAC2A XGIPART5
125#define XGIDAC2D (XGIPART5 + 1)
126#define XGIMISCR (XGI_Pr.RelIO + 0x1c)
127#define XGIINPSTAT (XGI_Pr.RelIO + 0x2a)
128
129#define IND_XGI_PASSWORD 0x05 /* SRs */
130#define IND_XGI_COLOR_MODE 0x06
131#define IND_XGI_RAMDAC_CONTROL 0x07
132#define IND_XGI_DRAM_SIZE 0x14
133#define IND_XGI_SCRATCH_REG_16 0x16
134#define IND_XGI_SCRATCH_REG_17 0x17
135#define IND_XGI_SCRATCH_REG_1A 0x1A
136#define IND_XGI_MODULE_ENABLE 0x1E
137#define IND_XGI_PCI_ADDRESS_SET 0x20
138#define IND_XGI_TURBOQUEUE_ADR 0x26
139#define IND_XGI_TURBOQUEUE_SET 0x27
140#define IND_XGI_POWER_ON_TRAP 0x38
141#define IND_XGI_POWER_ON_TRAP2 0x39
142#define IND_XGI_CMDQUEUE_SET 0x26
143#define IND_XGI_CMDQUEUE_THRESHOLD 0x27
144
145#define IND_XGI_SCRATCH_REG_CR30 0x30 /* CRs */
146#define IND_XGI_SCRATCH_REG_CR31 0x31
147#define IND_XGI_SCRATCH_REG_CR32 0x32
148#define IND_XGI_SCRATCH_REG_CR33 0x33
149#define IND_XGI_LCD_PANEL 0x36
150#define IND_XGI_SCRATCH_REG_CR37 0x37
151#define IND_XGI_AGP_IO_PAD 0x48
152
153#define IND_BRI_DRAM_STATUS 0x63 /* PCI config memory size offset */
154
155#define MMIO_QUEUE_PHYBASE 0x85C0
156#define MMIO_QUEUE_WRITEPORT 0x85C4
157#define MMIO_QUEUE_READPORT 0x85C8
158
159#define IND_XGI_CRT2_WRITE_ENABLE_300 0x24
160#define IND_XGI_CRT2_WRITE_ENABLE_315 0x2F
161
162#define XGI_PASSWORD 0x86 /* SR05 */
163#define XGI_INTERLACED_MODE 0x20 /* SR06 */
164#define XGI_8BPP_COLOR_MODE 0x0
165#define XGI_15BPP_COLOR_MODE 0x1
166#define XGI_16BPP_COLOR_MODE 0x2
167#define XGI_32BPP_COLOR_MODE 0x4
168
169#define XGI_DRAM_SIZE_MASK 0xF0 /*SR14 */
170#define XGI_DRAM_SIZE_1MB 0x00
171#define XGI_DRAM_SIZE_2MB 0x01
172#define XGI_DRAM_SIZE_4MB 0x02
173#define XGI_DRAM_SIZE_8MB 0x03
174#define XGI_DRAM_SIZE_16MB 0x04
175#define XGI_DRAM_SIZE_32MB 0x05
176#define XGI_DRAM_SIZE_64MB 0x06
177#define XGI_DRAM_SIZE_128MB 0x07
178#define XGI_DRAM_SIZE_256MB 0x08
179#define XGI_DATA_BUS_MASK 0x02
180#define XGI_DATA_BUS_64 0x00
181#define XGI_DATA_BUS_128 0x01
182#define XGI_DUAL_CHANNEL_MASK 0x0C
183#define XGI_SINGLE_CHANNEL_1_RANK 0x0
184#define XGI_SINGLE_CHANNEL_2_RANK 0x1
185#define XGI_ASYM_DDR 0x02
186#define XGI_DUAL_CHANNEL_1_RANK 0x3
187
188#define XGI550_DRAM_SIZE_MASK 0x3F /* 550/650/740 SR14 */
189#define XGI550_DRAM_SIZE_4MB 0x00
190#define XGI550_DRAM_SIZE_8MB 0x01
191#define XGI550_DRAM_SIZE_16MB 0x03
192#define XGI550_DRAM_SIZE_24MB 0x05
193#define XGI550_DRAM_SIZE_32MB 0x07
194#define XGI550_DRAM_SIZE_64MB 0x0F
195#define XGI550_DRAM_SIZE_96MB 0x17
196#define XGI550_DRAM_SIZE_128MB 0x1F
197#define XGI550_DRAM_SIZE_256MB 0x3F
198
199#define XGI_SCRATCH_REG_1A_MASK 0x10
200
201#define XGI_ENABLE_2D 0x40 /* SR1E */
202
203#define XGI_MEM_MAP_IO_ENABLE 0x01 /* SR20 */
204#define XGI_PCI_ADDR_ENABLE 0x80
205
206#define XGI_AGP_CMDQUEUE_ENABLE 0x80 /* 315/650/740 SR26 */
207#define XGI_VRAM_CMDQUEUE_ENABLE 0x40
208#define XGI_MMIO_CMD_ENABLE 0x20
209#define XGI_CMD_QUEUE_SIZE_512k 0x00
210#define XGI_CMD_QUEUE_SIZE_1M 0x04
211#define XGI_CMD_QUEUE_SIZE_2M 0x08
212#define XGI_CMD_QUEUE_SIZE_4M 0x0C
213#define XGI_CMD_QUEUE_RESET 0x01
214#define XGI_CMD_AUTO_CORR 0x02
215
216#define XGI_SIMULTANEOUS_VIEW_ENABLE 0x01 /* CR30 */
217#define XGI_MODE_SELECT_CRT2 0x02
218#define XGI_VB_OUTPUT_COMPOSITE 0x04
219#define XGI_VB_OUTPUT_SVIDEO 0x08
220#define XGI_VB_OUTPUT_SCART 0x10
221#define XGI_VB_OUTPUT_LCD 0x20
222#define XGI_VB_OUTPUT_CRT2 0x40
223#define XGI_VB_OUTPUT_HIVISION 0x80
224
225#define XGI_VB_OUTPUT_DISABLE 0x20 /* CR31 */
226#define XGI_DRIVER_MODE 0x40
227
228#define XGI_VB_COMPOSITE 0x01 /* CR32 */
229#define XGI_VB_SVIDEO 0x02
230#define XGI_VB_SCART 0x04
231#define XGI_VB_LCD 0x08
232#define XGI_VB_CRT2 0x10
233#define XGI_CRT1 0x20
234#define XGI_VB_HIVISION 0x40
235#define XGI_VB_YPBPR 0x80
236#define XGI_VB_TV (XGI_VB_COMPOSITE | XGI_VB_SVIDEO | \
237 XGI_VB_SCART | XGI_VB_HIVISION|XGI_VB_YPBPR)
238
239#define XGI_EXTERNAL_CHIP_MASK 0x0E /* CR37 */
240#define XGI_EXTERNAL_CHIP_XGI301 0x01 /* in CR37 << 1 ! */
241#define XGI_EXTERNAL_CHIP_LVDS 0x02 /* in CR37 << 1 ! */
242#define XGI_EXTERNAL_CHIP_TRUMPION 0x03 /* in CR37 << 1 ! */
243#define XGI_EXTERNAL_CHIP_LVDS_CHRONTEL 0x04 /* in CR37 << 1 ! */
244#define XGI_EXTERNAL_CHIP_CHRONTEL 0x05 /* in CR37 << 1 ! */
245#define XGI310_EXTERNAL_CHIP_LVDS 0x02 /* in CR37 << 1 ! */
246#define XGI310_EXTERNAL_CHIP_LVDS_CHRONTEL 0x03 /* in CR37 << 1 ! */
247
248#define XGI_AGP_2X 0x20 /* CR48 */
249
250#define BRI_DRAM_SIZE_MASK 0x70 /* PCI bridge config data */
251#define BRI_DRAM_SIZE_2MB 0x00
252#define BRI_DRAM_SIZE_4MB 0x01
253#define BRI_DRAM_SIZE_8MB 0x02
254#define BRI_DRAM_SIZE_16MB 0x03
255#define BRI_DRAM_SIZE_32MB 0x04
256#define BRI_DRAM_SIZE_64MB 0x05
257
258#define HW_DEVICE_EXTENSION XGI_HW_DEVICE_INFO
259#define PHW_DEVICE_EXTENSION PXGI_HW_DEVICE_INFO
260
261#define SR_BUFFER_SIZE 5
262#define CR_BUFFER_SIZE 5
263
264/* Useful macros */
265#define inXGIREG(base) inb(base)
266#define outXGIREG(base,val) outb(val,base)
267#define orXGIREG(base,val) do { \
268 unsigned char __Temp = inb(base); \
269 outXGIREG(base, __Temp | (val)); \
270 } while (0)
271#define andXGIREG(base,val) do { \
272 unsigned char __Temp = inb(base); \
273 outXGIREG(base, __Temp & (val)); \
274 } while (0)
275#define inXGIIDXREG(base,idx,var) do { \
276 outb(idx,base); var=inb((base)+1); \
277 } while (0)
278#define outXGIIDXREG(base,idx,val) do { \
279 outb(idx,base); outb((val),(base)+1); \
280 } while (0)
281#define orXGIIDXREG(base,idx,val) do { \
282 unsigned char __Temp; \
283 outb(idx,base); \
284 __Temp = inb((base)+1)|(val); \
285 outXGIIDXREG(base,idx,__Temp); \
286 } while (0)
287#define andXGIIDXREG(base,idx,and) do { \
288 unsigned char __Temp; \
289 outb(idx,base); \
290 __Temp = inb((base)+1)&(and); \
291 outXGIIDXREG(base,idx,__Temp); \
292 } while (0)
293#define setXGIIDXREG(base,idx,and,or) do { \
294 unsigned char __Temp; \
295 outb(idx,base); \
296 __Temp = (inb((base)+1)&(and))|(or); \
297 outXGIIDXREG(base,idx,__Temp); \
298 } while (0)
299
300/* ------------------- Global Variables ----------------------------- */
301
302/* Fbcon variables */
303#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
304static struct fb_info* fb_info;
305#else
306static struct fb_info XGI_fb_info;
307#endif
308
309
310static int video_type = FB_TYPE_PACKED_PIXELS;
311
312static struct fb_var_screeninfo default_var = {
313 .xres = 0,
314 .yres = 0,
315 .xres_virtual = 0,
316 .yres_virtual = 0,
317 .xoffset = 0,
318 .yoffset = 0,
319 .bits_per_pixel = 0,
320 .grayscale = 0,
321 .red = {0, 8, 0},
322 .green = {0, 8, 0},
323 .blue = {0, 8, 0},
324 .transp = {0, 0, 0},
325 .nonstd = 0,
326 .activate = FB_ACTIVATE_NOW,
327 .height = -1,
328 .width = -1,
329 .accel_flags = 0,
330 .pixclock = 0,
331 .left_margin = 0,
332 .right_margin = 0,
333 .upper_margin = 0,
334 .lower_margin = 0,
335 .hsync_len = 0,
336 .vsync_len = 0,
337 .sync = 0,
338 .vmode = FB_VMODE_NONINTERLACED,
339#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
340 .reserved = {0, 0, 0, 0, 0, 0}
341#endif
342};
343
344#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
345static struct fb_fix_screeninfo XGIfb_fix = {
346 .id = "XGI",
347 .type = FB_TYPE_PACKED_PIXELS,
348 .xpanstep = 1,
349 .ypanstep = 1,
350};
351static char myid[20];
352static u32 pseudo_palette[17];
353#endif
354
355#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
356static struct display XGI_disp;
357
358static struct display_switch XGIfb_sw;
359
360static struct {
361 u16 blue, green, red, pad;
362} XGI_palette[256];
363
364static union {
365#ifdef FBCON_HAS_CFB16
366 u16 cfb16[16];
367#endif
368#ifdef FBCON_HAS_CFB32
369 u32 cfb32[16];
370#endif
371} XGI_fbcon_cmap;
372
373static int XGIfb_inverse = 0;
374#endif
375
376/* display status */
377static int XGIfb_off = 0;
378static int XGIfb_crt1off = 0;
379static int XGIfb_forcecrt1 = -1;
380static int XGIvga_enabled = 0;
381static int XGIfb_userom = 0;
382//static int XGIfb_useoem = -1;
383#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
384static int currcon = 0;
385#endif
386
387/* global flags */
388static int XGIfb_registered;
389static int XGIfb_tvmode = 0;
390static int XGIfb_mem = 0;
391static int XGIfb_pdc = 0;
392static int enable_dstn = 0;
393static int XGIfb_ypan = -1;
394
395
396int XGIfb_accel = 0;
397
398
399static int XGIfb_hwcursor_size = 0;
400static int XGIfb_CRT2_write_enable = 0;
401
402int XGIfb_crt2type = -1; /* TW: CRT2 type (for overriding autodetection) */
403int XGIfb_tvplug = -1; /* PR: Tv plug type (for overriding autodetection) */
404
405int XGIfb_queuemode = -1; /* TW: Use MMIO queue mode by default (310/325 series only) */
406
407unsigned char XGIfb_detectedpdc = 0;
408
409unsigned char XGIfb_detectedlcda = 0xff;
410
411
412
413
414/* TW: For ioctl XGIFB_GET_INFO */
415/* XGIfb_info XGIfbinfo; */
416
417/* TW: Hardware extension; contains data on hardware */
418HW_DEVICE_EXTENSION XGIhw_ext;
419
420/* TW: XGI private structure */
421VB_DEVICE_INFO XGI_Pr;
422
423/* card parameters */
424static unsigned long XGIfb_mmio_size = 0;
425static u8 XGIfb_caps = 0;
426
427typedef enum _XGI_CMDTYPE {
428 MMIO_CMD = 0,
429 AGP_CMD_QUEUE,
430 VM_CMD_QUEUE,
431} XGI_CMDTYPE;
432
433#define MD_XGI300 1
434#define MD_XGI315 2
435
436/* mode table */
437/* NOT const - will be patched for 1280x960 mode number chaos reasons */
438struct _XGIbios_mode {
439 char name[15];
440 u8 mode_no;
441 u16 vesa_mode_no_1; /* "XGI defined" VESA mode number */
442 u16 vesa_mode_no_2; /* Real VESA mode numbers */
443 u16 xres;
444 u16 yres;
445 u16 bpp;
446 u16 rate_idx;
447 u16 cols;
448 u16 rows;
449 u8 chipset;
450} XGIbios_mode[] = {
451#define MODE_INDEX_NONE 0 /* TW: index for mode=none */
452 {"none", 0xFF, 0x0000, 0x0000, 0, 0, 0, 0, 0, 0, MD_XGI300|MD_XGI315}, /* TW: for mode "none" */
453 {"320x240x16", 0x56, 0x0000, 0x0000, 320, 240, 16, 1, 40, 15, MD_XGI315},
454 {"320x480x8", 0x5A, 0x0000, 0x0000, 320, 480, 8, 1, 40, 30, MD_XGI315}, /* TW: FSTN */
455 {"320x480x16", 0x5B, 0x0000, 0x0000, 320, 480, 16, 1, 40, 30, MD_XGI315}, /* TW: FSTN */
456 {"640x480x8", 0x2E, 0x0101, 0x0101, 640, 480, 8, 1, 80, 30, MD_XGI300|MD_XGI315},
457 {"640x480x16", 0x44, 0x0111, 0x0111, 640, 480, 16, 1, 80, 30, MD_XGI300|MD_XGI315},
458 {"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 */
459 {"640x480x32", 0x62, 0x013a, 0x0112, 640, 480, 32, 1, 80, 30, MD_XGI300|MD_XGI315},
460 {"720x480x8", 0x31, 0x0000, 0x0000, 720, 480, 8, 1, 90, 30, MD_XGI300|MD_XGI315},
461 {"720x480x16", 0x33, 0x0000, 0x0000, 720, 480, 16, 1, 90, 30, MD_XGI300|MD_XGI315},
462 {"720x480x24", 0x35, 0x0000, 0x0000, 720, 480, 32, 1, 90, 30, MD_XGI300|MD_XGI315},
463 {"720x480x32", 0x35, 0x0000, 0x0000, 720, 480, 32, 1, 90, 30, MD_XGI300|MD_XGI315},
464 {"720x576x8", 0x32, 0x0000, 0x0000, 720, 576, 8, 1, 90, 36, MD_XGI300|MD_XGI315},
465 {"720x576x16", 0x34, 0x0000, 0x0000, 720, 576, 16, 1, 90, 36, MD_XGI300|MD_XGI315},
466 {"720x576x24", 0x36, 0x0000, 0x0000, 720, 576, 32, 1, 90, 36, MD_XGI300|MD_XGI315},
467 {"720x576x32", 0x36, 0x0000, 0x0000, 720, 576, 32, 1, 90, 36, MD_XGI300|MD_XGI315},
468 {"800x480x8", 0x70, 0x0000, 0x0000, 800, 480, 8, 1, 100, 30, MD_XGI300|MD_XGI315},
469 {"800x480x16", 0x7a, 0x0000, 0x0000, 800, 480, 16, 1, 100, 30, MD_XGI300|MD_XGI315},
470 {"800x480x24", 0x76, 0x0000, 0x0000, 800, 480, 32, 1, 100, 30, MD_XGI300|MD_XGI315},
471 {"800x480x32", 0x76, 0x0000, 0x0000, 800, 480, 32, 1, 100, 30, MD_XGI300|MD_XGI315},
472#define DEFAULT_MODE 21 /* TW: index for 800x600x8 */
473#define DEFAULT_LCDMODE 21 /* TW: index for 800x600x8 */
474#define DEFAULT_TVMODE 21 /* TW: index for 800x600x8 */
475 {"800x600x8", 0x30, 0x0103, 0x0103, 800, 600, 8, 1, 100, 37, MD_XGI300|MD_XGI315},
476 {"800x600x16", 0x47, 0x0114, 0x0114, 800, 600, 16, 1, 100, 37, MD_XGI300|MD_XGI315},
477 {"800x600x24", 0x63, 0x013b, 0x0115, 800, 600, 32, 1, 100, 37, MD_XGI300|MD_XGI315},
478 {"800x600x32", 0x63, 0x013b, 0x0115, 800, 600, 32, 1, 100, 37, MD_XGI300|MD_XGI315},
479 {"1024x576x8", 0x71, 0x0000, 0x0000, 1024, 576, 8, 1, 128, 36, MD_XGI300|MD_XGI315},
480 {"1024x576x16", 0x74, 0x0000, 0x0000, 1024, 576, 16, 1, 128, 36, MD_XGI300|MD_XGI315},
481 {"1024x576x24", 0x77, 0x0000, 0x0000, 1024, 576, 32, 1, 128, 36, MD_XGI300|MD_XGI315},
482 {"1024x576x32", 0x77, 0x0000, 0x0000, 1024, 576, 32, 1, 128, 36, MD_XGI300|MD_XGI315},
483 {"1024x600x8", 0x20, 0x0000, 0x0000, 1024, 600, 8, 1, 128, 37, MD_XGI300 }, /* TW: 300 series only */
484 {"1024x600x16", 0x21, 0x0000, 0x0000, 1024, 600, 16, 1, 128, 37, MD_XGI300 },
485 {"1024x600x24", 0x22, 0x0000, 0x0000, 1024, 600, 32, 1, 128, 37, MD_XGI300 },
486 {"1024x600x32", 0x22, 0x0000, 0x0000, 1024, 600, 32, 1, 128, 37, MD_XGI300 },
487 {"1024x768x8", 0x38, 0x0105, 0x0105, 1024, 768, 8, 1, 128, 48, MD_XGI300|MD_XGI315},
488 {"1024x768x16", 0x4A, 0x0117, 0x0117, 1024, 768, 16, 1, 128, 48, MD_XGI300|MD_XGI315},
489 {"1024x768x24", 0x64, 0x013c, 0x0118, 1024, 768, 32, 1, 128, 48, MD_XGI300|MD_XGI315},
490 {"1024x768x32", 0x64, 0x013c, 0x0118, 1024, 768, 32, 1, 128, 48, MD_XGI300|MD_XGI315},
491 {"1152x768x8", 0x23, 0x0000, 0x0000, 1152, 768, 8, 1, 144, 48, MD_XGI300 }, /* TW: 300 series only */
492 {"1152x768x16", 0x24, 0x0000, 0x0000, 1152, 768, 16, 1, 144, 48, MD_XGI300 },
493 {"1152x768x24", 0x25, 0x0000, 0x0000, 1152, 768, 32, 1, 144, 48, MD_XGI300 },
494 {"1152x768x32", 0x25, 0x0000, 0x0000, 1152, 768, 32, 1, 144, 48, MD_XGI300 },
495 {"1280x720x8", 0x79, 0x0000, 0x0000, 1280, 720, 8, 1, 160, 45, MD_XGI300|MD_XGI315},
496 {"1280x720x16", 0x75, 0x0000, 0x0000, 1280, 720, 16, 1, 160, 45, MD_XGI300|MD_XGI315},
497 {"1280x720x24", 0x78, 0x0000, 0x0000, 1280, 720, 32, 1, 160, 45, MD_XGI300|MD_XGI315},
498 {"1280x720x32", 0x78, 0x0000, 0x0000, 1280, 720, 32, 1, 160, 45, MD_XGI300|MD_XGI315},
499 {"1280x768x8", 0x23, 0x0000, 0x0000, 1280, 768, 8, 1, 160, 48, MD_XGI315}, /* TW: 310/325 series only */
500 {"1280x768x16", 0x24, 0x0000, 0x0000, 1280, 768, 16, 1, 160, 48, MD_XGI315},
501 {"1280x768x24", 0x25, 0x0000, 0x0000, 1280, 768, 32, 1, 160, 48, MD_XGI315},
502 {"1280x768x32", 0x25, 0x0000, 0x0000, 1280, 768, 32, 1, 160, 48, MD_XGI315},
503#define MODEINDEX_1280x960 48
504 {"1280x960x8", 0x7C, 0x0000, 0x0000, 1280, 960, 8, 1, 160, 60, MD_XGI300|MD_XGI315}, /* TW: Modenumbers being patched */
505 {"1280x960x16", 0x7D, 0x0000, 0x0000, 1280, 960, 16, 1, 160, 60, MD_XGI300|MD_XGI315},
506 {"1280x960x24", 0x7E, 0x0000, 0x0000, 1280, 960, 32, 1, 160, 60, MD_XGI300|MD_XGI315},
507 {"1280x960x32", 0x7E, 0x0000, 0x0000, 1280, 960, 32, 1, 160, 60, MD_XGI300|MD_XGI315},
508 {"1280x1024x8", 0x3A, 0x0107, 0x0107, 1280, 1024, 8, 1, 160, 64, MD_XGI300|MD_XGI315},
509 {"1280x1024x16", 0x4D, 0x011a, 0x011a, 1280, 1024, 16, 1, 160, 64, MD_XGI300|MD_XGI315},
510 {"1280x1024x24", 0x65, 0x013d, 0x011b, 1280, 1024, 32, 1, 160, 64, MD_XGI300|MD_XGI315},
511 {"1280x1024x32", 0x65, 0x013d, 0x011b, 1280, 1024, 32, 1, 160, 64, MD_XGI300|MD_XGI315},
512 {"1400x1050x8", 0x26, 0x0000, 0x0000, 1400, 1050, 8, 1, 175, 65, MD_XGI315}, /* TW: 310/325 series only */
513 {"1400x1050x16", 0x27, 0x0000, 0x0000, 1400, 1050, 16, 1, 175, 65, MD_XGI315},
514 {"1400x1050x24", 0x28, 0x0000, 0x0000, 1400, 1050, 32, 1, 175, 65, MD_XGI315},
515 {"1400x1050x32", 0x28, 0x0000, 0x0000, 1400, 1050, 32, 1, 175, 65, MD_XGI315},
516 {"1600x1200x8", 0x3C, 0x0130, 0x011c, 1600, 1200, 8, 1, 200, 75, MD_XGI300|MD_XGI315},
517 {"1600x1200x16", 0x3D, 0x0131, 0x011e, 1600, 1200, 16, 1, 200, 75, MD_XGI300|MD_XGI315},
518 {"1600x1200x24", 0x66, 0x013e, 0x011f, 1600, 1200, 32, 1, 200, 75, MD_XGI300|MD_XGI315},
519 {"1600x1200x32", 0x66, 0x013e, 0x011f, 1600, 1200, 32, 1, 200, 75, MD_XGI300|MD_XGI315},
520 {"1920x1440x8", 0x68, 0x013f, 0x0000, 1920, 1440, 8, 1, 240, 75, MD_XGI300|MD_XGI315},
521 {"1920x1440x16", 0x69, 0x0140, 0x0000, 1920, 1440, 16, 1, 240, 75, MD_XGI300|MD_XGI315},
522 {"1920x1440x24", 0x6B, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_XGI300|MD_XGI315},
523 {"1920x1440x32", 0x6B, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_XGI300|MD_XGI315},
524 {"2048x1536x8", 0x6c, 0x0000, 0x0000, 2048, 1536, 8, 1, 256, 96, MD_XGI315}, /* TW: 310/325 series only */
525 {"2048x1536x16", 0x6d, 0x0000, 0x0000, 2048, 1536, 16, 1, 256, 96, MD_XGI315},
526 {"2048x1536x24", 0x6e, 0x0000, 0x0000, 2048, 1536, 32, 1, 256, 96, MD_XGI315},
527 {"2048x1536x32", 0x6e, 0x0000, 0x0000, 2048, 1536, 32, 1, 256, 96, MD_XGI315},
528 {"\0", 0x00, 0, 0, 0, 0, 0, 0, 0}
529};
530
531/* mode-related variables */
532#ifdef MODULE
533#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
534static int xgifb_mode_idx = 1;
535#else
536static int XGIfb_mode_idx = MODE_INDEX_NONE; /* Don't use a mode by default if we are a module */
537#endif
538#else
539#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
540static int xgifb_mode_idx = -1; /* Use a default mode if we are inside the kernel */
541#else
542static int XGIfb_mode_idx = -1;
543#endif
544#endif
545u8 XGIfb_mode_no = 0;
546u8 XGIfb_rate_idx = 0;
547
548/* TW: CR36 evaluation */
549const USHORT XGI300paneltype[] =
550 { LCD_UNKNOWN, LCD_800x600, LCD_1024x768, LCD_1280x1024,
551 LCD_1280x960, LCD_640x480, LCD_1024x600, LCD_1152x768,
552 LCD_1024x768, LCD_1024x768, LCD_1024x768,
553 LCD_1024x768, LCD_1024x768, LCD_1024x768, LCD_1024x768 };
554
555const USHORT XGI310paneltype[] =
556 { LCD_UNKNOWN, LCD_800x600, LCD_1024x768, LCD_1280x1024,
557 LCD_640x480, LCD_1024x600, LCD_1152x864, LCD_1280x960,
558 LCD_1152x768, LCD_1400x1050,LCD_1280x768, LCD_1600x1200,
559 LCD_1024x768, LCD_1024x768, LCD_1024x768 };
560
561static const struct _XGI_crt2type {
562 char name[10];
563 int type_no;
564 int tvplug_no;
565} XGI_crt2type[] = {
566 {"NONE", 0, -1},
567 {"LCD", DISPTYPE_LCD, -1},
568 {"TV", DISPTYPE_TV, -1},
569 {"VGA", DISPTYPE_CRT2, -1},
570 {"SVIDEO", DISPTYPE_TV, TVPLUG_SVIDEO},
571 {"COMPOSITE", DISPTYPE_TV, TVPLUG_COMPOSITE},
572 {"SCART", DISPTYPE_TV, TVPLUG_SCART},
573 {"none", 0, -1},
574 {"lcd", DISPTYPE_LCD, -1},
575 {"tv", DISPTYPE_TV, -1},
576 {"vga", DISPTYPE_CRT2, -1},
577 {"svideo", DISPTYPE_TV, TVPLUG_SVIDEO},
578 {"composite", DISPTYPE_TV, TVPLUG_COMPOSITE},
579 {"scart", DISPTYPE_TV, TVPLUG_SCART},
580 {"\0", -1, -1}
581};
582
583/* Queue mode selection for 310 series */
584static const struct _XGI_queuemode {
585 char name[6];
586 int type_no;
587} XGI_queuemode[] = {
588 {"AGP", AGP_CMD_QUEUE},
589 {"VRAM", VM_CMD_QUEUE},
590 {"MMIO", MMIO_CMD},
591 {"agp", AGP_CMD_QUEUE},
592 {"vram", VM_CMD_QUEUE},
593 {"mmio", MMIO_CMD},
594 {"\0", -1}
595};
596
597/* TV standard */
598static const struct _XGI_tvtype {
599 char name[6];
600 int type_no;
601} XGI_tvtype[] = {
602 {"PAL", 1},
603 {"NTSC", 2},
604 {"pal", 1},
605 {"ntsc", 2},
606 {"\0", -1}
607};
608
609static const struct _XGI_vrate {
610 u16 idx;
611 u16 xres;
612 u16 yres;
613 u16 refresh;
614} XGIfb_vrate[] = {
615 {1, 640, 480, 60}, {2, 640, 480, 72}, {3, 640, 480, 75}, {4, 640, 480, 85},
616 {5, 640, 480,100}, {6, 640, 480, 120}, {7, 640, 480, 160}, {8, 640, 480, 200},
617 {1, 720, 480, 60},
618 {1, 720, 576, 58},
619 {1, 800, 480, 60}, {2, 800, 480, 75}, {3, 800, 480, 85},
620 {1, 800, 600, 60}, {2, 800, 600, 72}, {3, 800, 600, 75},
621 {4, 800, 600, 85}, {5, 800, 600, 100}, {6, 800, 600, 120}, {7, 800, 600, 160},
622 {1, 1024, 768, 60}, {2, 1024, 768, 70}, {3, 1024, 768, 75},
623 {4, 1024, 768, 85}, {5, 1024, 768, 100}, {6, 1024, 768, 120},
624 {1, 1024, 576, 60}, {2, 1024, 576, 75}, {3, 1024, 576, 85},
625 {1, 1024, 600, 60},
626 {1, 1152, 768, 60},
627 {1, 1280, 720, 60}, {2, 1280, 720, 75}, {3, 1280, 720, 85},
628 {1, 1280, 768, 60},
629 {1, 1280, 1024, 60}, {2, 1280, 1024, 75}, {3, 1280, 1024, 85},
630 {1, 1280, 960, 70},
631 {1, 1400, 1050, 60},
632 {1, 1600, 1200, 60}, {2, 1600, 1200, 65}, {3, 1600, 1200, 70}, {4, 1600, 1200, 75},
633 {5, 1600, 1200, 85}, {6, 1600, 1200, 100}, {7, 1600, 1200, 120},
634 {1, 1920, 1440, 60}, {2, 1920, 1440, 65}, {3, 1920, 1440, 70}, {4, 1920, 1440, 75},
635 {5, 1920, 1440, 85}, {6, 1920, 1440, 100},
636 {1, 2048, 1536, 60}, {2, 2048, 1536, 65}, {3, 2048, 1536, 70}, {4, 2048, 1536, 75},
637 {5, 2048, 1536, 85},
638 {0, 0, 0, 0}
639};
640
641static const struct _chswtable {
642 int subsysVendor;
643 int subsysCard;
644 char *vendorName;
645 char *cardName;
646} mychswtable[] = {
647 { 0x1631, 0x1002, "Mitachi", "0x1002" },
648 { 0, 0, "" , "" }
649};
650
651#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
652/* Offscreen layout */
653typedef struct _XGI_GLYINFO {
654 unsigned char ch;
655 int fontwidth;
656 int fontheight;
657 u8 gmask[72];
658 int ngmask;
659} XGI_GLYINFO;
660#endif
661
662typedef struct _XGI_OH {
663 struct _XGI_OH *poh_next;
664 struct _XGI_OH *poh_prev;
665 unsigned long offset;
666 unsigned long size;
667} XGI_OH;
668
669typedef struct _XGI_OHALLOC {
670 struct _XGI_OHALLOC *poha_next;
671 XGI_OH aoh[1];
672} XGI_OHALLOC;
673
674typedef struct _XGI_HEAP {
675 XGI_OH oh_free;
676 XGI_OH oh_used;
677 XGI_OH *poh_freelist;
678 XGI_OHALLOC *poha_chain;
679 unsigned long max_freesize;
680} XGI_HEAP;
681
682static unsigned long XGIfb_hwcursor_vbase;
683
684static unsigned long XGIfb_heap_start;
685static unsigned long XGIfb_heap_end;
686static unsigned long XGIfb_heap_size;
687static XGI_HEAP XGIfb_heap;
688
689// Eden Chen
690static const struct _XGI_TV_filter {
691 u8 filter[9][4];
692} XGI_TV_filter[] = {
693 { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_0 */
694 {0x00,0xE0,0x10,0x60},
695 {0x00,0xEE,0x10,0x44},
696 {0x00,0xF4,0x10,0x38},
697 {0xF8,0xF4,0x18,0x38},
698 {0xFC,0xFB,0x14,0x2A},
699 {0x00,0x00,0x10,0x20},
700 {0x00,0x04,0x10,0x18},
701 {0xFF,0xFF,0xFF,0xFF} }},
702 { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_1 */
703 {0x00,0xE0,0x10,0x60},
704 {0x00,0xEE,0x10,0x44},
705 {0x00,0xF4,0x10,0x38},
706 {0xF8,0xF4,0x18,0x38},
707 {0xFC,0xFB,0x14,0x2A},
708 {0x00,0x00,0x10,0x20},
709 {0x00,0x04,0x10,0x18},
710 {0xFF,0xFF,0xFF,0xFF} }},
711 { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_2 */
712 {0xF5,0xEE,0x1B,0x44},
713 {0xF8,0xF4,0x18,0x38},
714 {0xEB,0x04,0x25,0x18},
715 {0xF1,0x05,0x1F,0x16},
716 {0xF6,0x06,0x1A,0x14},
717 {0xFA,0x06,0x16,0x14},
718 {0x00,0x04,0x10,0x18},
719 {0xFF,0xFF,0xFF,0xFF} }},
720 { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_3 */
721 {0xF1,0x04,0x1F,0x18},
722 {0xEE,0x0D,0x22,0x06},
723 {0xF7,0x06,0x19,0x14},
724 {0xF4,0x0B,0x1C,0x0A},
725 {0xFA,0x07,0x16,0x12},
726 {0xF9,0x0A,0x17,0x0C},
727 {0x00,0x07,0x10,0x12},
728 {0xFF,0xFF,0xFF,0xFF} }},
729 { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_4 */
730 {0x00,0xE0,0x10,0x60},
731 {0x00,0xEE,0x10,0x44},
732 {0x00,0xF4,0x10,0x38},
733 {0xF8,0xF4,0x18,0x38},
734 {0xFC,0xFB,0x14,0x2A},
735 {0x00,0x00,0x10,0x20},
736 {0x00,0x04,0x10,0x18},
737 {0xFF,0xFF,0xFF,0xFF} }},
738 { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_5 */
739 {0xF5,0xEE,0x1B,0x44},
740 {0xF8,0xF4,0x18,0x38},
741 {0xEB,0x04,0x25,0x18},
742 {0xF1,0x05,0x1F,0x16},
743 {0xF6,0x06,0x1A,0x14},
744 {0xFA,0x06,0x16,0x14},
745 {0x00,0x04,0x10,0x18},
746 {0xFF,0xFF,0xFF,0xFF} }},
747 { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_6 */
748 {0xEB,0x04,0x25,0x18},
749 {0xE7,0x0E,0x29,0x04},
750 {0xEE,0x0C,0x22,0x08},
751 {0xF6,0x0B,0x1A,0x0A},
752 {0xF9,0x0A,0x17,0x0C},
753 {0xFC,0x0A,0x14,0x0C},
754 {0x00,0x08,0x10,0x10},
755 {0xFF,0xFF,0xFF,0xFF} }},
756 { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_7 */
757 {0xEC,0x02,0x24,0x1C},
758 {0xF2,0x04,0x1E,0x18},
759 {0xEB,0x15,0x25,0xF6},
760 {0xF4,0x10,0x1C,0x00},
761 {0xF8,0x0F,0x18,0x02},
762 {0x00,0x04,0x10,0x18},
763 {0x01,0x06,0x0F,0x14},
764 {0xFF,0xFF,0xFF,0xFF} }},
765 { {{0x00,0x00,0x00,0x40}, /* PALFilter_0 */
766 {0x00,0xE0,0x10,0x60},
767 {0x00,0xEE,0x10,0x44},
768 {0x00,0xF4,0x10,0x38},
769 {0xF8,0xF4,0x18,0x38},
770 {0xFC,0xFB,0x14,0x2A},
771 {0x00,0x00,0x10,0x20},
772 {0x00,0x04,0x10,0x18},
773 {0xFF,0xFF,0xFF,0xFF} }},
774 { {{0x00,0x00,0x00,0x40}, /* PALFilter_1 */
775 {0x00,0xE0,0x10,0x60},
776 {0x00,0xEE,0x10,0x44},
777 {0x00,0xF4,0x10,0x38},
778 {0xF8,0xF4,0x18,0x38},
779 {0xFC,0xFB,0x14,0x2A},
780 {0x00,0x00,0x10,0x20},
781 {0x00,0x04,0x10,0x18},
782 {0xFF,0xFF,0xFF,0xFF} }},
783 { {{0x00,0x00,0x00,0x40}, /* PALFilter_2 */
784 {0xF5,0xEE,0x1B,0x44},
785 {0xF8,0xF4,0x18,0x38},
786 {0xF1,0xF7,0x01,0x32},
787 {0xF5,0xFB,0x1B,0x2A},
788 {0xF9,0xFF,0x17,0x22},
789 {0xFB,0x01,0x15,0x1E},
790 {0x00,0x04,0x10,0x18},
791 {0xFF,0xFF,0xFF,0xFF} }},
792 { {{0x00,0x00,0x00,0x40}, /* PALFilter_3 */
793 {0xF5,0xFB,0x1B,0x2A},
794 {0xEE,0xFE,0x22,0x24},
795 {0xF3,0x00,0x1D,0x20},
796 {0xF9,0x03,0x17,0x1A},
797 {0xFB,0x02,0x14,0x1E},
798 {0xFB,0x04,0x15,0x18},
799 {0x00,0x06,0x10,0x14},
800 {0xFF,0xFF,0xFF,0xFF} }},
801 { {{0x00,0x00,0x00,0x40}, /* PALFilter_4 */
802 {0x00,0xE0,0x10,0x60},
803 {0x00,0xEE,0x10,0x44},
804 {0x00,0xF4,0x10,0x38},
805 {0xF8,0xF4,0x18,0x38},
806 {0xFC,0xFB,0x14,0x2A},
807 {0x00,0x00,0x10,0x20},
808 {0x00,0x04,0x10,0x18},
809 {0xFF,0xFF,0xFF,0xFF} }},
810 { {{0x00,0x00,0x00,0x40}, /* PALFilter_5 */
811 {0xF5,0xEE,0x1B,0x44},
812 {0xF8,0xF4,0x18,0x38},
813 {0xF1,0xF7,0x1F,0x32},
814 {0xF5,0xFB,0x1B,0x2A},
815 {0xF9,0xFF,0x17,0x22},
816 {0xFB,0x01,0x15,0x1E},
817 {0x00,0x04,0x10,0x18},
818 {0xFF,0xFF,0xFF,0xFF} }},
819 { {{0x00,0x00,0x00,0x40}, /* PALFilter_6 */
820 {0xF5,0xEE,0x1B,0x2A},
821 {0xEE,0xFE,0x22,0x24},
822 {0xF3,0x00,0x1D,0x20},
823 {0xF9,0x03,0x17,0x1A},
824 {0xFB,0x02,0x14,0x1E},
825 {0xFB,0x04,0x15,0x18},
826 {0x00,0x06,0x10,0x14},
827 {0xFF,0xFF,0xFF,0xFF} }},
828 { {{0x00,0x00,0x00,0x40}, /* PALFilter_7 */
829 {0xF5,0xEE,0x1B,0x44},
830 {0xF8,0xF4,0x18,0x38},
831 {0xFC,0xFB,0x14,0x2A},
832 {0xEB,0x05,0x25,0x16},
833 {0xF1,0x05,0x1F,0x16},
834 {0xFA,0x07,0x16,0x12},
835 {0x00,0x07,0x10,0x12},
836 {0xFF,0xFF,0xFF,0xFF} }}
837};
838
839static int filter = -1;
840static unsigned char filter_tb;
841
842
843/* ---------------------- Routine prototypes ------------------------- */
844
845/* Interface used by the world */
846#ifndef MODULE
847XGIINITSTATIC int __init XGIfb_setup(char *options);
848#endif
849
850/* Interface to the low level console driver */
851
852
853
854/* fbdev routines */
855#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
856 int XGIfb_init(void);
857static int XGIfb_get_fix(struct fb_fix_screeninfo *fix,
858 int con,
859 struct fb_info *info);
860static int XGIfb_get_var(struct fb_var_screeninfo *var,
861 int con,
862 struct fb_info *info);
863static int XGIfb_set_var(struct fb_var_screeninfo *var,
864 int con,
865 struct fb_info *info);
866static void XGIfb_crtc_to_var(struct fb_var_screeninfo *var);
867static int XGIfb_get_cmap(struct fb_cmap *cmap,
868 int kspc,
869 int con,
870 struct fb_info *info);
871static int XGIfb_set_cmap(struct fb_cmap *cmap,
872 int kspc,
873 int con,
874 struct fb_info *info);
875static int XGIfb_update_var(int con,
876 struct fb_info *info);
877static int XGIfb_switch(int con,
878 struct fb_info *info);
879static void XGIfb_blank(int blank,
880 struct fb_info *info);
881static void XGIfb_set_disp(int con,
882 struct fb_var_screeninfo *var,
883 struct fb_info *info);
884static int XGI_getcolreg(unsigned regno, unsigned *red, unsigned *green,
885 unsigned *blue, unsigned *transp,
886 struct fb_info *fb_info);
887static void XGIfb_do_install_cmap(int con,
888 struct fb_info *info);
889static void XGI_get_glyph(struct fb_info *info,
890 XGI_GLYINFO *gly);
891static int XGIfb_mmap(struct fb_info *info, struct file *file,
892 struct vm_area_struct *vma);
893static int XGIfb_ioctl(struct inode *inode, struct file *file,
894 unsigned int cmd, unsigned long arg, int con,
895 struct fb_info *info);
896#endif
897
898#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
899XGIINITSTATIC int __init xgifb_init(void);
900static int XGIfb_set_par(struct fb_info *info);
901static int XGIfb_blank(int blank,
902 struct fb_info *info);
903/*static int XGIfb_mmap(struct fb_info *info, struct file *file,
904 struct vm_area_struct *vma);
905*/
906extern void fbcon_XGI_fillrect(struct fb_info *info,
907 const struct fb_fillrect *rect);
908extern void fbcon_XGI_copyarea(struct fb_info *info,
909 const struct fb_copyarea *area);
910#if 0
911extern void cfb_imageblit(struct fb_info *info,
912 const struct fb_image *image);
913#endif
914extern int fbcon_XGI_sync(struct fb_info *info);
915
916#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
917static int XGIfb_ioctl(struct fb_info *info, unsigned int cmd,
918 unsigned long arg);
919#else
920static int XGIfb_ioctl(struct inode *inode,
921 struct file *file,
922 unsigned int cmd,
923 unsigned long arg,
924 struct fb_info *info);
925#endif
926
927/*
928extern int XGIfb_mode_rate_to_dclock(VB_DEVICE_INFO *XGI_Pr,
929 PXGI_HW_DEVICE_INFO HwDeviceExtension,
930 unsigned char modeno, unsigned char rateindex);
931extern int XGIfb_mode_rate_to_ddata(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwDeviceExtension,
932 unsigned char modeno, unsigned char rateindex,
933 unsigned int *left_margin, unsigned int *right_margin,
934 unsigned int *upper_margin, unsigned int *lower_margin,
935 unsigned int *hsync_len, unsigned int *vsync_len,
936 unsigned int *sync, unsigned int *vmode);
937*/
938#endif
939 extern BOOLEAN XGI_SearchModeID( USHORT ModeNo,USHORT *ModeIdIndex, PVB_DEVICE_INFO );
940static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con,
941 struct fb_info *info);
942
943/* Internal 2D accelerator functions */
944extern int XGIfb_initaccel(void);
945extern void XGIfb_syncaccel(void);
946
947/* Internal general routines */
948static void XGIfb_search_mode(const char *name);
949static int XGIfb_validate_mode(int modeindex);
950static u8 XGIfb_search_refresh_rate(unsigned int rate);
951static int XGIfb_setcolreg(unsigned regno, unsigned red, unsigned green,
952 unsigned blue, unsigned transp,
953 struct fb_info *fb_info);
954static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
955 struct fb_info *info);
956static void XGIfb_pre_setmode(void);
957static void XGIfb_post_setmode(void);
958
959static BOOLEAN XGIfb_CheckVBRetrace(void);
960static BOOLEAN XGIfbcheckvretracecrt2(void);
961static BOOLEAN XGIfbcheckvretracecrt1(void);
962static BOOLEAN XGIfb_bridgeisslave(void);
963
964struct XGI_memreq {
965 unsigned long offset;
966 unsigned long size;
967};
968
969/* XGI-specific Export functions */
970void XGI_dispinfo(struct ap_data *rec);
971void XGI_malloc(struct XGI_memreq *req);
972void XGI_free(unsigned long base);
973
974/* Internal hardware access routines */
975void XGIfb_set_reg4(u16 port, unsigned long data);
976u32 XGIfb_get_reg3(u16 port);
977
978/* Chipset-dependent internal routines */
979
980
981static int XGIfb_get_dram_size(void);
982static void XGIfb_detect_VB(void);
983static void XGIfb_get_VB_type(void);
984static int XGIfb_has_VB(void);
985
986
987/* Internal heap routines */
988static int XGIfb_heap_init(void);
989static XGI_OH *XGIfb_poh_new_node(void);
990static XGI_OH *XGIfb_poh_allocate(unsigned long size);
991static void XGIfb_delete_node(XGI_OH *poh);
992static void XGIfb_insert_node(XGI_OH *pohList, XGI_OH *poh);
993static XGI_OH *XGIfb_poh_free(unsigned long base);
994static void XGIfb_free_node(XGI_OH *poh);
995
996/* Internal routines to access PCI configuration space */
997BOOLEAN XGIfb_query_VGA_config_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
998 unsigned long offset, unsigned long set, unsigned long *value);
999//BOOLEAN XGIfb_query_north_bridge_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
1000// unsigned long offset, unsigned long set, unsigned long *value);
1001
1002
1003/* Routines from init.c/init301.c */
1004extern void InitTo330Pointer(UCHAR,PVB_DEVICE_INFO pVBInfo);
1005extern BOOLEAN XGIInitNew(PXGI_HW_DEVICE_INFO HwDeviceExtension);
1006extern BOOLEAN XGISetModeNew(PXGI_HW_DEVICE_INFO HwDeviceExtension, USHORT ModeNo);
1007//extern void XGI_SetEnableDstn(VB_DEVICE_INFO *XGI_Pr);
1008extern void XGI_LongWait(VB_DEVICE_INFO *XGI_Pr);
1009extern USHORT XGI_GetRatePtrCRT2( PXGI_HW_DEVICE_INFO pXGIHWDE, USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo );
1010/* TW: Chrontel TV functions */
1011extern USHORT XGI_GetCH700x(VB_DEVICE_INFO *XGI_Pr, USHORT tempbx);
1012extern void XGI_SetCH700x(VB_DEVICE_INFO *XGI_Pr, USHORT tempbx);
1013extern USHORT XGI_GetCH701x(VB_DEVICE_INFO *XGI_Pr, USHORT tempbx);
1014extern void XGI_SetCH701x(VB_DEVICE_INFO *XGI_Pr, USHORT tempbx);
1015extern void XGI_SetCH70xxANDOR(VB_DEVICE_INFO *XGI_Pr, USHORT tempax,USHORT tempbh);
1016extern void XGI_DDC2Delay(VB_DEVICE_INFO *XGI_Pr, USHORT delaytime);
1017
1018/* TW: Sensing routines */
1019void XGI_Sense30x(void);
1020int XGIDoSense(int tempbl, int tempbh, int tempcl, int tempch);
1021
1022extern XGI21_LVDSCapStruct XGI21_LCDCapList[13];
1023#endif
diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c
new file mode 100644
index 000000000000..867012b48a01
--- /dev/null
+++ b/drivers/staging/xgifb/XGI_main_26.c
@@ -0,0 +1,3773 @@
1/*
2 * XG20, XG21, XG40, XG42 frame buffer device
3 * for Linux kernels 2.5.x, 2.6.x
4 * Base on TW's sis fbdev code.
5 */
6
7//#include <linux/config.h>
8#include <linux/version.h>
9#include <linux/module.h>
10#include <linux/moduleparam.h>
11#include <linux/kernel.h>
12#include <linux/spinlock.h>
13#include <linux/errno.h>
14#include <linux/string.h>
15#include <linux/mm.h>
16#include <linux/tty.h>
17#include <linux/slab.h>
18#include <linux/delay.h>
19#include <linux/fb.h>
20#include <linux/console.h>
21#include <linux/selection.h>
22#include <linux/ioport.h>
23#include <linux/init.h>
24#include <linux/pci.h>
25#include <linux/vmalloc.h>
26#include <linux/vt_kern.h>
27#include <linux/capability.h>
28#include <linux/fs.h>
29#include <linux/types.h>
30#include <linux/proc_fs.h>
31#include <linux/kernel.h>
32
33#include "osdef.h"
34
35
36#ifndef XGIFB_PAN
37#define XGIFB_PAN
38#endif
39
40#include <asm/io.h>
41#ifdef CONFIG_MTRR
42#include <asm/mtrr.h>
43#endif
44
45#include "XGIfb.h"
46#include "vgatypes.h"
47#include "XGI_main.h"
48#include "vb_util.h"
49
50
51#define Index_CR_GPIO_Reg1 0x48
52#define Index_CR_GPIO_Reg2 0x49
53#define Index_CR_GPIO_Reg3 0x4a
54
55#define GPIOG_EN (1<<6)
56#define GPIOG_WRITE (1<<6)
57#define GPIOG_READ (1<<1)
58int XGIfb_GetXG21DefaultLVDSModeIdx(void);
59
60/* -------------------- Macro definitions ---------------------------- */
61
62#undef XGIFBDEBUG
63
64#ifdef XGIFBDEBUG
65#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
66#else
67#define DPRINTK(fmt, args...)
68#endif
69
70#ifdef XGIFBDEBUG
71static void dumpVGAReg(void)
72{
73 u8 i,reg;
74
75outXGIIDXREG(XGISR, 0x05, 0x86);
76/*
77outXGIIDXREG(XGISR, 0x08, 0x4f);
78outXGIIDXREG(XGISR, 0x0f, 0x20);
79outXGIIDXREG(XGISR, 0x11, 0x4f);
80outXGIIDXREG(XGISR, 0x13, 0x45);
81outXGIIDXREG(XGISR, 0x14, 0x51);
82outXGIIDXREG(XGISR, 0x1e, 0x41);
83outXGIIDXREG(XGISR, 0x1f, 0x0);
84outXGIIDXREG(XGISR, 0x20, 0xa1);
85outXGIIDXREG(XGISR, 0x22, 0xfb);
86outXGIIDXREG(XGISR, 0x26, 0x22);
87outXGIIDXREG(XGISR, 0x3e, 0x07);
88*/
89
90//outXGIIDXREG(XGICR, 0x19, 0x00);
91//outXGIIDXREG(XGICR, 0x1a, 0x3C);
92//outXGIIDXREG(XGICR, 0x22, 0xff);
93//outXGIIDXREG(XGICR, 0x3D, 0x10);
94
95//outXGIIDXREG(XGICR, 0x4a, 0xf3);
96
97//outXGIIDXREG(XGICR, 0x57, 0x0);
98//outXGIIDXREG(XGICR, 0x7a, 0x2c);
99
100//outXGIIDXREG(XGICR, 0x82, 0xcc);
101//outXGIIDXREG(XGICR, 0x8c, 0x0);
102/*
103outXGIIDXREG(XGICR, 0x99, 0x1);
104outXGIIDXREG(XGICR, 0x41, 0x40);
105*/
106
107 for(i=0; i < 0x4f; i++)
108 {
109 inXGIIDXREG(XGISR, i, reg);
110 printk("\no 3c4 %x",i);
111 printk("\ni 3c5 => %x",reg);
112 }
113
114 for(i=0; i < 0xF0; i++)
115 {
116 inXGIIDXREG(XGICR, i, reg);
117 printk("\no 3d4 %x",i);
118 printk("\ni 3d5 => %x",reg);
119 }
120/*
121
122 outXGIIDXREG(XGIPART1,0x2F,1);
123 for(i=1; i < 0x50; i++)
124 {
125 inXGIIDXREG(XGIPART1, i, reg);
126 printk("\no d004 %x",i);
127 printk("\ni d005 => %x",reg);
128 }
129
130 for(i=0; i < 0x50; i++)
131 {
132 inXGIIDXREG(XGIPART2, i, reg);
133 printk("\no d010 %x",i);
134 printk("\ni d011 => %x",reg);
135 }
136 for(i=0; i < 0x50; i++)
137 {
138 inXGIIDXREG(XGIPART3, i, reg);
139 printk("\no d012 %x",i);
140 printk("\ni d013 => %x",reg);
141 }
142 for(i=0; i < 0x50; i++)
143 {
144 inXGIIDXREG(XGIPART4, i, reg);
145 printk("\no d014 %x",i);
146 printk("\ni d015 => %x",reg);
147 }
148*/
149}
150#else
151static inline void dumpVGAReg(void) {}
152#endif
153
154/* data for XGI components */
155struct video_info xgi_video_info;
156
157
158#if 1
159#define DEBUGPRN(x)
160#else
161#define DEBUGPRN(x) printk(KERN_INFO x "\n");
162#endif
163
164
165/* --------------- Hardware Access Routines -------------------------- */
166
167#ifdef LINUX_KERNEL
168int
169XGIfb_mode_rate_to_dclock(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwDeviceExtension,
170 unsigned char modeno, unsigned char rateindex)
171{
172 USHORT ModeNo = modeno;
173 USHORT ModeIdIndex = 0, ClockIndex = 0;
174 USHORT RefreshRateTableIndex = 0;
175
176 /*ULONG temp = 0;*/
177 int Clock;
178 XGI_Pr->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
179 InitTo330Pointer( HwDeviceExtension->jChipType, XGI_Pr ) ;
180
181 RefreshRateTableIndex = XGI_GetRatePtrCRT2( HwDeviceExtension, ModeNo , ModeIdIndex, XGI_Pr ) ;
182
183/*
184 temp = XGI_SearchModeID( ModeNo , &ModeIdIndex, XGI_Pr ) ;
185 if(!temp) {
186 printk(KERN_ERR "Could not find mode %x\n", ModeNo);
187 return 65000;
188 }
189
190 RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
191 RefreshRateTableIndex += (rateindex - 1);
192
193*/
194 ClockIndex = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
195 if(HwDeviceExtension->jChipType < XGI_315H) {
196 ClockIndex &= 0x3F;
197 }
198 Clock = XGI_Pr->VCLKData[ClockIndex].CLOCK * 1000 ;
199
200 return(Clock);
201}
202
203int
204XGIfb_mode_rate_to_ddata(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwDeviceExtension,
205 unsigned char modeno, unsigned char rateindex,
206 u32 *left_margin, u32 *right_margin,
207 u32 *upper_margin, u32 *lower_margin,
208 u32 *hsync_len, u32 *vsync_len,
209 u32 *sync, u32 *vmode)
210{
211 USHORT ModeNo = modeno;
212 USHORT ModeIdIndex = 0, index = 0;
213 USHORT RefreshRateTableIndex = 0;
214
215 unsigned short VRE, VBE, VRS, VBS, VDE, VT;
216 unsigned short HRE, HBE, HRS, HBS, HDE, HT;
217 unsigned char sr_data, cr_data, cr_data2;
218 unsigned long cr_data3;
219 int A, B, C, D, E, F, temp, j;
220 XGI_Pr->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
221 InitTo330Pointer( HwDeviceExtension->jChipType, XGI_Pr ) ;
222 RefreshRateTableIndex = XGI_GetRatePtrCRT2( HwDeviceExtension, ModeNo , ModeIdIndex, XGI_Pr ) ;
223/*
224 temp = XGI_SearchModeID( ModeNo, &ModeIdIndex, XGI_Pr);
225 if(!temp) return 0;
226
227 RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
228 RefreshRateTableIndex += (rateindex - 1);
229*/
230 index = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
231
232 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[5];
233
234 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[0];
235
236 /* Horizontal total */
237 HT = (cr_data & 0xff) |
238 ((unsigned short) (sr_data & 0x03) << 8);
239 A = HT + 5;
240
241 /*cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
242
243 Horizontal display enable end
244 HDE = (cr_data & 0xff) |
245 ((unsigned short) (sr_data & 0x0C) << 6);*/
246 HDE = (XGI_Pr->RefIndex[RefreshRateTableIndex].XRes >> 3) -1;
247 E = HDE + 1;
248
249 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[3];
250
251 /* Horizontal retrace (=sync) start */
252 HRS = (cr_data & 0xff) |
253 ((unsigned short) (sr_data & 0xC0) << 2);
254 F = HRS - E - 3;
255
256 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
257
258 /* Horizontal blank start */
259 HBS = (cr_data & 0xff) |
260 ((unsigned short) (sr_data & 0x30) << 4);
261
262 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[6];
263
264 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[2];
265
266 cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[4];
267
268 /* Horizontal blank end */
269 HBE = (cr_data & 0x1f) |
270 ((unsigned short) (cr_data2 & 0x80) >> 2) |
271 ((unsigned short) (sr_data & 0x03) << 6);
272
273 /* Horizontal retrace (=sync) end */
274 HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
275
276 temp = HBE - ((E - 1) & 255);
277 B = (temp > 0) ? temp : (temp + 256);
278
279 temp = HRE - ((E + F + 3) & 63);
280 C = (temp > 0) ? temp : (temp + 64);
281
282 D = B - F - C;
283
284 *left_margin = D * 8;
285 *right_margin = F * 8;
286 *hsync_len = C * 8;
287
288 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[14];
289
290 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[8];
291
292 cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[9];
293
294 /* Vertical total */
295 VT = (cr_data & 0xFF) |
296 ((unsigned short) (cr_data2 & 0x01) << 8) |
297 ((unsigned short)(cr_data2 & 0x20) << 4) |
298 ((unsigned short) (sr_data & 0x01) << 10);
299 A = VT + 2;
300
301 //cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10];
302
303 /* Vertical display enable end */
304/* VDE = (cr_data & 0xff) |
305 ((unsigned short) (cr_data2 & 0x02) << 7) |
306 ((unsigned short) (cr_data2 & 0x40) << 3) |
307 ((unsigned short) (sr_data & 0x02) << 9); */
308 VDE = XGI_Pr->RefIndex[RefreshRateTableIndex].YRes -1;
309 E = VDE + 1;
310
311 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10];
312
313 /* Vertical retrace (=sync) start */
314 VRS = (cr_data & 0xff) |
315 ((unsigned short) (cr_data2 & 0x04) << 6) |
316 ((unsigned short) (cr_data2 & 0x80) << 2) |
317 ((unsigned short) (sr_data & 0x08) << 7);
318 F = VRS + 1 - E;
319
320 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[12];
321
322 cr_data3 = (XGI_Pr->XGINEWUB_CRT1Table[index].CR[14] & 0x80) << 5;
323
324 /* Vertical blank start */
325 VBS = (cr_data & 0xff) |
326 ((unsigned short) (cr_data2 & 0x08) << 5) |
327 ((unsigned short) (cr_data3 & 0x20) << 4) |
328 ((unsigned short) (sr_data & 0x04) << 8);
329
330 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[13];
331
332 /* Vertical blank end */
333 VBE = (cr_data & 0xff) |
334 ((unsigned short) (sr_data & 0x10) << 4);
335 temp = VBE - ((E - 1) & 511);
336 B = (temp > 0) ? temp : (temp + 512);
337
338 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[11];
339
340 /* Vertical retrace (=sync) end */
341 VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);
342 temp = VRE - ((E + F - 1) & 31);
343 C = (temp > 0) ? temp : (temp + 32);
344
345 D = B - F - C;
346
347 *upper_margin = D;
348 *lower_margin = F;
349 *vsync_len = C;
350
351 if(XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x8000)
352 *sync &= ~FB_SYNC_VERT_HIGH_ACT;
353 else
354 *sync |= FB_SYNC_VERT_HIGH_ACT;
355
356 if(XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x4000)
357 *sync &= ~FB_SYNC_HOR_HIGH_ACT;
358 else
359 *sync |= FB_SYNC_HOR_HIGH_ACT;
360
361 *vmode = FB_VMODE_NONINTERLACED;
362 if(XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x0080)
363 *vmode = FB_VMODE_INTERLACED;
364 else {
365 j = 0;
366 while(XGI_Pr->EModeIDTable[j].Ext_ModeID != 0xff) {
367 if(XGI_Pr->EModeIDTable[j].Ext_ModeID ==
368 XGI_Pr->RefIndex[RefreshRateTableIndex].ModeID) {
369 if(XGI_Pr->EModeIDTable[j].Ext_ModeFlag & DoubleScanMode) {
370 *vmode = FB_VMODE_DOUBLE;
371 }
372 break;
373 }
374 j++;
375 }
376 }
377
378#if 0 /* That's bullshit, only the resolution needs to be shifted */
379 if((*vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
380 *upper_margin <<= 1;
381 *lower_margin <<= 1;
382 *vsync_len <<= 1;
383 } else if((*vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
384 *upper_margin >>= 1;
385 *lower_margin >>= 1;
386 *vsync_len >>= 1;
387 }
388#endif
389
390 return 1;
391}
392
393#endif
394
395
396
397void XGIRegInit(VB_DEVICE_INFO *XGI_Pr, ULONG BaseAddr)
398{
399 XGI_Pr->RelIO = BaseAddr;
400 XGI_Pr->P3c4 = BaseAddr + 0x14;
401 XGI_Pr->P3d4 = BaseAddr + 0x24;
402 XGI_Pr->P3c0 = BaseAddr + 0x10;
403 XGI_Pr->P3ce = BaseAddr + 0x1e;
404 XGI_Pr->P3c2 = BaseAddr + 0x12;
405 XGI_Pr->P3ca = BaseAddr + 0x1a;
406 XGI_Pr->P3c6 = BaseAddr + 0x16;
407 XGI_Pr->P3c7 = BaseAddr + 0x17;
408 XGI_Pr->P3c8 = BaseAddr + 0x18;
409 XGI_Pr->P3c9 = BaseAddr + 0x19;
410 XGI_Pr->P3da = BaseAddr + 0x2A;
411 XGI_Pr->Part1Port = BaseAddr + XGI_CRT2_PORT_04; /* Digital video interface registers (LCD) */
412 XGI_Pr->Part2Port = BaseAddr + XGI_CRT2_PORT_10; /* 301 TV Encoder registers */
413 XGI_Pr->Part3Port = BaseAddr + XGI_CRT2_PORT_12; /* 301 Macrovision registers */
414 XGI_Pr->Part4Port = BaseAddr + XGI_CRT2_PORT_14; /* 301 VGA2 (and LCD) registers */
415 XGI_Pr->Part5Port = BaseAddr + XGI_CRT2_PORT_14+2; /* 301 palette address port registers */
416
417}
418
419
420void XGIfb_set_reg4(u16 port, unsigned long data)
421{
422 outl((u32) (data & 0xffffffff), port);
423}
424
425u32 XGIfb_get_reg3(u16 port)
426{
427 u32 data;
428
429 data = inl(port);
430 return (data);
431}
432
433/* ------------ Interface for init & mode switching code ------------- */
434
435BOOLEAN
436XGIfb_query_VGA_config_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
437 unsigned long offset, unsigned long set, unsigned long *value)
438{
439 static struct pci_dev *pdev = NULL;
440 static unsigned char init = 0, valid_pdev = 0;
441
442 if (!set)
443 DPRINTK("XGIfb: Get VGA offset 0x%lx\n", offset);
444 else
445 DPRINTK("XGIfb: Set offset 0x%lx to 0x%lx\n", offset, *value);
446
447 if (!init) {
448 init = TRUE;
449 pdev = pci_get_device(PCI_VENDOR_ID_XG, xgi_video_info.chip_id, pdev);
450 if (pdev) {
451 valid_pdev = TRUE;
452 pci_dev_put(pdev);
453 }
454 }
455
456 if (!valid_pdev) {
457 printk(KERN_DEBUG "XGIfb: Can't find XGI %d VGA device.\n",
458 xgi_video_info.chip_id);
459 return FALSE;
460 }
461
462 if (set == 0)
463 pci_read_config_dword(pdev, offset, (u32 *)value);
464 else
465 pci_write_config_dword(pdev, offset, (u32)(*value));
466
467 return TRUE;
468}
469
470/*BOOLEAN XGIfb_query_north_bridge_space(PXGI_HW_DEVICE_INFO pXGIhw_ext,
471 unsigned long offset, unsigned long set, unsigned long *value)
472{
473 static struct pci_dev *pdev = NULL;
474 static unsigned char init = 0, valid_pdev = 0;
475 u16 nbridge_id = 0;
476
477 if (!init) {
478 init = TRUE;
479 switch (xgi_video_info.chip) {
480 case XGI_540:
481 nbridge_id = PCI_DEVICE_ID_XG_540;
482 break;
483 case XGI_630:
484 nbridge_id = PCI_DEVICE_ID_XG_630;
485 break;
486 case XGI_730:
487 nbridge_id = PCI_DEVICE_ID_XG_730;
488 break;
489 case XGI_550:
490 nbridge_id = PCI_DEVICE_ID_XG_550;
491 break;
492 case XGI_650:
493 nbridge_id = PCI_DEVICE_ID_XG_650;
494 break;
495 case XGI_740:
496 nbridge_id = PCI_DEVICE_ID_XG_740;
497 break;
498 default:
499 nbridge_id = 0;
500 break;
501 }
502
503 pdev = pci_find_device(PCI_VENDOR_ID_SI, nbridge_id, pdev);
504 if (pdev)
505 valid_pdev = TRUE;
506 }
507
508 if (!valid_pdev) {
509 printk(KERN_DEBUG "XGIfb: Can't find XGI %d North Bridge device.\n",
510 nbridge_id);
511 return FALSE;
512 }
513
514 if (set == 0)
515 pci_read_config_dword(pdev, offset, (u32 *)value);
516 else
517 pci_write_config_dword(pdev, offset, (u32)(*value));
518
519 return TRUE;
520}
521*/
522/* ------------------ Internal helper routines ----------------- */
523
524static void XGIfb_search_mode(const char *name)
525{
526 int i = 0, j = 0, l;
527
528 if(name == NULL) {
529 printk(KERN_ERR "XGIfb: Internal error, using default mode.\n");
530 xgifb_mode_idx = DEFAULT_MODE;
531 if ((xgi_video_info.chip == XG21) && ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD))
532 {
533 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
534 }
535 return;
536 }
537
538
539 if (!strcmp(name, XGIbios_mode[MODE_INDEX_NONE].name)) {
540 printk(KERN_ERR "XGIfb: Mode 'none' not supported anymore. Using default.\n");
541 xgifb_mode_idx = DEFAULT_MODE;
542 if ((xgi_video_info.chip == XG21) && ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD))
543 {
544 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
545 }
546 return;
547 }
548
549 while(XGIbios_mode[i].mode_no != 0) {
550 l = min(strlen(name), strlen(XGIbios_mode[i].name));
551 if (!strncmp(name, XGIbios_mode[i].name, l)) {
552 xgifb_mode_idx = i;
553 j = 1;
554 break;
555 }
556 i++;
557 }
558 if(!j) printk(KERN_INFO "XGIfb: Invalid mode '%s'\n", name);
559}
560
561static void XGIfb_search_vesamode(unsigned int vesamode)
562{
563 int i = 0, j = 0;
564
565 if(vesamode == 0) {
566
567 printk(KERN_ERR "XGIfb: Mode 'none' not supported anymore. Using default.\n");
568 xgifb_mode_idx = DEFAULT_MODE;
569 if ((xgi_video_info.chip == XG21) && ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD))
570 {
571 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
572 }
573 return;
574 }
575
576 vesamode &= 0x1dff; /* Clean VESA mode number from other flags */
577
578 while(XGIbios_mode[i].mode_no != 0) {
579 if( (XGIbios_mode[i].vesa_mode_no_1 == vesamode) ||
580 (XGIbios_mode[i].vesa_mode_no_2 == vesamode) ) {
581 xgifb_mode_idx = i;
582 j = 1;
583 break;
584 }
585 i++;
586 }
587 if(!j) printk(KERN_INFO "XGIfb: Invalid VESA mode 0x%x'\n", vesamode);
588}
589
590int XGIfb_GetXG21LVDSData(void)
591{
592 u8 tmp;
593 unsigned char *pData;
594 int i,j,k;
595
596 inXGIIDXREG(XGISR,0x1e,tmp);
597 outXGIIDXREG(XGISR, 0x1e, tmp|4);
598
599 pData = xgi_video_info.mmio_vbase+0x20000;
600 if ((pData[0x0]==0x55) && (pData[0x1]==0xAA) && (pData[0x65] & 0x1))
601 {
602 i = pData[ 0x316 ] | ( pData[ 0x317 ] << 8 );
603 j = pData[ i-1 ] ;
604 if ( j == 0xff )
605 {
606 j = 1;
607 }
608 k = 0;
609 do
610 {
611 XGI21_LCDCapList[k].LVDS_Capability = pData[ i ] | ( pData[ i + 1 ] << 8 );
612 XGI21_LCDCapList[k].LVDSHT = pData[ i + 2 ] | ( pData[ i + 3 ] << 8 ) ;
613 XGI21_LCDCapList[k].LVDSVT = pData[ i + 4 ] | ( pData[ i + 5 ] << 8 );
614 XGI21_LCDCapList[k].LVDSHDE = pData[ i + 6 ] | ( pData[ i + 7 ] << 8 );
615 XGI21_LCDCapList[k].LVDSVDE = pData[ i + 8 ] | ( pData[ i + 9 ] << 8 );
616 XGI21_LCDCapList[k].LVDSHFP = pData[ i + 10 ] | ( pData[ i + 11 ] << 8 );
617 XGI21_LCDCapList[k].LVDSVFP = pData[ i + 12 ] | ( pData[ i + 13 ] << 8 );
618 XGI21_LCDCapList[k].LVDSHSYNC = pData[ i + 14 ] | ( pData[ i + 15 ] << 8 );
619 XGI21_LCDCapList[k].LVDSVSYNC = pData[ i + 16 ] | ( pData[ i + 17 ] << 8 );
620 XGI21_LCDCapList[k].VCLKData1 = pData[ i + 18 ] ;
621 XGI21_LCDCapList[k].VCLKData2 = pData[ i + 19 ] ;
622 XGI21_LCDCapList[k].PSC_S1 = pData[ i + 20 ] ;
623 XGI21_LCDCapList[k].PSC_S2 = pData[ i + 21 ] ;
624 XGI21_LCDCapList[k].PSC_S3 = pData[ i + 22 ] ;
625 XGI21_LCDCapList[k].PSC_S4 = pData[ i + 23 ] ;
626 XGI21_LCDCapList[k].PSC_S5 = pData[ i + 24 ] ;
627 i += 25;
628 j--;
629 k++;
630 } while ( (j>0) && ( k < (sizeof(XGI21_LCDCapList)/sizeof(XGI21_LVDSCapStruct)) ) );
631 return 1;
632 }
633 return 0;
634}
635
636int XGIfb_GetXG21DefaultLVDSModeIdx(void)
637{
638
639 int found_mode = 0;
640 int XGIfb_mode_idx = 0;
641
642 found_mode = 0;
643 while( (XGIbios_mode[XGIfb_mode_idx].mode_no != 0) &&
644 (XGIbios_mode[XGIfb_mode_idx].xres <= XGI21_LCDCapList[0].LVDSHDE) )
645 {
646 if( (XGIbios_mode[XGIfb_mode_idx].xres == XGI21_LCDCapList[0].LVDSHDE) &&
647 (XGIbios_mode[XGIfb_mode_idx].yres == XGI21_LCDCapList[0].LVDSVDE) &&
648 (XGIbios_mode[XGIfb_mode_idx].bpp == 8))
649 {
650 XGIfb_mode_no = XGIbios_mode[XGIfb_mode_idx].mode_no;
651 found_mode = 1;
652 break;
653 }
654 XGIfb_mode_idx++;
655 }
656 if (!found_mode)
657 XGIfb_mode_idx = 0;
658
659 return (XGIfb_mode_idx);
660}
661
662
663static int XGIfb_validate_mode(int myindex)
664{
665 u16 xres, yres;
666
667 if (xgi_video_info.chip == XG21)
668 {
669 if ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD)
670 {
671 xres = XGI21_LCDCapList[0].LVDSHDE;
672 yres = XGI21_LCDCapList[0].LVDSVDE;
673 if(XGIbios_mode[myindex].xres > xres)
674 return(-1);
675 if(XGIbios_mode[myindex].yres > yres)
676 return(-1);
677 if ((XGIbios_mode[myindex].xres < xres) && (XGIbios_mode[myindex].yres < yres) )
678 {
679 if (XGIbios_mode[myindex].bpp > 8)
680 return(-1);
681 }
682
683 }
684 return(myindex);
685
686 }
687
688 /* FIXME: for now, all is valid on XG27 */
689 if (xgi_video_info.chip == XG27)
690 return(myindex);
691
692 if(!(XGIbios_mode[myindex].chipset & MD_XGI315))
693 return(-1);
694
695 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
696 case DISPTYPE_LCD:
697 switch (XGIhw_ext.ulCRT2LCDType) {
698 case LCD_640x480:
699 xres = 640; yres = 480; break;
700 case LCD_800x600:
701 xres = 800; yres = 600; break;
702 case LCD_1024x600:
703 xres = 1024; yres = 600; break;
704 case LCD_1024x768:
705 xres = 1024; yres = 768; break;
706 case LCD_1152x768:
707 xres = 1152; yres = 768; break;
708 case LCD_1280x960:
709 xres = 1280; yres = 960; break;
710 case LCD_1280x768:
711 xres = 1280; yres = 768; break;
712 case LCD_1280x1024:
713 xres = 1280; yres = 1024; break;
714 case LCD_1400x1050:
715 xres = 1400; yres = 1050; break;
716 case LCD_1600x1200:
717 xres = 1600; yres = 1200; break;
718// case LCD_320x480: // TW: FSTN
719// xres = 320; yres = 480; break;
720 default:
721 xres = 0; yres = 0; break;
722 }
723 if(XGIbios_mode[myindex].xres > xres) {
724 return(-1);
725 }
726 if(XGIbios_mode[myindex].yres > yres) {
727 return(-1);
728 }
729 if((XGIhw_ext.ulExternalChip == 0x01) || // LVDS
730 (XGIhw_ext.ulExternalChip == 0x05)) // LVDS+Chrontel
731 {
732 switch (XGIbios_mode[myindex].xres) {
733 case 512:
734 if(XGIbios_mode[myindex].yres != 512) return -1;
735 if(XGIhw_ext.ulCRT2LCDType == LCD_1024x600) return -1;
736 break;
737 case 640:
738 if((XGIbios_mode[myindex].yres != 400) &&
739 (XGIbios_mode[myindex].yres != 480))
740 return -1;
741 break;
742 case 800:
743 if(XGIbios_mode[myindex].yres != 600) return -1;
744 break;
745 case 1024:
746 if((XGIbios_mode[myindex].yres != 600) &&
747 (XGIbios_mode[myindex].yres != 768))
748 return -1;
749 if((XGIbios_mode[myindex].yres == 600) &&
750 (XGIhw_ext.ulCRT2LCDType != LCD_1024x600))
751 return -1;
752 break;
753 case 1152:
754 if((XGIbios_mode[myindex].yres) != 768) return -1;
755 if(XGIhw_ext.ulCRT2LCDType != LCD_1152x768) return -1;
756 break;
757 case 1280:
758 if((XGIbios_mode[myindex].yres != 768) &&
759 (XGIbios_mode[myindex].yres != 1024))
760 return -1;
761 if((XGIbios_mode[myindex].yres == 768) &&
762 (XGIhw_ext.ulCRT2LCDType != LCD_1280x768))
763 return -1;
764 break;
765 case 1400:
766 if(XGIbios_mode[myindex].yres != 1050) return -1;
767 break;
768 case 1600:
769 if(XGIbios_mode[myindex].yres != 1200) return -1;
770 break;
771 default:
772 return -1;
773 }
774 } else {
775 switch (XGIbios_mode[myindex].xres) {
776 case 512:
777 if(XGIbios_mode[myindex].yres != 512) return -1;
778 break;
779 case 640:
780 if((XGIbios_mode[myindex].yres != 400) &&
781 (XGIbios_mode[myindex].yres != 480))
782 return -1;
783 break;
784 case 800:
785 if(XGIbios_mode[myindex].yres != 600) return -1;
786 break;
787 case 1024:
788 if(XGIbios_mode[myindex].yres != 768) return -1;
789 break;
790 case 1280:
791 if((XGIbios_mode[myindex].yres != 960) &&
792 (XGIbios_mode[myindex].yres != 1024))
793 return -1;
794 if(XGIbios_mode[myindex].yres == 960) {
795 if(XGIhw_ext.ulCRT2LCDType == LCD_1400x1050)
796 return -1;
797 }
798 break;
799 case 1400:
800 if(XGIbios_mode[myindex].yres != 1050) return -1;
801 break;
802 case 1600:
803 if(XGIbios_mode[myindex].yres != 1200) return -1;
804 break;
805 default:
806 return -1;
807 }
808 }
809 break;
810 case DISPTYPE_TV:
811 switch (XGIbios_mode[myindex].xres) {
812 case 512:
813 case 640:
814 case 800:
815 break;
816 case 720:
817 if (xgi_video_info.TV_type == TVMODE_NTSC) {
818 if (XGIbios_mode[myindex].yres != 480) {
819 return(-1);
820 }
821 } else if (xgi_video_info.TV_type == TVMODE_PAL) {
822 if (XGIbios_mode[myindex].yres != 576) {
823 return(-1);
824 }
825 }
826 // TW: LVDS/CHRONTEL does not support 720
827 if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL ||
828 xgi_video_info.hasVB == HASVB_CHRONTEL) {
829 return(-1);
830 }
831 break;
832 case 1024:
833 if (xgi_video_info.TV_type == TVMODE_NTSC) {
834 if(XGIbios_mode[myindex].bpp == 32) {
835 return(-1);
836 }
837 }
838 // TW: LVDS/CHRONTEL only supports < 800 (1024 on 650/Ch7019)
839 if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL ||
840 xgi_video_info.hasVB == HASVB_CHRONTEL) {
841 if(xgi_video_info.chip < XGI_315H) {
842 return(-1);
843 }
844 }
845 break;
846 default:
847 return(-1);
848 }
849 break;
850 case DISPTYPE_CRT2:
851 if(XGIbios_mode[myindex].xres > 1280) return -1;
852 break;
853 }
854 return(myindex);
855
856}
857
858static void XGIfb_search_crt2type(const char *name)
859{
860 int i = 0;
861
862 if(name == NULL)
863 return;
864
865 while(XGI_crt2type[i].type_no != -1) {
866 if (!strcmp(name, XGI_crt2type[i].name)) {
867 XGIfb_crt2type = XGI_crt2type[i].type_no;
868 XGIfb_tvplug = XGI_crt2type[i].tvplug_no;
869 break;
870 }
871 i++;
872 }
873 if(XGIfb_crt2type < 0)
874 printk(KERN_INFO "XGIfb: Invalid CRT2 type: %s\n", name);
875}
876
877static void XGIfb_search_queuemode(const char *name)
878{
879 int i = 0;
880
881 if(name == NULL)
882 return;
883
884 while (XGI_queuemode[i].type_no != -1) {
885 if (!strcmp(name, XGI_queuemode[i].name)) {
886 XGIfb_queuemode = XGI_queuemode[i].type_no;
887 break;
888 }
889 i++;
890 }
891 if (XGIfb_queuemode < 0)
892 printk(KERN_INFO "XGIfb: Invalid queuemode type: %s\n", name);
893}
894
895static u8 XGIfb_search_refresh_rate(unsigned int rate)
896{
897 u16 xres, yres;
898 int i = 0;
899
900 xres = XGIbios_mode[xgifb_mode_idx].xres;
901 yres = XGIbios_mode[xgifb_mode_idx].yres;
902
903 XGIfb_rate_idx = 0;
904 while ((XGIfb_vrate[i].idx != 0) && (XGIfb_vrate[i].xres <= xres)) {
905 if ((XGIfb_vrate[i].xres == xres) && (XGIfb_vrate[i].yres == yres)) {
906 if (XGIfb_vrate[i].refresh == rate) {
907 XGIfb_rate_idx = XGIfb_vrate[i].idx;
908 break;
909 } else if (XGIfb_vrate[i].refresh > rate) {
910 if ((XGIfb_vrate[i].refresh - rate) <= 3) {
911 DPRINTK("XGIfb: Adjusting rate from %d up to %d\n",
912 rate, XGIfb_vrate[i].refresh);
913 XGIfb_rate_idx = XGIfb_vrate[i].idx;
914 xgi_video_info.refresh_rate = XGIfb_vrate[i].refresh;
915 } else if (((rate - XGIfb_vrate[i-1].refresh) <= 2)
916 && (XGIfb_vrate[i].idx != 1)) {
917 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
918 rate, XGIfb_vrate[i-1].refresh);
919 XGIfb_rate_idx = XGIfb_vrate[i-1].idx;
920 xgi_video_info.refresh_rate = XGIfb_vrate[i-1].refresh;
921 }
922 break;
923 } else if((rate - XGIfb_vrate[i].refresh) <= 2) {
924 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
925 rate, XGIfb_vrate[i].refresh);
926 XGIfb_rate_idx = XGIfb_vrate[i].idx;
927 break;
928 }
929 }
930 i++;
931 }
932 if (XGIfb_rate_idx > 0) {
933 return XGIfb_rate_idx;
934 } else {
935 printk(KERN_INFO
936 "XGIfb: Unsupported rate %d for %dx%d\n", rate, xres, yres);
937 return 0;
938 }
939}
940
941static void XGIfb_search_tvstd(const char *name)
942{
943 int i = 0;
944
945 if(name == NULL)
946 return;
947
948 while (XGI_tvtype[i].type_no != -1) {
949 if (!strcmp(name, XGI_tvtype[i].name)) {
950 XGIfb_tvmode = XGI_tvtype[i].type_no;
951 break;
952 }
953 i++;
954 }
955}
956
957static BOOLEAN XGIfb_bridgeisslave(void)
958{
959 unsigned char usScratchP1_00;
960
961 if(xgi_video_info.hasVB == HASVB_NONE) return FALSE;
962
963 inXGIIDXREG(XGIPART1,0x00,usScratchP1_00);
964 if( (usScratchP1_00 & 0x50) == 0x10) {
965 return TRUE;
966 } else {
967 return FALSE;
968 }
969}
970
971static BOOLEAN XGIfbcheckvretracecrt1(void)
972{
973 unsigned char temp;
974
975 inXGIIDXREG(XGICR,0x17,temp);
976 if(!(temp & 0x80)) return FALSE;
977
978
979 inXGIIDXREG(XGISR,0x1f,temp);
980 if(temp & 0xc0) return FALSE;
981
982
983 if(inXGIREG(XGIINPSTAT) & 0x08) return TRUE;
984 else return FALSE;
985}
986
987static BOOLEAN XGIfbcheckvretracecrt2(void)
988{
989 unsigned char temp;
990 if(xgi_video_info.hasVB == HASVB_NONE) return FALSE;
991 inXGIIDXREG(XGIPART1, 0x30, temp);
992 if(temp & 0x02) return FALSE;
993 else return TRUE;
994}
995
996static BOOLEAN XGIfb_CheckVBRetrace(void)
997{
998 if(xgi_video_info.disp_state & DISPTYPE_DISP2) {
999 if(XGIfb_bridgeisslave()) {
1000 return(XGIfbcheckvretracecrt1());
1001 } else {
1002 return(XGIfbcheckvretracecrt2());
1003 }
1004 }
1005 return(XGIfbcheckvretracecrt1());
1006}
1007
1008/* ----------- FBDev related routines for all series ----------- */
1009
1010
1011static void XGIfb_bpp_to_var(struct fb_var_screeninfo *var)
1012{
1013 switch(var->bits_per_pixel) {
1014 case 8:
1015 var->red.offset = var->green.offset = var->blue.offset = 0;
1016 var->red.length = var->green.length = var->blue.length = 6;
1017 xgi_video_info.video_cmap_len = 256;
1018 break;
1019 case 16:
1020 var->red.offset = 11;
1021 var->red.length = 5;
1022 var->green.offset = 5;
1023 var->green.length = 6;
1024 var->blue.offset = 0;
1025 var->blue.length = 5;
1026 var->transp.offset = 0;
1027 var->transp.length = 0;
1028 xgi_video_info.video_cmap_len = 16;
1029 break;
1030 case 32:
1031 var->red.offset = 16;
1032 var->red.length = 8;
1033 var->green.offset = 8;
1034 var->green.length = 8;
1035 var->blue.offset = 0;
1036 var->blue.length = 8;
1037 var->transp.offset = 24;
1038 var->transp.length = 8;
1039 xgi_video_info.video_cmap_len = 16;
1040 break;
1041 }
1042}
1043
1044
1045
1046static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
1047 struct fb_info *info)
1048{
1049
1050 unsigned int htotal = var->left_margin + var->xres +
1051 var->right_margin + var->hsync_len;
1052 unsigned int vtotal = var->upper_margin + var->yres +
1053 var->lower_margin + var->vsync_len;
1054#if defined(__powerpc__)
1055 u8 sr_data, cr_data;
1056#endif
1057 unsigned int drate = 0, hrate = 0;
1058 int found_mode = 0;
1059 int old_mode;
1060// unsigned char reg,reg1;
1061
1062 DEBUGPRN("Inside do_set_var");
1063// 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);
1064
1065 info->var.xres_virtual = var->xres_virtual;
1066 info->var.yres_virtual = var->yres_virtual;
1067 info->var.bits_per_pixel = var->bits_per_pixel;
1068
1069 if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
1070 vtotal <<= 1;
1071 else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
1072 vtotal <<= 2;
1073 else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
1074 {
1075// vtotal <<= 1;
1076// var->yres <<= 1;
1077 }
1078
1079 if(!htotal || !vtotal) {
1080 DPRINTK("XGIfb: Invalid 'var' information\n");
1081 return -EINVAL;
1082 }
1083 printk(KERN_DEBUG "XGIfb: var->pixclock=%d, htotal=%d, vtotal=%d\n",
1084 var->pixclock,htotal,vtotal);
1085
1086
1087
1088 if(var->pixclock && htotal && vtotal) {
1089 drate = 1000000000 / var->pixclock;
1090 hrate = (drate * 1000) / htotal;
1091 xgi_video_info.refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1092 } else {
1093 xgi_video_info.refresh_rate = 60;
1094 }
1095
1096 printk(KERN_DEBUG "XGIfb: Change mode to %dx%dx%d-%dHz\n",
1097 var->xres,var->yres,var->bits_per_pixel,xgi_video_info.refresh_rate);
1098
1099 old_mode = xgifb_mode_idx;
1100 xgifb_mode_idx = 0;
1101
1102 while( (XGIbios_mode[xgifb_mode_idx].mode_no != 0) &&
1103 (XGIbios_mode[xgifb_mode_idx].xres <= var->xres) ) {
1104 if( (XGIbios_mode[xgifb_mode_idx].xres == var->xres) &&
1105 (XGIbios_mode[xgifb_mode_idx].yres == var->yres) &&
1106 (XGIbios_mode[xgifb_mode_idx].bpp == var->bits_per_pixel)) {
1107 XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
1108 found_mode = 1;
1109 break;
1110 }
1111 xgifb_mode_idx++;
1112 }
1113
1114 if(found_mode)
1115 xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
1116 else
1117 xgifb_mode_idx = -1;
1118
1119 if(xgifb_mode_idx < 0) {
1120 printk(KERN_ERR "XGIfb: Mode %dx%dx%d not supported\n", var->xres,
1121 var->yres, var->bits_per_pixel);
1122 xgifb_mode_idx = old_mode;
1123 return -EINVAL;
1124 }
1125
1126 if(XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0) {
1127 XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
1128 xgi_video_info.refresh_rate = 60;
1129 }
1130
1131 if(isactive) {
1132
1133
1134 XGIfb_pre_setmode();
1135 if(XGISetModeNew( &XGIhw_ext, XGIfb_mode_no) == 0) {
1136 printk(KERN_ERR "XGIfb: Setting mode[0x%x] failed\n", XGIfb_mode_no);
1137 return -EINVAL;
1138 }
1139 info->fix.line_length = ((info->var.xres_virtual * info->var.bits_per_pixel)>>6);
1140
1141 outXGIIDXREG(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD);
1142
1143 outXGIIDXREG(XGICR,0x13,(info->fix.line_length & 0x00ff));
1144 outXGIIDXREG(XGISR,0x0E,(info->fix.line_length & 0xff00)>>8);
1145
1146 XGIfb_post_setmode();
1147
1148 DPRINTK("XGIfb: Set new mode: %dx%dx%d-%d \n",
1149 XGIbios_mode[xgifb_mode_idx].xres,
1150 XGIbios_mode[xgifb_mode_idx].yres,
1151 XGIbios_mode[xgifb_mode_idx].bpp,
1152 xgi_video_info.refresh_rate);
1153
1154 xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
1155 xgi_video_info.video_vwidth = info->var.xres_virtual;
1156 xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres;
1157 xgi_video_info.video_vheight = info->var.yres_virtual;
1158 xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres;
1159 xgi_video_info.org_x = xgi_video_info.org_y = 0;
1160 xgi_video_info.video_linelength = info->var.xres_virtual * (xgi_video_info.video_bpp >> 3);
1161 xgi_video_info.accel = 0;
1162 if(XGIfb_accel) {
1163 xgi_video_info.accel = (var->accel_flags & FB_ACCELF_TEXT) ? -1 : 0;
1164 }
1165 switch(xgi_video_info.video_bpp)
1166 {
1167 case 8:
1168 xgi_video_info.DstColor = 0x0000;
1169 xgi_video_info.XGI310_AccelDepth = 0x00000000;
1170 xgi_video_info.video_cmap_len = 256;
1171#if defined(__powerpc__)
1172 inXGIIDXREG (XGICR, 0x4D, cr_data);
1173 outXGIIDXREG(XGICR, 0x4D, (cr_data & 0xE0));
1174#endif
1175 break;
1176 case 16:
1177 xgi_video_info.DstColor = 0x8000;
1178 xgi_video_info.XGI310_AccelDepth = 0x00010000;
1179#if defined(__powerpc__)
1180 inXGIIDXREG (XGICR, 0x4D, cr_data);
1181 outXGIIDXREG(XGICR, 0x4D, ((cr_data & 0xE0) | 0x0B));
1182#endif
1183 xgi_video_info.video_cmap_len = 16;
1184 break;
1185 case 32:
1186 xgi_video_info.DstColor = 0xC000;
1187 xgi_video_info.XGI310_AccelDepth = 0x00020000;
1188 xgi_video_info.video_cmap_len = 16;
1189#if defined(__powerpc__)
1190 inXGIIDXREG (XGICR, 0x4D, cr_data);
1191 outXGIIDXREG(XGICR, 0x4D, ((cr_data & 0xE0) | 0x15));
1192#endif
1193 break;
1194 default:
1195 xgi_video_info.video_cmap_len = 16;
1196 printk(KERN_ERR "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp);
1197 xgi_video_info.accel = 0;
1198 break;
1199 }
1200 }
1201 XGIfb_bpp_to_var(var); /*update ARGB info*/
1202 DEBUGPRN("End of do_set_var");
1203
1204 dumpVGAReg();
1205 return 0;
1206}
1207
1208#ifdef XGIFB_PAN
1209static int XGIfb_pan_var(struct fb_var_screeninfo *var)
1210{
1211 unsigned int base;
1212
1213// printk("Inside pan_var");
1214
1215 if (var->xoffset > (var->xres_virtual - var->xres)) {
1216// printk( "Pan: xo: %d xv %d xr %d\n",
1217// var->xoffset, var->xres_virtual, var->xres);
1218 return -EINVAL;
1219 }
1220 if(var->yoffset > (var->yres_virtual - var->yres)) {
1221// printk( "Pan: yo: %d yv %d yr %d\n",
1222// var->yoffset, var->yres_virtual, var->yres);
1223 return -EINVAL;
1224 }
1225 base = var->yoffset * var->xres_virtual + var->xoffset;
1226
1227 /* calculate base bpp dep. */
1228 switch(var->bits_per_pixel) {
1229 case 16:
1230 base >>= 1;
1231 break;
1232 case 32:
1233 break;
1234 case 8:
1235 default:
1236 base >>= 2;
1237 break;
1238 }
1239
1240 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
1241
1242 outXGIIDXREG(XGICR, 0x0D, base & 0xFF);
1243 outXGIIDXREG(XGICR, 0x0C, (base >> 8) & 0xFF);
1244 outXGIIDXREG(XGISR, 0x0D, (base >> 16) & 0xFF);
1245 outXGIIDXREG(XGISR, 0x37, (base >> 24) & 0x03);
1246 setXGIIDXREG(XGISR, 0x37, 0xDF, (base >> 21) & 0x04);
1247
1248 if(xgi_video_info.disp_state & DISPTYPE_DISP2) {
1249 orXGIIDXREG(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
1250 outXGIIDXREG(XGIPART1, 0x06, (base & 0xFF));
1251 outXGIIDXREG(XGIPART1, 0x05, ((base >> 8) & 0xFF));
1252 outXGIIDXREG(XGIPART1, 0x04, ((base >> 16) & 0xFF));
1253 setXGIIDXREG(XGIPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
1254 }
1255// printk("End of pan_var");
1256 return 0;
1257}
1258#endif
1259
1260
1261void XGI_dispinfo(struct ap_data *rec)
1262{
1263 rec->minfo.bpp = xgi_video_info.video_bpp;
1264 rec->minfo.xres = xgi_video_info.video_width;
1265 rec->minfo.yres = xgi_video_info.video_height;
1266 rec->minfo.v_xres = xgi_video_info.video_vwidth;
1267 rec->minfo.v_yres = xgi_video_info.video_vheight;
1268 rec->minfo.org_x = xgi_video_info.org_x;
1269 rec->minfo.org_y = xgi_video_info.org_y;
1270 rec->minfo.vrate = xgi_video_info.refresh_rate;
1271 rec->iobase = xgi_video_info.vga_base - 0x30;
1272 rec->mem_size = xgi_video_info.video_size;
1273 rec->disp_state = xgi_video_info.disp_state;
1274 rec->version = (VER_MAJOR << 24) | (VER_MINOR << 16) | VER_LEVEL;
1275 rec->hasVB = xgi_video_info.hasVB;
1276 rec->TV_type = xgi_video_info.TV_type;
1277 rec->TV_plug = xgi_video_info.TV_plug;
1278 rec->chip = xgi_video_info.chip;
1279}
1280
1281
1282
1283
1284static int XGIfb_open(struct fb_info *info, int user)
1285{
1286 return 0;
1287}
1288
1289static int XGIfb_release(struct fb_info *info, int user)
1290{
1291 return 0;
1292}
1293
1294static int XGIfb_get_cmap_len(const struct fb_var_screeninfo *var)
1295{
1296 int rc = 16;
1297
1298 switch(var->bits_per_pixel) {
1299 case 8:
1300 rc = 256;
1301 break;
1302 case 16:
1303 rc = 16;
1304 break;
1305 case 32:
1306 rc = 16;
1307 break;
1308 }
1309 return rc;
1310}
1311
1312static int XGIfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
1313 unsigned transp, struct fb_info *info)
1314{
1315 if (regno >= XGIfb_get_cmap_len(&info->var))
1316 return 1;
1317
1318 switch (info->var.bits_per_pixel) {
1319 case 8:
1320 outXGIREG(XGIDACA, regno);
1321 outXGIREG(XGIDACD, (red >> 10));
1322 outXGIREG(XGIDACD, (green >> 10));
1323 outXGIREG(XGIDACD, (blue >> 10));
1324 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
1325 outXGIREG(XGIDAC2A, regno);
1326 outXGIREG(XGIDAC2D, (red >> 8));
1327 outXGIREG(XGIDAC2D, (green >> 8));
1328 outXGIREG(XGIDAC2D, (blue >> 8));
1329 }
1330 break;
1331 case 16:
1332 ((u32 *)(info->pseudo_palette))[regno] =
1333 ((red & 0xf800)) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
1334 break;
1335 case 32:
1336 red >>= 8;
1337 green >>= 8;
1338 blue >>= 8;
1339 ((u32 *) (info->pseudo_palette))[regno] =
1340 (red << 16) | (green << 8) | (blue);
1341 break;
1342 }
1343 return 0;
1344}
1345
1346static int XGIfb_set_par(struct fb_info *info)
1347{
1348 int err;
1349
1350// printk("XGIfb: inside set_par\n");
1351 if((err = XGIfb_do_set_var(&info->var, 1, info)))
1352 return err;
1353#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
1354 XGIfb_get_fix(&info->fix, info->currcon, info);
1355#else
1356 XGIfb_get_fix(&info->fix, -1, info);
1357#endif
1358// printk("XGIfb:end of set_par\n");
1359 return 0;
1360}
1361
1362static int XGIfb_check_var(struct fb_var_screeninfo *var,
1363 struct fb_info *info)
1364{
1365 unsigned int htotal =
1366 var->left_margin + var->xres + var->right_margin +
1367 var->hsync_len;
1368 unsigned int vtotal = 0;
1369 unsigned int drate = 0, hrate = 0;
1370 int found_mode = 0;
1371 int refresh_rate, search_idx;
1372
1373 DEBUGPRN("Inside check_var");
1374
1375 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1376 vtotal = var->upper_margin + var->yres + var->lower_margin +
1377 var->vsync_len;
1378 vtotal <<= 1;
1379 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1380 vtotal = var->upper_margin + var->yres + var->lower_margin +
1381 var->vsync_len;
1382 vtotal <<= 2;
1383 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1384 vtotal = var->upper_margin + (var->yres/2) + var->lower_margin +
1385 var->vsync_len;
1386 } else vtotal = var->upper_margin + var->yres + var->lower_margin +
1387 var->vsync_len;
1388
1389 if(!(htotal) || !(vtotal)) {
1390 XGIFAIL("XGIfb: no valid timing data");
1391 }
1392
1393
1394 if(var->pixclock && htotal && vtotal) {
1395 drate = 1000000000 / var->pixclock;
1396 hrate = (drate * 1000) / htotal;
1397 xgi_video_info.refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1398 printk(KERN_DEBUG \
1399 "%s: pixclock = %d ,htotal=%d, vtotal=%d\n" \
1400 "%s: drate=%d, hrate=%d, refresh_rate=%d\n",
1401 __func__,var->pixclock, htotal, vtotal,
1402 __func__, drate, hrate, xgi_video_info.refresh_rate);
1403 } else {
1404 xgi_video_info.refresh_rate = 60;
1405 }
1406
1407/*
1408 if((var->pixclock) && (htotal)) {
1409 drate = 1E12 / var->pixclock;
1410 hrate = drate / htotal;
1411 refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
1412 } else refresh_rate = 60;
1413*/
1414 /* TW: Calculation wrong for 1024x600 - force it to 60Hz */
1415 if((var->xres == 1024) && (var->yres == 600)) refresh_rate = 60;
1416
1417 search_idx = 0;
1418 while((XGIbios_mode[search_idx].mode_no != 0) &&
1419 (XGIbios_mode[search_idx].xres <= var->xres) ) {
1420 if((XGIbios_mode[search_idx].xres == var->xres) &&
1421 (XGIbios_mode[search_idx].yres == var->yres) &&
1422 (XGIbios_mode[search_idx].bpp == var->bits_per_pixel)) {
1423 if(XGIfb_validate_mode(search_idx) > 0) {
1424 found_mode = 1;
1425 break;
1426 }
1427 }
1428 search_idx++;
1429 }
1430
1431 if(!found_mode) {
1432
1433 printk(KERN_ERR "XGIfb: %dx%dx%d is no valid mode\n",
1434 var->xres, var->yres, var->bits_per_pixel);
1435
1436 search_idx = 0;
1437 while(XGIbios_mode[search_idx].mode_no != 0) {
1438
1439 if( (var->xres <= XGIbios_mode[search_idx].xres) &&
1440 (var->yres <= XGIbios_mode[search_idx].yres) &&
1441 (var->bits_per_pixel == XGIbios_mode[search_idx].bpp) ) {
1442 if(XGIfb_validate_mode(search_idx) > 0) {
1443 found_mode = 1;
1444 break;
1445 }
1446 }
1447 search_idx++;
1448 }
1449 if(found_mode) {
1450 var->xres = XGIbios_mode[search_idx].xres;
1451 var->yres = XGIbios_mode[search_idx].yres;
1452 printk(KERN_DEBUG "XGIfb: Adapted to mode %dx%dx%d\n",
1453 var->xres, var->yres, var->bits_per_pixel);
1454
1455 } else {
1456 printk(KERN_ERR "XGIfb: Failed to find similar mode to %dx%dx%d\n",
1457 var->xres, var->yres, var->bits_per_pixel);
1458 return -EINVAL;
1459 }
1460 }
1461
1462 /* TW: TODO: Check the refresh rate */
1463
1464 /* Adapt RGB settings */
1465 XGIfb_bpp_to_var(var);
1466
1467 /* Sanity check for offsets */
1468 if (var->xoffset < 0)
1469 var->xoffset = 0;
1470 if (var->yoffset < 0)
1471 var->yoffset = 0;
1472
1473
1474 if(!XGIfb_ypan) {
1475 if(var->xres != var->xres_virtual)
1476 var->xres_virtual = var->xres;
1477 if(var->yres != var->yres_virtual)
1478 var->yres_virtual = var->yres;
1479 }/* else {
1480 // TW: Now patch yres_virtual if we use panning
1481 // May I do this?
1482 var->yres_virtual = xgi_video_info.heapstart / (var->xres * (var->bits_per_pixel >> 3));
1483 if(var->yres_virtual <= var->yres) {
1484 // TW: Paranoia check
1485 var->yres_virtual = var->yres;
1486 }
1487 }*/
1488
1489 /* Truncate offsets to maximum if too high */
1490 if (var->xoffset > var->xres_virtual - var->xres)
1491 var->xoffset = var->xres_virtual - var->xres - 1;
1492
1493 if (var->yoffset > var->yres_virtual - var->yres)
1494 var->yoffset = var->yres_virtual - var->yres - 1;
1495
1496 /* Set everything else to 0 */
1497 var->red.msb_right =
1498 var->green.msb_right =
1499 var->blue.msb_right =
1500 var->transp.offset = var->transp.length = var->transp.msb_right = 0;
1501
1502 DEBUGPRN("end of check_var");
1503 return 0;
1504}
1505
1506#ifdef XGIFB_PAN
1507static int XGIfb_pan_display( struct fb_var_screeninfo *var,
1508 struct fb_info* info)
1509{
1510 int err;
1511
1512// printk("\nInside pan_display:");
1513
1514 if (var->xoffset > (var->xres_virtual - var->xres))
1515 return -EINVAL;
1516 if (var->yoffset > (var->yres_virtual - var->yres))
1517 return -EINVAL;
1518
1519 if (var->vmode & FB_VMODE_YWRAP) {
1520 if (var->yoffset < 0
1521 || var->yoffset >= info->var.yres_virtual
1522 || var->xoffset) return -EINVAL;
1523 } else {
1524 if (var->xoffset + info->var.xres > info->var.xres_virtual ||
1525 var->yoffset + info->var.yres > info->var.yres_virtual)
1526 return -EINVAL;
1527 }
1528
1529 if((err = XGIfb_pan_var(var)) < 0) return err;
1530
1531 info->var.xoffset = var->xoffset;
1532 info->var.yoffset = var->yoffset;
1533 if (var->vmode & FB_VMODE_YWRAP)
1534 info->var.vmode |= FB_VMODE_YWRAP;
1535 else
1536 info->var.vmode &= ~FB_VMODE_YWRAP;
1537
1538// printk(" End of pan_display");
1539 return 0;
1540}
1541#endif
1542
1543#if 0
1544static int XGIfb_mmap(struct fb_info *info, struct file *file,
1545 struct vm_area_struct *vma)
1546{
1547 unsigned long start;
1548 unsigned long off;
1549 u32 len, mmio_off;
1550
1551 DEBUGPRN("inside mmap");
1552 if(vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) return -EINVAL;
1553
1554 off = vma->vm_pgoff << PAGE_SHIFT;
1555
1556 start = (unsigned long) xgi_video_info.video_base;
1557 len = PAGE_ALIGN((start & ~PAGE_MASK) + xgi_video_info.video_size);
1558 start &= PAGE_MASK;
1559#if 0
1560 if (off >= len) {
1561 off -= len;
1562#endif
1563 /* By Jake Page: Treat mmap request with offset beyond heapstart
1564 * as request for mapping the mmio area
1565 */
1566 #if 1
1567 mmio_off = PAGE_ALIGN((start & ~PAGE_MASK) + xgi_video_info.heapstart);
1568 if(off >= mmio_off) {
1569 off -= mmio_off;
1570 if(info->var.accel_flags) return -EINVAL;
1571
1572 start = (unsigned long) xgi_video_info.mmio_base;
1573 len = PAGE_ALIGN((start & ~PAGE_MASK) + XGIfb_mmio_size);
1574 }
1575 start &= PAGE_MASK;
1576 #endif
1577 if((vma->vm_end - vma->vm_start + off) > len) return -EINVAL;
1578
1579 off += start;
1580 vma->vm_pgoff = off >> PAGE_SHIFT;
1581 vma->vm_flags |= VM_IO; /* by Jake Page; is that really needed? */
1582
1583#if defined(__i386__) || defined(__x86_64__)
1584 if (boot_cpu_data.x86 > 3)
1585 pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
1586#endif
1587 if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, vma->vm_end - vma->vm_start,
1588 vma->vm_page_prot))
1589 return -EAGAIN;
1590
1591 DEBUGPRN("end of mmap");
1592 return 0;
1593}
1594#endif
1595static int XGIfb_blank(int blank, struct fb_info *info)
1596{
1597 u8 reg;
1598
1599 inXGIIDXREG(XGICR, 0x17, reg);
1600
1601 if(blank > 0)
1602 reg &= 0x7f;
1603 else
1604 reg |= 0x80;
1605
1606 outXGIIDXREG(XGICR, 0x17, reg);
1607 outXGIIDXREG(XGISR, 0x00, 0x01); /* Synchronous Reset */
1608 outXGIIDXREG(XGISR, 0x00, 0x03); /* End Reset */
1609 return(0);
1610}
1611
1612
1613#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
1614static int XGIfb_ioctl(struct fb_info *info, unsigned int cmd,
1615 unsigned long arg)
1616#else
1617static int XGIfb_ioctl(struct inode *inode, struct file *file,
1618 unsigned int cmd, unsigned long arg,
1619 struct fb_info *info)
1620#endif
1621
1622{
1623 DEBUGPRN("inside ioctl");
1624 switch (cmd) {
1625 case FBIO_ALLOC:
1626 if (!capable(CAP_SYS_RAWIO))
1627 return -EPERM;
1628 XGI_malloc((struct XGI_memreq *) arg);
1629 break;
1630 case FBIO_FREE:
1631 if (!capable(CAP_SYS_RAWIO))
1632 return -EPERM;
1633 XGI_free(*(unsigned long *) arg);
1634 break;
1635 case FBIOGET_HWCINFO:
1636 {
1637 unsigned long *hwc_offset = (unsigned long *) arg;
1638
1639 if (XGIfb_caps & HW_CURSOR_CAP)
1640 *hwc_offset = XGIfb_hwcursor_vbase -
1641 (unsigned long) xgi_video_info.video_vbase;
1642 else
1643 *hwc_offset = 0;
1644
1645 break;
1646 }
1647 case FBIOPUT_MODEINFO:
1648 {
1649 struct mode_info *x = (struct mode_info *)arg;
1650
1651 xgi_video_info.video_bpp = x->bpp;
1652 xgi_video_info.video_width = x->xres;
1653 xgi_video_info.video_height = x->yres;
1654 xgi_video_info.video_vwidth = x->v_xres;
1655 xgi_video_info.video_vheight = x->v_yres;
1656 xgi_video_info.org_x = x->org_x;
1657 xgi_video_info.org_y = x->org_y;
1658 xgi_video_info.refresh_rate = x->vrate;
1659 xgi_video_info.video_linelength = xgi_video_info.video_vwidth * (xgi_video_info.video_bpp >> 3);
1660 switch(xgi_video_info.video_bpp) {
1661 case 8:
1662 xgi_video_info.DstColor = 0x0000;
1663 xgi_video_info.XGI310_AccelDepth = 0x00000000;
1664 xgi_video_info.video_cmap_len = 256;
1665 break;
1666 case 16:
1667 xgi_video_info.DstColor = 0x8000;
1668 xgi_video_info.XGI310_AccelDepth = 0x00010000;
1669 xgi_video_info.video_cmap_len = 16;
1670 break;
1671 case 32:
1672 xgi_video_info.DstColor = 0xC000;
1673 xgi_video_info.XGI310_AccelDepth = 0x00020000;
1674 xgi_video_info.video_cmap_len = 16;
1675 break;
1676 default:
1677 xgi_video_info.video_cmap_len = 16;
1678 printk(KERN_ERR "XGIfb: Unsupported accel depth %d", xgi_video_info.video_bpp);
1679 xgi_video_info.accel = 0;
1680 break;
1681 }
1682
1683 break;
1684 }
1685 case FBIOGET_DISPINFO:
1686 XGI_dispinfo((struct ap_data *)arg);
1687 break;
1688 case XGIFB_GET_INFO: /* TW: New for communication with X driver */
1689 {
1690 XGIfb_info *x = (XGIfb_info *)arg;
1691
1692 //x->XGIfb_id = XGIFB_ID;
1693 x->XGIfb_version = VER_MAJOR;
1694 x->XGIfb_revision = VER_MINOR;
1695 x->XGIfb_patchlevel = VER_LEVEL;
1696 x->chip_id = xgi_video_info.chip_id;
1697 x->memory = xgi_video_info.video_size / 1024;
1698 x->heapstart = xgi_video_info.heapstart / 1024;
1699 x->fbvidmode = XGIfb_mode_no;
1700 x->XGIfb_caps = XGIfb_caps;
1701 x->XGIfb_tqlen = 512; /* yet unused */
1702 x->XGIfb_pcibus = xgi_video_info.pcibus;
1703 x->XGIfb_pcislot = xgi_video_info.pcislot;
1704 x->XGIfb_pcifunc = xgi_video_info.pcifunc;
1705 x->XGIfb_lcdpdc = XGIfb_detectedpdc;
1706 x->XGIfb_lcda = XGIfb_detectedlcda;
1707 break;
1708 }
1709 case XGIFB_GET_VBRSTATUS:
1710 {
1711 unsigned long *vbrstatus = (unsigned long *) arg;
1712 if(XGIfb_CheckVBRetrace()) *vbrstatus = 1;
1713 else *vbrstatus = 0;
1714 }
1715 default:
1716 return -EINVAL;
1717 }
1718 DEBUGPRN("end of ioctl");
1719 return 0;
1720
1721}
1722
1723
1724
1725/* ----------- FBDev related routines for all series ---------- */
1726
1727static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con,
1728 struct fb_info *info)
1729{
1730 DEBUGPRN("inside get_fix");
1731 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1732
1733 strcpy(fix->id, myid);
1734
1735 fix->smem_start = xgi_video_info.video_base;
1736
1737 fix->smem_len = xgi_video_info.video_size;
1738
1739
1740/* if((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size/1024))) {
1741 if (xgi_video_info.video_size > 0x1000000) {
1742 fix->smem_len = 0xD00000;
1743 } else if (xgi_video_info.video_size > 0x800000)
1744 fix->smem_len = 0x800000;
1745 else
1746 fix->smem_len = 0x400000;
1747 } else
1748 fix->smem_len = XGIfb_mem * 1024;
1749*/
1750 fix->type = video_type;
1751 fix->type_aux = 0;
1752 if(xgi_video_info.video_bpp == 8)
1753 fix->visual = FB_VISUAL_PSEUDOCOLOR;
1754 else
1755 fix->visual = FB_VISUAL_DIRECTCOLOR;
1756 fix->xpanstep = 0;
1757#ifdef XGIFB_PAN
1758 if(XGIfb_ypan) fix->ypanstep = 1;
1759#endif
1760 fix->ywrapstep = 0;
1761 fix->line_length = xgi_video_info.video_linelength;
1762 fix->mmio_start = xgi_video_info.mmio_base;
1763 fix->mmio_len = XGIfb_mmio_size;
1764 if(xgi_video_info.chip >= XG40)
1765 fix->accel = FB_ACCEL_XGI_XABRE;
1766 else
1767 fix->accel = FB_ACCEL_XGI_GLAMOUR_2;
1768
1769
1770 DEBUGPRN("end of get_fix");
1771 return 0;
1772}
1773
1774
1775static struct fb_ops XGIfb_ops = {
1776 .owner = THIS_MODULE,
1777 .fb_open = XGIfb_open,
1778 .fb_release = XGIfb_release,
1779 .fb_check_var = XGIfb_check_var,
1780 .fb_set_par = XGIfb_set_par,
1781 .fb_setcolreg = XGIfb_setcolreg,
1782#ifdef XGIFB_PAN
1783 .fb_pan_display = XGIfb_pan_display,
1784#endif
1785 .fb_blank = XGIfb_blank,
1786 .fb_fillrect = fbcon_XGI_fillrect,
1787 .fb_copyarea = fbcon_XGI_copyarea,
1788 .fb_imageblit = cfb_imageblit,
1789#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
1790 .fb_cursor = soft_cursor,
1791#endif
1792 .fb_sync = fbcon_XGI_sync,
1793 .fb_ioctl = XGIfb_ioctl,
1794// .fb_mmap = XGIfb_mmap,
1795};
1796
1797/* ---------------- Chip generation dependent routines ---------------- */
1798
1799
1800/* for XGI 315/550/650/740/330 */
1801
1802static int XGIfb_get_dram_size(void)
1803{
1804
1805 u8 ChannelNum,tmp;
1806 u8 reg = 0;
1807
1808 /* xorg driver sets 32MB * 1 channel */
1809 if (xgi_video_info.chip == XG27)
1810 outXGIIDXREG(XGISR, IND_XGI_DRAM_SIZE, 0x51);
1811
1812 inXGIIDXREG(XGISR, IND_XGI_DRAM_SIZE, reg);
1813 switch ((reg & XGI_DRAM_SIZE_MASK) >> 4) {
1814 case XGI_DRAM_SIZE_1MB:
1815 xgi_video_info.video_size = 0x100000;
1816 break;
1817 case XGI_DRAM_SIZE_2MB:
1818 xgi_video_info.video_size = 0x200000;
1819 break;
1820 case XGI_DRAM_SIZE_4MB:
1821 xgi_video_info.video_size = 0x400000;
1822 break;
1823 case XGI_DRAM_SIZE_8MB:
1824 xgi_video_info.video_size = 0x800000;
1825 break;
1826 case XGI_DRAM_SIZE_16MB:
1827 xgi_video_info.video_size = 0x1000000;
1828 break;
1829 case XGI_DRAM_SIZE_32MB:
1830 xgi_video_info.video_size = 0x2000000;
1831 break;
1832 case XGI_DRAM_SIZE_64MB:
1833 xgi_video_info.video_size = 0x4000000;
1834 break;
1835 case XGI_DRAM_SIZE_128MB:
1836 xgi_video_info.video_size = 0x8000000;
1837 break;
1838 case XGI_DRAM_SIZE_256MB:
1839 xgi_video_info.video_size = 0x10000000;
1840 break;
1841 default:
1842 return -1;
1843 }
1844
1845 tmp = (reg & 0x0c) >> 2;
1846 switch(xgi_video_info.chip)
1847 {
1848 case XG20:
1849 case XG21:
1850 case XG27:
1851 ChannelNum = 1;
1852 break;
1853
1854 case XG42:
1855 if(reg & 0x04)
1856 ChannelNum = 2;
1857 else
1858 ChannelNum = 1;
1859 break;
1860
1861 case XG45:
1862 if(tmp == 1)
1863 ChannelNum = 2;
1864 else
1865 if(tmp == 2)
1866 ChannelNum = 3;
1867 else
1868 if(tmp == 3)
1869 ChannelNum = 4;
1870 else
1871 ChannelNum = 1;
1872 break;
1873
1874 case XG40:
1875 default:
1876 if(tmp == 2)
1877 ChannelNum = 2;
1878 else
1879 if(tmp == 3)
1880 ChannelNum = 3;
1881 else
1882 ChannelNum = 1;
1883 break;
1884 }
1885
1886
1887 xgi_video_info.video_size = xgi_video_info.video_size * ChannelNum;
1888 //PLiad fixed for benchmarking and fb set
1889 //xgi_video_info.video_size = 0x200000;//1024x768x16
1890 //xgi_video_info.video_size = 0x1000000;//benchmark
1891
1892 printk("XGIfb: SR14=%x DramSzie %x ChannelNum %x\n",reg,xgi_video_info.video_size ,ChannelNum );
1893 return 0;
1894
1895}
1896
1897static void XGIfb_detect_VB(void)
1898{
1899 u8 cr32, temp=0;
1900
1901 xgi_video_info.TV_plug = xgi_video_info.TV_type = 0;
1902
1903 switch(xgi_video_info.hasVB) {
1904 case HASVB_LVDS_CHRONTEL:
1905 case HASVB_CHRONTEL:
1906 break;
1907 case HASVB_301:
1908 case HASVB_302:
1909// XGI_Sense30x(); //Yi-Lin TV Sense?
1910 break;
1911 }
1912
1913 inXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR32, cr32);
1914
1915 if ((cr32 & XGI_CRT1) && !XGIfb_crt1off)
1916 XGIfb_crt1off = 0;
1917 else {
1918 if (cr32 & 0x5F)
1919 XGIfb_crt1off = 1;
1920 else
1921 XGIfb_crt1off = 0;
1922 }
1923
1924 if (XGIfb_crt2type != -1)
1925 /* TW: Override with option */
1926 xgi_video_info.disp_state = XGIfb_crt2type;
1927 else if (cr32 & XGI_VB_TV)
1928 xgi_video_info.disp_state = DISPTYPE_TV;
1929 else if (cr32 & XGI_VB_LCD)
1930 xgi_video_info.disp_state = DISPTYPE_LCD;
1931 else if (cr32 & XGI_VB_CRT2)
1932 xgi_video_info.disp_state = DISPTYPE_CRT2;
1933 else
1934 xgi_video_info.disp_state = 0;
1935
1936 if(XGIfb_tvplug != -1)
1937 /* PR/TW: Override with option */
1938 xgi_video_info.TV_plug = XGIfb_tvplug;
1939 else if (cr32 & XGI_VB_HIVISION) {
1940 xgi_video_info.TV_type = TVMODE_HIVISION;
1941 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
1942 }
1943 else if (cr32 & XGI_VB_SVIDEO)
1944 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
1945 else if (cr32 & XGI_VB_COMPOSITE)
1946 xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
1947 else if (cr32 & XGI_VB_SCART)
1948 xgi_video_info.TV_plug = TVPLUG_SCART;
1949
1950 if(xgi_video_info.TV_type == 0) {
1951 /* TW: PAL/NTSC changed for 650 */
1952 if((xgi_video_info.chip <= XGI_315PRO) || (xgi_video_info.chip >= XGI_330)) {
1953
1954 inXGIIDXREG(XGICR, 0x38, temp);
1955 if(temp & 0x10)
1956 xgi_video_info.TV_type = TVMODE_PAL;
1957 else
1958 xgi_video_info.TV_type = TVMODE_NTSC;
1959
1960 } else {
1961
1962 inXGIIDXREG(XGICR, 0x79, temp);
1963 if(temp & 0x20)
1964 xgi_video_info.TV_type = TVMODE_PAL;
1965 else
1966 xgi_video_info.TV_type = TVMODE_NTSC;
1967 }
1968 }
1969
1970 /* TW: Copy forceCRT1 option to CRT1off if option is given */
1971 if (XGIfb_forcecrt1 != -1) {
1972 if (XGIfb_forcecrt1) XGIfb_crt1off = 0;
1973 else XGIfb_crt1off = 1;
1974 }
1975}
1976
1977static void XGIfb_get_VB_type(void)
1978{
1979 u8 reg;
1980
1981 if (!XGIfb_has_VB()) {
1982 inXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR37, reg);
1983 switch ((reg & XGI_EXTERNAL_CHIP_MASK) >> 1) {
1984 case XGI310_EXTERNAL_CHIP_LVDS:
1985 xgi_video_info.hasVB = HASVB_LVDS;
1986 break;
1987 case XGI310_EXTERNAL_CHIP_LVDS_CHRONTEL:
1988 xgi_video_info.hasVB = HASVB_LVDS_CHRONTEL;
1989 break;
1990 default:
1991 break;
1992 }
1993 }
1994}
1995
1996
1997static int XGIfb_has_VB(void)
1998{
1999 u8 vb_chipid;
2000
2001 inXGIIDXREG(XGIPART4, 0x00, vb_chipid);
2002 switch (vb_chipid) {
2003 case 0x01:
2004 xgi_video_info.hasVB = HASVB_301;
2005 break;
2006 case 0x02:
2007 xgi_video_info.hasVB = HASVB_302;
2008 break;
2009 default:
2010 xgi_video_info.hasVB = HASVB_NONE;
2011 return FALSE;
2012 }
2013 return TRUE;
2014}
2015
2016
2017
2018/* ------------------ Sensing routines ------------------ */
2019
2020/* TW: Determine and detect attached devices on XGI30x */
2021int
2022XGIDoSense(int tempbl, int tempbh, int tempcl, int tempch)
2023{
2024 int temp,i;
2025
2026 outXGIIDXREG(XGIPART4,0x11,tempbl);
2027 temp = tempbh | tempcl;
2028 setXGIIDXREG(XGIPART4,0x10,0xe0,temp);
2029 for(i=0; i<10; i++) XGI_LongWait(&XGI_Pr);
2030 tempch &= 0x7f;
2031 inXGIIDXREG(XGIPART4,0x03,temp);
2032 temp ^= 0x0e;
2033 temp &= tempch;
2034 return(temp);
2035}
2036
2037void
2038XGI_Sense30x(void)
2039{
2040 u8 backupP4_0d;
2041 u8 testsvhs_tempbl, testsvhs_tempbh;
2042 u8 testsvhs_tempcl, testsvhs_tempch;
2043 u8 testcvbs_tempbl, testcvbs_tempbh;
2044 u8 testcvbs_tempcl, testcvbs_tempch;
2045 u8 testvga2_tempbl, testvga2_tempbh;
2046 u8 testvga2_tempcl, testvga2_tempch;
2047 int myflag, result;
2048
2049 inXGIIDXREG(XGIPART4,0x0d,backupP4_0d);
2050 outXGIIDXREG(XGIPART4,0x0d,(backupP4_0d | 0x04));
2051
2052
2053
2054 testvga2_tempbh = 0x00; testvga2_tempbl = 0xd1;
2055 testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xb9;
2056 testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xb3;
2057 if((XGIhw_ext.ujVBChipID != VB_CHIP_301) &&
2058 (XGIhw_ext.ujVBChipID != VB_CHIP_302)) {
2059 testvga2_tempbh = 0x01; testvga2_tempbl = 0x90;
2060 testsvhs_tempbh = 0x01; testsvhs_tempbl = 0x6b;
2061 testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x74;
2062 if(XGIhw_ext.ujVBChipID == VB_CHIP_301LV ||
2063 XGIhw_ext.ujVBChipID == VB_CHIP_302LV) {
2064 testvga2_tempbh = 0x00; testvga2_tempbl = 0x00;
2065 testsvhs_tempbh = 0x02; testsvhs_tempbl = 0x00;
2066 testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x00;
2067 }
2068 }
2069 if(XGIhw_ext.ujVBChipID != VB_CHIP_301LV &&
2070 XGIhw_ext.ujVBChipID != VB_CHIP_302LV) {
2071 inXGIIDXREG(XGIPART4,0x01,myflag);
2072 if(myflag & 0x04) {
2073 testvga2_tempbh = 0x00; testvga2_tempbl = 0xfd;
2074 testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xdd;
2075 testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xee;
2076 }
2077 }
2078 if((XGIhw_ext.ujVBChipID == VB_CHIP_301LV) ||
2079 (XGIhw_ext.ujVBChipID == VB_CHIP_302LV) ) {
2080 testvga2_tempbh = 0x00; testvga2_tempbl = 0x00;
2081 testvga2_tempch = 0x00; testvga2_tempcl = 0x00;
2082 testsvhs_tempch = 0x04; testsvhs_tempcl = 0x08;
2083 testcvbs_tempch = 0x08; testcvbs_tempcl = 0x08;
2084 } else {
2085 testvga2_tempch = 0x0e; testvga2_tempcl = 0x08;
2086 testsvhs_tempch = 0x06; testsvhs_tempcl = 0x04;
2087 testcvbs_tempch = 0x08; testcvbs_tempcl = 0x04;
2088 }
2089
2090
2091 if(testvga2_tempch || testvga2_tempcl || testvga2_tempbh || testvga2_tempbl) {
2092 result = XGIDoSense(testvga2_tempbl, testvga2_tempbh,
2093 testvga2_tempcl, testvga2_tempch);
2094 if(result) {
2095 printk(KERN_INFO "XGIfb: Detected secondary VGA connection\n");
2096 orXGIIDXREG(XGICR, 0x32, 0x10);
2097 }
2098 }
2099
2100 result = XGIDoSense(testsvhs_tempbl, testsvhs_tempbh,
2101 testsvhs_tempcl, testsvhs_tempch);
2102 if(result) {
2103 printk(KERN_INFO "XGIfb: Detected TV connected to SVHS output\n");
2104 /* TW: So we can be sure that there IS a SVHS output */
2105 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
2106 orXGIIDXREG(XGICR, 0x32, 0x02);
2107 }
2108
2109 if(!result) {
2110 result = XGIDoSense(testcvbs_tempbl, testcvbs_tempbh,
2111 testcvbs_tempcl, testcvbs_tempch);
2112 if(result) {
2113 printk(KERN_INFO "XGIfb: Detected TV connected to CVBS output\n");
2114 /* TW: So we can be sure that there IS a CVBS output */
2115 xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
2116 orXGIIDXREG(XGICR, 0x32, 0x01);
2117 }
2118 }
2119 XGIDoSense(0, 0, 0, 0);
2120
2121 outXGIIDXREG(XGIPART4,0x0d,backupP4_0d);
2122}
2123
2124
2125
2126/* ------------------------ Heap routines -------------------------- */
2127
2128static int XGIfb_heap_init(void)
2129{
2130 XGI_OH *poh;
2131 u8 temp=0;
2132
2133 int agp_enabled = 1;
2134 u32 agp_size;
2135 unsigned long *cmdq_baseport = 0;
2136 unsigned long *read_port = 0;
2137 unsigned long *write_port = 0;
2138 XGI_CMDTYPE cmd_type;
2139#ifndef AGPOFF
2140 struct agp_kern_info *agp_info;
2141 struct agp_memory *agp;
2142 u32 agp_phys;
2143#endif
2144
2145/* TW: The heap start is either set manually using the "mem" parameter, or
2146 * defaults as follows:
2147 * -) If more than 16MB videoRAM available, let our heap start at 12MB.
2148 * -) If more than 8MB videoRAM available, let our heap start at 8MB.
2149 * -) If 4MB or less is available, let it start at 4MB.
2150 * This is for avoiding a clash with X driver which uses the beginning
2151 * of the videoRAM. To limit size of X framebuffer, use Option MaxXFBMem
2152 * in XF86Config-4.
2153 * The heap start can also be specified by parameter "mem" when starting the XGIfb
2154 * driver. XGIfb mem=1024 lets heap starts at 1MB, etc.
2155 */
2156 if ((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size/1024))) {
2157 if (xgi_video_info.video_size > 0x1000000) {
2158 xgi_video_info.heapstart = 0xD00000;
2159 } else if (xgi_video_info.video_size > 0x800000) {
2160 xgi_video_info.heapstart = 0x800000;
2161 } else {
2162 xgi_video_info.heapstart = 0x400000;
2163 }
2164 } else {
2165 xgi_video_info.heapstart = XGIfb_mem * 1024;
2166 }
2167 XGIfb_heap_start =
2168 (unsigned long) (xgi_video_info.video_vbase + xgi_video_info.heapstart);
2169 printk(KERN_INFO "XGIfb: Memory heap starting at %dK\n",
2170 (int)(xgi_video_info.heapstart / 1024));
2171
2172 XGIfb_heap_end = (unsigned long) xgi_video_info.video_vbase + xgi_video_info.video_size;
2173 XGIfb_heap_size = XGIfb_heap_end - XGIfb_heap_start;
2174
2175
2176
2177 /* TW: Now initialize the 310 series' command queue mode.
2178 * On 310/325, there are three queue modes available which
2179 * are chosen by setting bits 7:5 in SR26:
2180 * 1. MMIO queue mode (bit 5, 0x20). The hardware will keep
2181 * track of the queue, the FIFO, command parsing and so
2182 * on. This is the one comparable to the 300 series.
2183 * 2. VRAM queue mode (bit 6, 0x40). In this case, one will
2184 * have to do queue management himself. Register 0x85c4 will
2185 * hold the location of the next free queue slot, 0x85c8
2186 * is the "queue read pointer" whose way of working is
2187 * unknown to me. Anyway, this mode would require a
2188 * translation of the MMIO commands to some kind of
2189 * accelerator assembly and writing these commands
2190 * to the memory location pointed to by 0x85c4.
2191 * We will not use this, as nobody knows how this
2192 * "assembly" works, and as it would require a complete
2193 * re-write of the accelerator code.
2194 * 3. AGP queue mode (bit 7, 0x80). Works as 2., but keeps the
2195 * queue in AGP memory space.
2196 *
2197 * SR26 bit 4 is called "Bypass H/W queue".
2198 * SR26 bit 1 is called "Enable Command Queue Auto Correction"
2199 * SR26 bit 0 resets the queue
2200 * Size of queue memory is encoded in bits 3:2 like this:
2201 * 00 (0x00) 512K
2202 * 01 (0x04) 1M
2203 * 10 (0x08) 2M
2204 * 11 (0x0C) 4M
2205 * The queue location is to be written to 0x85C0.
2206 *
2207 */
2208 cmdq_baseport = (unsigned long *)(xgi_video_info.mmio_vbase + MMIO_QUEUE_PHYBASE);
2209 write_port = (unsigned long *)(xgi_video_info.mmio_vbase + MMIO_QUEUE_WRITEPORT);
2210 read_port = (unsigned long *)(xgi_video_info.mmio_vbase + MMIO_QUEUE_READPORT);
2211
2212 DPRINTK("AGP base: 0x%p, read: 0x%p, write: 0x%p\n", cmdq_baseport, read_port, write_port);
2213
2214 agp_size = COMMAND_QUEUE_AREA_SIZE;
2215
2216#ifndef AGPOFF
2217 if (XGIfb_queuemode == AGP_CMD_QUEUE) {
2218 agp_info = vmalloc(sizeof(*agp_info));
2219 memset((void*)agp_info, 0x00, sizeof(*agp_info));
2220 agp_copy_info(agp_info);
2221
2222 agp_backend_acquire();
2223
2224 agp = agp_allocate_memory(COMMAND_QUEUE_AREA_SIZE/PAGE_SIZE,
2225 AGP_NORMAL_MEMORY);
2226 if (agp == NULL) {
2227 DPRINTK("XGIfb: Allocating AGP buffer failed.\n");
2228 agp_enabled = 0;
2229 } else {
2230 if (agp_bind_memory(agp, agp->pg_start) != 0) {
2231 DPRINTK("XGIfb: AGP: Failed to bind memory\n");
2232 /* TODO: Free AGP memory here */
2233 agp_enabled = 0;
2234 } else {
2235 agp_enable(0);
2236 }
2237 }
2238 }
2239#else
2240 agp_enabled = 0;
2241#endif
2242
2243 /* TW: Now select the queue mode */
2244
2245 if ((agp_enabled) && (XGIfb_queuemode == AGP_CMD_QUEUE)) {
2246 cmd_type = AGP_CMD_QUEUE;
2247 printk(KERN_INFO "XGIfb: Using AGP queue mode\n");
2248/* } else if (XGIfb_heap_size >= COMMAND_QUEUE_AREA_SIZE) */
2249 } else if (XGIfb_queuemode == VM_CMD_QUEUE) {
2250 cmd_type = VM_CMD_QUEUE;
2251 printk(KERN_INFO "XGIfb: Using VRAM queue mode\n");
2252 } else {
2253 printk(KERN_INFO "XGIfb: Using MMIO queue mode\n");
2254 cmd_type = MMIO_CMD;
2255 }
2256
2257 switch (agp_size) {
2258 case 0x80000:
2259 temp = XGI_CMD_QUEUE_SIZE_512k;
2260 break;
2261 case 0x100000:
2262 temp = XGI_CMD_QUEUE_SIZE_1M;
2263 break;
2264 case 0x200000:
2265 temp = XGI_CMD_QUEUE_SIZE_2M;
2266 break;
2267 case 0x400000:
2268 temp = XGI_CMD_QUEUE_SIZE_4M;
2269 break;
2270 }
2271
2272 switch (cmd_type) {
2273 case AGP_CMD_QUEUE:
2274#ifndef AGPOFF
2275 DPRINTK("XGIfb: AGP buffer base = 0x%lx, offset = 0x%x, size = %dK\n",
2276 agp_info->aper_base, agp->physical, agp_size/1024);
2277
2278 agp_phys = agp_info->aper_base + agp->physical;
2279
2280 outXGIIDXREG(XGICR, IND_XGI_AGP_IO_PAD, 0);
2281 outXGIIDXREG(XGICR, IND_XGI_AGP_IO_PAD, XGI_AGP_2X);
2282
2283 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2284
2285 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
2286
2287 *write_port = *read_port;
2288
2289 temp |= XGI_AGP_CMDQUEUE_ENABLE;
2290 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
2291
2292 *cmdq_baseport = agp_phys;
2293
2294 XGIfb_caps |= AGP_CMD_QUEUE_CAP;
2295#endif
2296 break;
2297
2298 case VM_CMD_QUEUE:
2299 XGIfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
2300 XGIfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
2301
2302 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2303
2304 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
2305
2306 *write_port = *read_port;
2307
2308 temp |= XGI_VRAM_CMDQUEUE_ENABLE;
2309 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
2310
2311 *cmdq_baseport = xgi_video_info.video_size - COMMAND_QUEUE_AREA_SIZE;
2312
2313 XGIfb_caps |= VM_CMD_QUEUE_CAP;
2314
2315 DPRINTK("XGIfb: VM Cmd Queue offset = 0x%lx, size is %dK\n",
2316 *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024);
2317 break;
2318
2319 default: /* MMIO */
2320
2321// printk("%s:%d - I'm here\n", __FUNCTION__, __LINE__);
2322 /* TW: This previously only wrote XGI_MMIO_CMD_ENABLE
2323 * to IND_XGI_CMDQUEUE_SET. I doubt that this is
2324 * enough. Reserve memory in any way.
2325 */
2326// FIXME XGIfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
2327// FIXME XGIfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
2328// FIXME
2329// FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2330// FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
2331// FIXME
2332// FIXME *write_port = *read_port;
2333// FIXME
2334// FIXME /* TW: Set Auto_Correction bit */
2335// FIXME temp |= (XGI_MMIO_CMD_ENABLE | XGI_CMD_AUTO_CORR);
2336// FIXME // FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
2337// FIXME
2338// FIXME *cmdq_baseport = xgi_video_info.video_size - COMMAND_QUEUE_AREA_SIZE;
2339// FIXME
2340// FIXME XGIfb_caps |= MMIO_CMD_QUEUE_CAP;
2341// FIXME
2342// FIXME DPRINTK("XGIfb: MMIO Cmd Queue offset = 0x%lx, size is %dK\n",
2343// FIXME *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024);
2344 break;
2345 }
2346
2347
2348
2349
2350 /* TW: Now reserve memory for the HWCursor. It is always located at the very
2351 top of the videoRAM, right below the TB memory area (if used). */
2352 if (XGIfb_heap_size >= XGIfb_hwcursor_size) {
2353 XGIfb_heap_end -= XGIfb_hwcursor_size;
2354 XGIfb_heap_size -= XGIfb_hwcursor_size;
2355 XGIfb_hwcursor_vbase = XGIfb_heap_end;
2356
2357 XGIfb_caps |= HW_CURSOR_CAP;
2358
2359 DPRINTK("XGIfb: Hardware Cursor start at 0x%lx, size is %dK\n",
2360 XGIfb_heap_end, XGIfb_hwcursor_size/1024);
2361 }
2362
2363 XGIfb_heap.poha_chain = NULL;
2364 XGIfb_heap.poh_freelist = NULL;
2365
2366 poh = XGIfb_poh_new_node();
2367
2368 if(poh == NULL) return 1;
2369
2370 poh->poh_next = &XGIfb_heap.oh_free;
2371 poh->poh_prev = &XGIfb_heap.oh_free;
2372 poh->size = XGIfb_heap_end - XGIfb_heap_start + 1;
2373 poh->offset = XGIfb_heap_start - (unsigned long) xgi_video_info.video_vbase;
2374
2375 DPRINTK("XGIfb: Heap start:0x%p, end:0x%p, len=%dk\n",
2376 (char *) XGIfb_heap_start, (char *) XGIfb_heap_end,
2377 (unsigned int) poh->size / 1024);
2378
2379 DPRINTK("XGIfb: First Node offset:0x%x, size:%dk\n",
2380 (unsigned int) poh->offset, (unsigned int) poh->size / 1024);
2381
2382 XGIfb_heap.oh_free.poh_next = poh;
2383 XGIfb_heap.oh_free.poh_prev = poh;
2384 XGIfb_heap.oh_free.size = 0;
2385 XGIfb_heap.max_freesize = poh->size;
2386
2387 XGIfb_heap.oh_used.poh_next = &XGIfb_heap.oh_used;
2388 XGIfb_heap.oh_used.poh_prev = &XGIfb_heap.oh_used;
2389 XGIfb_heap.oh_used.size = SENTINEL;
2390
2391 return 0;
2392}
2393
2394static XGI_OH *XGIfb_poh_new_node(void)
2395{
2396 int i;
2397 unsigned long cOhs;
2398 XGI_OHALLOC *poha;
2399 XGI_OH *poh;
2400
2401 if (XGIfb_heap.poh_freelist == NULL) {
2402 poha = kmalloc(OH_ALLOC_SIZE, GFP_KERNEL);
2403 if(!poha) return NULL;
2404
2405 poha->poha_next = XGIfb_heap.poha_chain;
2406 XGIfb_heap.poha_chain = poha;
2407
2408 cOhs = (OH_ALLOC_SIZE - sizeof(XGI_OHALLOC)) / sizeof(XGI_OH) + 1;
2409
2410 poh = &poha->aoh[0];
2411 for (i = cOhs - 1; i != 0; i--) {
2412 poh->poh_next = poh + 1;
2413 poh = poh + 1;
2414 }
2415
2416 poh->poh_next = NULL;
2417 XGIfb_heap.poh_freelist = &poha->aoh[0];
2418 }
2419
2420 poh = XGIfb_heap.poh_freelist;
2421 XGIfb_heap.poh_freelist = poh->poh_next;
2422
2423 return (poh);
2424}
2425
2426static XGI_OH *XGIfb_poh_allocate(unsigned long size)
2427{
2428 XGI_OH *pohThis;
2429 XGI_OH *pohRoot;
2430 int bAllocated = 0;
2431
2432 if (size > XGIfb_heap.max_freesize) {
2433 DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n",
2434 (unsigned int) size / 1024);
2435 return (NULL);
2436 }
2437
2438 pohThis = XGIfb_heap.oh_free.poh_next;
2439
2440 while (pohThis != &XGIfb_heap.oh_free) {
2441 if (size <= pohThis->size) {
2442 bAllocated = 1;
2443 break;
2444 }
2445 pohThis = pohThis->poh_next;
2446 }
2447
2448 if (!bAllocated) {
2449 DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n",
2450 (unsigned int) size / 1024);
2451 return (NULL);
2452 }
2453
2454 if (size == pohThis->size) {
2455 pohRoot = pohThis;
2456 XGIfb_delete_node(pohThis);
2457 } else {
2458 pohRoot = XGIfb_poh_new_node();
2459
2460 if (pohRoot == NULL) {
2461 return (NULL);
2462 }
2463
2464 pohRoot->offset = pohThis->offset;
2465 pohRoot->size = size;
2466
2467 pohThis->offset += size;
2468 pohThis->size -= size;
2469 }
2470
2471 XGIfb_heap.max_freesize -= size;
2472
2473 pohThis = &XGIfb_heap.oh_used;
2474 XGIfb_insert_node(pohThis, pohRoot);
2475
2476 return (pohRoot);
2477}
2478
2479static void XGIfb_delete_node(XGI_OH *poh)
2480{
2481 XGI_OH *poh_prev;
2482 XGI_OH *poh_next;
2483
2484 poh_prev = poh->poh_prev;
2485 poh_next = poh->poh_next;
2486
2487 poh_prev->poh_next = poh_next;
2488 poh_next->poh_prev = poh_prev;
2489
2490}
2491
2492static void XGIfb_insert_node(XGI_OH *pohList, XGI_OH *poh)
2493{
2494 XGI_OH *pohTemp;
2495
2496 pohTemp = pohList->poh_next;
2497
2498 pohList->poh_next = poh;
2499 pohTemp->poh_prev = poh;
2500
2501 poh->poh_prev = pohList;
2502 poh->poh_next = pohTemp;
2503}
2504
2505static XGI_OH *XGIfb_poh_free(unsigned long base)
2506{
2507 XGI_OH *pohThis;
2508 XGI_OH *poh_freed;
2509 XGI_OH *poh_prev;
2510 XGI_OH *poh_next;
2511 unsigned long ulUpper;
2512 unsigned long ulLower;
2513 int foundNode = 0;
2514
2515 poh_freed = XGIfb_heap.oh_used.poh_next;
2516
2517 while(poh_freed != &XGIfb_heap.oh_used) {
2518 if(poh_freed->offset == base) {
2519 foundNode = 1;
2520 break;
2521 }
2522
2523 poh_freed = poh_freed->poh_next;
2524 }
2525
2526 if (!foundNode) return (NULL);
2527
2528 XGIfb_heap.max_freesize += poh_freed->size;
2529
2530 poh_prev = poh_next = NULL;
2531 ulUpper = poh_freed->offset + poh_freed->size;
2532 ulLower = poh_freed->offset;
2533
2534 pohThis = XGIfb_heap.oh_free.poh_next;
2535
2536 while (pohThis != &XGIfb_heap.oh_free) {
2537 if (pohThis->offset == ulUpper) {
2538 poh_next = pohThis;
2539 }
2540 else if ((pohThis->offset + pohThis->size) ==
2541 ulLower) {
2542 poh_prev = pohThis;
2543 }
2544 pohThis = pohThis->poh_next;
2545 }
2546
2547 XGIfb_delete_node(poh_freed);
2548
2549 if (poh_prev && poh_next) {
2550 poh_prev->size += (poh_freed->size + poh_next->size);
2551 XGIfb_delete_node(poh_next);
2552 XGIfb_free_node(poh_freed);
2553 XGIfb_free_node(poh_next);
2554 return (poh_prev);
2555 }
2556
2557 if (poh_prev) {
2558 poh_prev->size += poh_freed->size;
2559 XGIfb_free_node(poh_freed);
2560 return (poh_prev);
2561 }
2562
2563 if (poh_next) {
2564 poh_next->size += poh_freed->size;
2565 poh_next->offset = poh_freed->offset;
2566 XGIfb_free_node(poh_freed);
2567 return (poh_next);
2568 }
2569
2570 XGIfb_insert_node(&XGIfb_heap.oh_free, poh_freed);
2571
2572 return (poh_freed);
2573}
2574
2575static void XGIfb_free_node(XGI_OH *poh)
2576{
2577 if(poh == NULL) return;
2578
2579 poh->poh_next = XGIfb_heap.poh_freelist;
2580 XGIfb_heap.poh_freelist = poh;
2581
2582}
2583
2584void XGI_malloc(struct XGI_memreq *req)
2585{
2586 XGI_OH *poh;
2587
2588 poh = XGIfb_poh_allocate(req->size);
2589
2590 if(poh == NULL) {
2591 req->offset = 0;
2592 req->size = 0;
2593 DPRINTK("XGIfb: Video RAM allocation failed\n");
2594 } else {
2595 DPRINTK("XGIfb: Video RAM allocation succeeded: 0x%p\n",
2596 (char *) (poh->offset + (unsigned long) xgi_video_info.video_vbase));
2597
2598 req->offset = poh->offset;
2599 req->size = poh->size;
2600 }
2601
2602}
2603
2604void XGI_free(unsigned long base)
2605{
2606 XGI_OH *poh;
2607
2608 poh = XGIfb_poh_free(base);
2609
2610 if(poh == NULL) {
2611 DPRINTK("XGIfb: XGIfb_poh_free() failed at base 0x%x\n",
2612 (unsigned int) base);
2613 }
2614}
2615
2616/* --------------------- SetMode routines ------------------------- */
2617
2618static void XGIfb_pre_setmode(void)
2619{
2620 u8 cr30 = 0, cr31 = 0;
2621
2622 inXGIIDXREG(XGICR, 0x31, cr31);
2623 cr31 &= ~0x60;
2624
2625 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
2626 case DISPTYPE_CRT2:
2627 cr30 = (XGI_VB_OUTPUT_CRT2 | XGI_SIMULTANEOUS_VIEW_ENABLE);
2628 cr31 |= XGI_DRIVER_MODE;
2629 break;
2630 case DISPTYPE_LCD:
2631 cr30 = (XGI_VB_OUTPUT_LCD | XGI_SIMULTANEOUS_VIEW_ENABLE);
2632 cr31 |= XGI_DRIVER_MODE;
2633 break;
2634 case DISPTYPE_TV:
2635 if (xgi_video_info.TV_type == TVMODE_HIVISION)
2636 cr30 = (XGI_VB_OUTPUT_HIVISION | XGI_SIMULTANEOUS_VIEW_ENABLE);
2637 else if (xgi_video_info.TV_plug == TVPLUG_SVIDEO)
2638 cr30 = (XGI_VB_OUTPUT_SVIDEO | XGI_SIMULTANEOUS_VIEW_ENABLE);
2639 else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE)
2640 cr30 = (XGI_VB_OUTPUT_COMPOSITE | XGI_SIMULTANEOUS_VIEW_ENABLE);
2641 else if (xgi_video_info.TV_plug == TVPLUG_SCART)
2642 cr30 = (XGI_VB_OUTPUT_SCART | XGI_SIMULTANEOUS_VIEW_ENABLE);
2643 cr31 |= XGI_DRIVER_MODE;
2644
2645 if (XGIfb_tvmode == 1 || xgi_video_info.TV_type == TVMODE_PAL)
2646 cr31 |= 0x01;
2647 else
2648 cr31 &= ~0x01;
2649 break;
2650 default: /* disable CRT2 */
2651 cr30 = 0x00;
2652 cr31 |= (XGI_DRIVER_MODE | XGI_VB_OUTPUT_DISABLE);
2653 }
2654
2655 outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR30, cr30);
2656 outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR31, cr31);
2657 outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR33, (XGIfb_rate_idx & 0x0F));
2658
2659 if(xgi_video_info.accel) XGIfb_syncaccel();
2660
2661
2662}
2663
2664static void XGIfb_post_setmode(void)
2665{
2666 u8 reg;
2667 BOOLEAN doit = TRUE;
2668#if 0 /* TW: Wrong: Is not in MMIO space, but in RAM */
2669 /* Backup mode number to MMIO space */
2670 if(xgi_video_info.mmio_vbase) {
2671 *(volatile u8 *)(((u8*)xgi_video_info.mmio_vbase) + 0x449) = (unsigned char)XGIfb_mode_no;
2672 }
2673#endif
2674/* outXGIIDXREG(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD);
2675 outXGIIDXREG(XGICR,0x13,0x00);
2676 setXGIIDXREG(XGISR,0x0E,0xF0,0x01);
2677*test**/
2678 if (xgi_video_info.video_bpp == 8) {
2679 /* TW: We can't switch off CRT1 on LVDS/Chrontel in 8bpp Modes */
2680 if ((xgi_video_info.hasVB == HASVB_LVDS) || (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL)) {
2681 doit = FALSE;
2682 }
2683 /* TW: We can't switch off CRT1 on 301B-DH in 8bpp Modes if using LCD */
2684 if (xgi_video_info.disp_state & DISPTYPE_LCD) {
2685 doit = FALSE;
2686 }
2687 }
2688
2689 /* TW: We can't switch off CRT1 if bridge is in slave mode */
2690 if(xgi_video_info.hasVB != HASVB_NONE) {
2691 inXGIIDXREG(XGIPART1, 0x00, reg);
2692
2693
2694 if((reg & 0x50) == 0x10) {
2695 doit = FALSE;
2696 }
2697
2698 } else XGIfb_crt1off = 0;
2699
2700 inXGIIDXREG(XGICR, 0x17, reg);
2701 if((XGIfb_crt1off) && (doit))
2702 reg &= ~0x80;
2703 else
2704 reg |= 0x80;
2705 outXGIIDXREG(XGICR, 0x17, reg);
2706
2707 andXGIIDXREG(XGISR, IND_XGI_RAMDAC_CONTROL, ~0x04);
2708
2709 if((xgi_video_info.disp_state & DISPTYPE_TV) && (xgi_video_info.hasVB == HASVB_301)) {
2710
2711 inXGIIDXREG(XGIPART4, 0x01, reg);
2712
2713 if(reg < 0xB0) { /* Set filter for XGI301 */
2714
2715 switch (xgi_video_info.video_width) {
2716 case 320:
2717 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 4 : 12;
2718 break;
2719 case 640:
2720 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 5 : 13;
2721 break;
2722 case 720:
2723 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 6 : 14;
2724 break;
2725 case 800:
2726 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 7 : 15;
2727 break;
2728 default:
2729 filter = -1;
2730 break;
2731 }
2732
2733 orXGIIDXREG(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
2734
2735 if(xgi_video_info.TV_type == TVMODE_NTSC) {
2736
2737 andXGIIDXREG(XGIPART2, 0x3a, 0x1f);
2738
2739 if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
2740
2741 andXGIIDXREG(XGIPART2, 0x30, 0xdf);
2742
2743 } else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE) {
2744
2745 orXGIIDXREG(XGIPART2, 0x30, 0x20);
2746
2747 switch (xgi_video_info.video_width) {
2748 case 640:
2749 outXGIIDXREG(XGIPART2, 0x35, 0xEB);
2750 outXGIIDXREG(XGIPART2, 0x36, 0x04);
2751 outXGIIDXREG(XGIPART2, 0x37, 0x25);
2752 outXGIIDXREG(XGIPART2, 0x38, 0x18);
2753 break;
2754 case 720:
2755 outXGIIDXREG(XGIPART2, 0x35, 0xEE);
2756 outXGIIDXREG(XGIPART2, 0x36, 0x0C);
2757 outXGIIDXREG(XGIPART2, 0x37, 0x22);
2758 outXGIIDXREG(XGIPART2, 0x38, 0x08);
2759 break;
2760 case 800:
2761 outXGIIDXREG(XGIPART2, 0x35, 0xEB);
2762 outXGIIDXREG(XGIPART2, 0x36, 0x15);
2763 outXGIIDXREG(XGIPART2, 0x37, 0x25);
2764 outXGIIDXREG(XGIPART2, 0x38, 0xF6);
2765 break;
2766 }
2767 }
2768
2769 } else if(xgi_video_info.TV_type == TVMODE_PAL) {
2770
2771 andXGIIDXREG(XGIPART2, 0x3A, 0x1F);
2772
2773 if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
2774
2775 andXGIIDXREG(XGIPART2, 0x30, 0xDF);
2776
2777 } else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE) {
2778
2779 orXGIIDXREG(XGIPART2, 0x30, 0x20);
2780
2781 switch (xgi_video_info.video_width) {
2782 case 640:
2783 outXGIIDXREG(XGIPART2, 0x35, 0xF1);
2784 outXGIIDXREG(XGIPART2, 0x36, 0xF7);
2785 outXGIIDXREG(XGIPART2, 0x37, 0x1F);
2786 outXGIIDXREG(XGIPART2, 0x38, 0x32);
2787 break;
2788 case 720:
2789 outXGIIDXREG(XGIPART2, 0x35, 0xF3);
2790 outXGIIDXREG(XGIPART2, 0x36, 0x00);
2791 outXGIIDXREG(XGIPART2, 0x37, 0x1D);
2792 outXGIIDXREG(XGIPART2, 0x38, 0x20);
2793 break;
2794 case 800:
2795 outXGIIDXREG(XGIPART2, 0x35, 0xFC);
2796 outXGIIDXREG(XGIPART2, 0x36, 0xFB);
2797 outXGIIDXREG(XGIPART2, 0x37, 0x14);
2798 outXGIIDXREG(XGIPART2, 0x38, 0x2A);
2799 break;
2800 }
2801 }
2802 }
2803
2804 if ((filter >= 0) && (filter <=7)) {
2805 DPRINTK("FilterTable[%d]-%d: %02x %02x %02x %02x\n", filter_tb, filter,
2806 XGI_TV_filter[filter_tb].filter[filter][0],
2807 XGI_TV_filter[filter_tb].filter[filter][1],
2808 XGI_TV_filter[filter_tb].filter[filter][2],
2809 XGI_TV_filter[filter_tb].filter[filter][3]
2810 );
2811 outXGIIDXREG(XGIPART2, 0x35, (XGI_TV_filter[filter_tb].filter[filter][0]));
2812 outXGIIDXREG(XGIPART2, 0x36, (XGI_TV_filter[filter_tb].filter[filter][1]));
2813 outXGIIDXREG(XGIPART2, 0x37, (XGI_TV_filter[filter_tb].filter[filter][2]));
2814 outXGIIDXREG(XGIPART2, 0x38, (XGI_TV_filter[filter_tb].filter[filter][3]));
2815 }
2816
2817 }
2818
2819 }
2820
2821}
2822
2823#ifndef MODULE
2824XGIINITSTATIC int __init XGIfb_setup(char *options)
2825{
2826 char *this_opt;
2827
2828
2829
2830 xgi_video_info.refresh_rate = 0;
2831
2832 printk(KERN_INFO "XGIfb: Options %s\n", options);
2833
2834 if (!options || !*options)
2835 return 0;
2836
2837 while((this_opt = strsep(&options, ",")) != NULL) {
2838
2839 if (!*this_opt) continue;
2840
2841 if (!strncmp(this_opt, "mode:", 5)) {
2842 XGIfb_search_mode(this_opt + 5);
2843 } else if (!strncmp(this_opt, "vesa:", 5)) {
2844 XGIfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0));
2845 } else if (!strncmp(this_opt, "mode:", 5)) {
2846 XGIfb_search_mode(this_opt + 5);
2847 } else if (!strncmp(this_opt, "vesa:", 5)) {
2848 XGIfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0));
2849 } else if (!strncmp(this_opt, "vrate:", 6)) {
2850 xgi_video_info.refresh_rate = simple_strtoul(this_opt + 6, NULL, 0);
2851 } else if (!strncmp(this_opt, "rate:", 5)) {
2852 xgi_video_info.refresh_rate = simple_strtoul(this_opt + 5, NULL, 0);
2853 } else if (!strncmp(this_opt, "off", 3)) {
2854 XGIfb_off = 1;
2855 } else if (!strncmp(this_opt, "crt1off", 7)) {
2856 XGIfb_crt1off = 1;
2857 } else if (!strncmp(this_opt, "filter:", 7)) {
2858 filter = (int)simple_strtoul(this_opt + 7, NULL, 0);
2859 } else if (!strncmp(this_opt, "forcecrt2type:", 14)) {
2860 XGIfb_search_crt2type(this_opt + 14);
2861 } else if (!strncmp(this_opt, "forcecrt1:", 10)) {
2862 XGIfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
2863 } else if (!strncmp(this_opt, "tvmode:",7)) {
2864 XGIfb_search_tvstd(this_opt + 7);
2865 } else if (!strncmp(this_opt, "tvstandard:",11)) {
2866 XGIfb_search_tvstd(this_opt + 7);
2867 } else if (!strncmp(this_opt, "mem:",4)) {
2868 XGIfb_mem = simple_strtoul(this_opt + 4, NULL, 0);
2869 } else if (!strncmp(this_opt, "dstn", 4)) {
2870 enable_dstn = 1;
2871 /* TW: DSTN overrules forcecrt2type */
2872 XGIfb_crt2type = DISPTYPE_LCD;
2873 } else if (!strncmp(this_opt, "queuemode:", 10)) {
2874 XGIfb_search_queuemode(this_opt + 10);
2875 } else if (!strncmp(this_opt, "pdc:", 4)) {
2876 XGIfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
2877 if(XGIfb_pdc & ~0x3c) {
2878 printk(KERN_INFO "XGIfb: Illegal pdc parameter\n");
2879 XGIfb_pdc = 0;
2880 }
2881 } else if (!strncmp(this_opt, "noaccel", 7)) {
2882 XGIfb_accel = 0;
2883 } else if (!strncmp(this_opt, "noypan", 6)) {
2884 XGIfb_ypan = 0;
2885 } else if (!strncmp(this_opt, "userom:", 7)) {
2886 XGIfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
2887// } else if (!strncmp(this_opt, "useoem:", 7)) {
2888// XGIfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
2889 } else {
2890 XGIfb_search_mode(this_opt);
2891// printk(KERN_INFO "XGIfb: Invalid option %s\n", this_opt);
2892 }
2893
2894 /* TW: Acceleration only with MMIO mode */
2895 if((XGIfb_queuemode != -1) && (XGIfb_queuemode != MMIO_CMD)) {
2896 XGIfb_ypan = 0;
2897 XGIfb_accel = 0;
2898 }
2899 /* TW: Panning only with acceleration */
2900 if(XGIfb_accel == 0) XGIfb_ypan = 0;
2901
2902 }
2903 printk("\nxgifb: outa xgifb_setup 3450");
2904 return 0;
2905}
2906#endif
2907
2908static unsigned char VBIOS_BUF[65535];
2909
2910unsigned char* attempt_map_rom(struct pci_dev *dev,void *copy_address)
2911{
2912 u32 rom_size = 0;
2913 u32 rom_address = 0;
2914 int j;
2915
2916 /* Get the size of the expansion rom */
2917 pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0xFFFFFFFF);
2918 pci_read_config_dword(dev, PCI_ROM_ADDRESS, &rom_size);
2919 if ((rom_size & 0x01) == 0)
2920 {
2921 printk("No ROM\n");
2922 return NULL;
2923 }
2924
2925 rom_size &= 0xFFFFF800;
2926 rom_size = (~rom_size)+1;
2927
2928 rom_address = pci_resource_start(dev, 0);
2929 if (rom_address == 0 || rom_address == 0xFFFFFFF0)
2930 {
2931 printk("No suitable rom address found\n"); return NULL;
2932 }
2933
2934 printk("ROM Size is %dK, Address is %x\n", rom_size/1024, rom_address);
2935
2936 /* Map ROM */
2937 pci_write_config_dword(dev, PCI_ROM_ADDRESS, rom_address | PCI_ROM_ADDRESS_ENABLE);
2938
2939 /* memcpy(copy_address, rom_address, rom_size); */
2940 {
2941 unsigned char *virt_addr = ioremap(rom_address, 0x8000000);
2942
2943 unsigned char *from = (unsigned char *)virt_addr;
2944 unsigned char *to = (unsigned char *)copy_address;
2945 for (j=0; j<65536 /*rom_size*/; j++) *to++ = *from++;
2946 }
2947
2948 pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0);
2949
2950 printk("Copy is done\n");
2951
2952 return copy_address;
2953}
2954
2955int __devinit xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
2956{
2957 u16 reg16;
2958 u8 reg, reg1;
2959 u8 CR48,CR38;
2960 if (XGIfb_off)
2961 return -ENXIO;
2962
2963 XGIfb_registered = 0;
2964
2965 memset(&XGIhw_ext, 0, sizeof(HW_DEVICE_EXTENSION));
2966#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3))
2967 fb_info = framebuffer_alloc(sizeof(struct fb_info), &pdev->dev);
2968 if(!fb_info) return -ENOMEM;
2969#else
2970 XGI_fb_info = kmalloc( sizeof(struct fb_info), GFP_KERNEL);
2971 if(!XGI_fb_info) return -ENOMEM;
2972 memset(XGI_fb_info, 0, sizeof(struct fb_info));
2973#endif
2974
2975 xgi_video_info.chip_id = pdev->device;
2976 pci_read_config_byte(pdev, PCI_REVISION_ID,&xgi_video_info.revision_id);
2977 pci_read_config_word(pdev, PCI_COMMAND, &reg16);
2978 XGIhw_ext.jChipRevision = xgi_video_info.revision_id;
2979 XGIvga_enabled = reg16 & 0x01;
2980
2981 xgi_video_info.pcibus = pdev->bus->number;
2982 xgi_video_info.pcislot = PCI_SLOT(pdev->devfn);
2983 xgi_video_info.pcifunc = PCI_FUNC(pdev->devfn);
2984 xgi_video_info.subsysvendor = pdev->subsystem_vendor;
2985 xgi_video_info.subsysdevice = pdev->subsystem_device;
2986
2987 xgi_video_info.video_base = pci_resource_start(pdev, 0);
2988 xgi_video_info.mmio_base = pci_resource_start(pdev, 1);
2989 XGIfb_mmio_size = pci_resource_len(pdev, 1);
2990 xgi_video_info.vga_base = pci_resource_start(pdev, 2) + 0x30;
2991 XGIhw_ext.pjIOAddress = (PUCHAR)xgi_video_info.vga_base;
2992 //XGI_Pr.RelIO = ioremap(pci_resource_start(pdev, 2), 128) + 0x30;
2993 printk("XGIfb: Relocate IO address: %lx [%08lx] \n", (unsigned long)pci_resource_start(pdev, 2), XGI_Pr.RelIO);
2994
2995 if (pci_enable_device(pdev))
2996 return -EIO;
2997
2998 XGIRegInit(&XGI_Pr, (ULONG)XGIhw_ext.pjIOAddress);
2999
3000 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
3001 inXGIIDXREG(XGISR, IND_XGI_PASSWORD, reg1);
3002
3003 if(reg1 != 0xa1) /*I/O error */
3004 {
3005 printk("\nXGIfb: I/O error!!!");
3006 return -EIO;
3007 }
3008
3009 switch (xgi_video_info.chip_id) {
3010 case PCI_DEVICE_ID_XG_20:
3011 orXGIIDXREG(XGICR, Index_CR_GPIO_Reg3, GPIOG_EN);
3012 inXGIIDXREG(XGICR, Index_CR_GPIO_Reg1, CR48);
3013 if (CR48&GPIOG_READ)
3014 xgi_video_info.chip = XG21;
3015 else
3016 xgi_video_info.chip = XG20;
3017 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
3018 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
3019 break;
3020 case PCI_DEVICE_ID_XG_40:
3021 xgi_video_info.chip = XG40;
3022 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
3023 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
3024 break;
3025 case PCI_DEVICE_ID_XG_41:
3026 xgi_video_info.chip = XG41;
3027 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
3028 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
3029 break;
3030 case PCI_DEVICE_ID_XG_42:
3031 xgi_video_info.chip = XG42;
3032 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
3033 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
3034 break;
3035 case PCI_DEVICE_ID_XG_27:
3036 xgi_video_info.chip = XG27;
3037 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
3038 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
3039 break;
3040 default:
3041 return -ENODEV;
3042 }
3043
3044 printk("XGIfb:chipid = %x\n",xgi_video_info.chip);
3045 XGIhw_ext.jChipType = xgi_video_info.chip;
3046
3047 switch (xgi_video_info.chip) {
3048 case XG40:
3049 case XG41:
3050 case XG42:
3051 case XG45:
3052 case XG20:
3053 case XG21:
3054 case XG27:
3055 XGIhw_ext.bIntegratedMMEnabled = TRUE;
3056 break;
3057
3058 default:
3059 break;
3060 }
3061
3062
3063 XGIhw_ext.pDevice = NULL;
3064 if ((xgi_video_info.chip == XG21) || (XGIfb_userom))
3065 {
3066 XGIhw_ext.pjVirtualRomBase = attempt_map_rom(pdev, VBIOS_BUF);
3067
3068 if(XGIhw_ext.pjVirtualRomBase)
3069 printk(KERN_INFO "XGIfb: Video ROM found and mapped to %p\n",XGIhw_ext.pjVirtualRomBase);
3070 else
3071 printk(KERN_INFO "XGIfb: Video ROM not found\n");
3072 } else {
3073 XGIhw_ext.pjVirtualRomBase = NULL;
3074 printk(KERN_INFO "XGIfb: Video ROM usage disabled\n");
3075 }
3076 XGIhw_ext.pjCustomizedROMImage = NULL;
3077 XGIhw_ext.bSkipDramSizing = 0;
3078 XGIhw_ext.pQueryVGAConfigSpace = &XGIfb_query_VGA_config_space;
3079// XGIhw_ext.pQueryNorthBridgeSpace = &XGIfb_query_north_bridge_space;
3080 strcpy(XGIhw_ext.szVBIOSVer, "0.84");
3081
3082
3083 XGIhw_ext.pSR = vmalloc(sizeof(XGI_DSReg) * SR_BUFFER_SIZE);
3084 if (XGIhw_ext.pSR == NULL)
3085 {
3086 printk(KERN_ERR "XGIfb: Fatal error: Allocating SRReg space failed.\n");
3087 return -ENODEV;
3088 }
3089 XGIhw_ext.pSR[0].jIdx = XGIhw_ext.pSR[0].jVal = 0xFF;
3090
3091 XGIhw_ext.pCR = vmalloc(sizeof(XGI_DSReg) * CR_BUFFER_SIZE);
3092 if (XGIhw_ext.pCR == NULL)
3093 {
3094 vfree(XGIhw_ext.pSR);
3095 printk(KERN_ERR "XGIfb: Fatal error: Allocating CRReg space failed.\n");
3096 return -ENODEV;
3097 }
3098 XGIhw_ext.pCR[0].jIdx = XGIhw_ext.pCR[0].jVal = 0xFF;
3099
3100
3101
3102
3103 if (!XGIvga_enabled)
3104 {
3105 /* Mapping Max FB Size for 315 Init */
3106 XGIhw_ext.pjVideoMemoryAddress = ioremap(xgi_video_info.video_base, 0x10000000);
3107 if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF))
3108 {
3109#ifdef LINUXBIOS
3110 printk("XGIfb: XGIInit() ...");
3111 /* XGIInitNewt for LINUXBIOS only */
3112 if(XGIInitNew(&XGIhw_ext))
3113 {
3114 printk("OK\n");
3115 }
3116 else
3117 {
3118 printk("Fail\n");
3119 }
3120#endif
3121
3122 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
3123
3124
3125 }
3126 }
3127#ifdef LINUXBIOS
3128 else
3129 {
3130 XGIhw_ext.pjVideoMemoryAddress = ioremap(xgi_video_info.video_base, 0x10000000);
3131 if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF))
3132 {
3133
3134 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
3135
3136 // yilin Because no VBIOS DRAM Sizing, Dram size will error.
3137 // Set SR13 ,14 temporarily for UDtech
3138 outXGIIDXREG(XGISR, 0x13, 0x45);
3139 outXGIIDXREG(XGISR, 0x14, 0x51);
3140
3141
3142 }
3143 }
3144#endif
3145 if (XGIfb_get_dram_size())
3146 {
3147 vfree(XGIhw_ext.pSR);
3148 vfree(XGIhw_ext.pCR);
3149 printk(KERN_INFO "XGIfb: Fatal error: Unable to determine RAM size.\n");
3150 return -ENODEV;
3151 }
3152
3153
3154
3155 if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF))
3156 {
3157 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
3158 orXGIIDXREG(XGISR, IND_XGI_PCI_ADDRESS_SET, (XGI_PCI_ADDR_ENABLE | XGI_MEM_MAP_IO_ENABLE));
3159 /* Enable 2D accelerator engine */
3160 orXGIIDXREG(XGISR, IND_XGI_MODULE_ENABLE, XGI_ENABLE_2D);
3161 }
3162
3163 XGIhw_ext.ulVideoMemorySize = xgi_video_info.video_size;
3164
3165 if (!request_mem_region(xgi_video_info.video_base, xgi_video_info.video_size, "XGIfb FB"))
3166 { printk("unable request memory size %x",xgi_video_info.video_size);
3167 printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve frame buffer memory\n");
3168 printk(KERN_ERR "XGIfb: Is there another framebuffer driver active?\n");
3169 vfree(XGIhw_ext.pSR);
3170 vfree(XGIhw_ext.pCR);
3171 return -ENODEV;
3172 }
3173
3174 if (!request_mem_region(xgi_video_info.mmio_base, XGIfb_mmio_size, "XGIfb MMIO"))
3175 {
3176 printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve MMIO region\n");
3177 release_mem_region(xgi_video_info.video_base, xgi_video_info.video_size);
3178 vfree(XGIhw_ext.pSR);
3179 vfree(XGIhw_ext.pCR);
3180 return -ENODEV;
3181 }
3182
3183 xgi_video_info.video_vbase = XGIhw_ext.pjVideoMemoryAddress =
3184 ioremap(xgi_video_info.video_base, xgi_video_info.video_size);
3185 xgi_video_info.mmio_vbase = ioremap(xgi_video_info.mmio_base, XGIfb_mmio_size);
3186
3187 printk(KERN_INFO "XGIfb: Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
3188 xgi_video_info.video_base, xgi_video_info.video_vbase,xgi_video_info.video_size / 1024);
3189
3190 printk(KERN_INFO "XGIfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",
3191 xgi_video_info.mmio_base, xgi_video_info.mmio_vbase,XGIfb_mmio_size / 1024);
3192 printk("XGIfb: XGIInitNew() ...");
3193 if(XGIInitNew(&XGIhw_ext))
3194 {
3195 printk("OK\n");
3196 }
3197 else
3198 {
3199 printk("Fail\n");
3200 }
3201
3202 if(XGIfb_heap_init())
3203 {
3204 printk(KERN_WARNING "XGIfb: Failed to initialize offscreen memory heap\n");
3205 }
3206
3207
3208 xgi_video_info.mtrr = (unsigned int) 0;
3209
3210 if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF))
3211 {
3212 xgi_video_info.hasVB = HASVB_NONE;
3213 if((xgi_video_info.chip == XG20)||(xgi_video_info.chip == XG27))
3214 xgi_video_info.hasVB = HASVB_NONE;
3215 else if(xgi_video_info.chip == XG21) {
3216 inXGIIDXREG(XGICR,0x38,CR38);
3217 if ((CR38&0xE0) == 0xC0) {
3218 xgi_video_info.disp_state = DISPTYPE_LCD;
3219 if (!XGIfb_GetXG21LVDSData()) {
3220 int m;
3221 for (m=0; m < sizeof(XGI21_LCDCapList)/sizeof(XGI21_LVDSCapStruct); m++) {
3222 if ((XGI21_LCDCapList[m].LVDSHDE == XGIbios_mode[xgifb_mode_idx].xres) &&
3223 (XGI21_LCDCapList[m].LVDSVDE == XGIbios_mode[xgifb_mode_idx].yres)) {
3224 XGINew_SetReg1( XGI_Pr.P3d4 , 0x36, m) ;
3225 }
3226 }
3227 }
3228 }
3229 else if ((CR38&0xE0) == 0x60)
3230 xgi_video_info.hasVB = HASVB_CHRONTEL ;
3231 else
3232 xgi_video_info.hasVB = HASVB_NONE;
3233 }
3234 else
3235 XGIfb_get_VB_type();
3236
3237 XGIhw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
3238
3239 XGIhw_ext.ulExternalChip = 0;
3240
3241 switch (xgi_video_info.hasVB) {
3242 case HASVB_301:
3243 inXGIIDXREG(XGIPART4, 0x01, reg);
3244 if (reg >= 0xE0) {
3245 XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
3246 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg);
3247 } else if (reg >= 0xD0) {
3248 XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
3249 printk(KERN_INFO "XGIfb: XGI301LV bridge detected (revision 0x%02x)\n",reg);
3250 }
3251 /* else if (reg >= 0xB0) {
3252 XGIhw_ext.ujVBChipID = VB_CHIP_301B;
3253 inXGIIDXREG(XGIPART4,0x23,reg1);
3254 printk("XGIfb: XGI301B bridge detected\n");
3255 }*/
3256 else {
3257 XGIhw_ext.ujVBChipID = VB_CHIP_301;
3258 printk("XGIfb: XGI301 bridge detected\n");
3259 }
3260 break;
3261 case HASVB_302:
3262 inXGIIDXREG(XGIPART4, 0x01, reg);
3263 if (reg >= 0xE0) {
3264 XGIhw_ext.ujVBChipID = VB_CHIP_302LV;
3265 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg);
3266 } else if (reg >= 0xD0) {
3267 XGIhw_ext.ujVBChipID = VB_CHIP_301LV;
3268 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg);
3269 } else if (reg >= 0xB0) {
3270 inXGIIDXREG(XGIPART4,0x23,reg1);
3271
3272 XGIhw_ext.ujVBChipID = VB_CHIP_302B;
3273
3274 } else {
3275 XGIhw_ext.ujVBChipID = VB_CHIP_302;
3276 printk(KERN_INFO "XGIfb: XGI302 bridge detected\n");
3277 }
3278 break;
3279 case HASVB_LVDS:
3280 XGIhw_ext.ulExternalChip = 0x1;
3281 printk(KERN_INFO "XGIfb: LVDS transmitter detected\n");
3282 break;
3283 case HASVB_TRUMPION:
3284 XGIhw_ext.ulExternalChip = 0x2;
3285 printk(KERN_INFO "XGIfb: Trumpion Zurac LVDS scaler detected\n");
3286 break;
3287 case HASVB_CHRONTEL:
3288 XGIhw_ext.ulExternalChip = 0x4;
3289 printk(KERN_INFO "XGIfb: Chrontel TV encoder detected\n");
3290 break;
3291 case HASVB_LVDS_CHRONTEL:
3292 XGIhw_ext.ulExternalChip = 0x5;
3293 printk(KERN_INFO "XGIfb: LVDS transmitter and Chrontel TV encoder detected\n");
3294 break;
3295 default:
3296 printk(KERN_INFO "XGIfb: No or unknown bridge type detected\n");
3297 break;
3298 }
3299
3300 if (xgi_video_info.hasVB != HASVB_NONE) {
3301 XGIfb_detect_VB();
3302 }
3303
3304 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
3305 if (XGIfb_crt1off)
3306 xgi_video_info.disp_state |= DISPMODE_SINGLE;
3307 else
3308 xgi_video_info.disp_state |= (DISPMODE_MIRROR | DISPTYPE_CRT1);
3309 } else {
3310 xgi_video_info.disp_state = DISPMODE_SINGLE | DISPTYPE_CRT1;
3311 }
3312
3313 if (xgi_video_info.disp_state & DISPTYPE_LCD) {
3314 if (!enable_dstn) {
3315 inXGIIDXREG(XGICR, IND_XGI_LCD_PANEL, reg);
3316 reg &= 0x0f;
3317 XGIhw_ext.ulCRT2LCDType = XGI310paneltype[reg];
3318
3319 } else {
3320 // TW: FSTN/DSTN
3321 XGIhw_ext.ulCRT2LCDType = LCD_320x480;
3322 }
3323 }
3324
3325 XGIfb_detectedpdc = 0;
3326
3327 XGIfb_detectedlcda = 0xff;
3328#ifndef LINUXBIOS
3329
3330 /* TW: Try to find about LCDA */
3331
3332 if((XGIhw_ext.ujVBChipID == VB_CHIP_302B) ||
3333 (XGIhw_ext.ujVBChipID == VB_CHIP_301LV) ||
3334 (XGIhw_ext.ujVBChipID == VB_CHIP_302LV))
3335 {
3336 int tmp;
3337 inXGIIDXREG(XGICR,0x34,tmp);
3338 if(tmp <= 0x13)
3339 {
3340 // Currently on LCDA? (Some BIOSes leave CR38)
3341 inXGIIDXREG(XGICR,0x38,tmp);
3342 if((tmp & 0x03) == 0x03)
3343 {
3344// XGI_Pr.XGI_UseLCDA = TRUE;
3345 }else
3346 {
3347 // Currently on LCDA? (Some newer BIOSes set D0 in CR35)
3348 inXGIIDXREG(XGICR,0x35,tmp);
3349 if(tmp & 0x01)
3350 {
3351// XGI_Pr.XGI_UseLCDA = TRUE;
3352 }else
3353 {
3354 inXGIIDXREG(XGICR,0x30,tmp);
3355 if(tmp & 0x20)
3356 {
3357 inXGIIDXREG(XGIPART1,0x13,tmp);
3358 if(tmp & 0x04)
3359 {
3360// XGI_Pr.XGI_UseLCDA = TRUE;
3361 }
3362 }
3363 }
3364 }
3365 }
3366
3367 }
3368
3369
3370#endif
3371
3372 if (xgifb_mode_idx >= 0)
3373 xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
3374
3375 if (xgifb_mode_idx < 0) {
3376 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
3377 case DISPTYPE_LCD:
3378 xgifb_mode_idx = DEFAULT_LCDMODE;
3379 if (xgi_video_info.chip == XG21)
3380 {
3381 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
3382 }
3383 break;
3384 case DISPTYPE_TV:
3385 xgifb_mode_idx = DEFAULT_TVMODE;
3386 break;
3387 default:
3388 xgifb_mode_idx = DEFAULT_MODE;
3389 break;
3390 }
3391 }
3392
3393 XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
3394
3395
3396 if( xgi_video_info.refresh_rate == 0)
3397 xgi_video_info.refresh_rate = 60; /*yilin set default refresh rate */
3398 if(XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0)
3399 {
3400 XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
3401 xgi_video_info.refresh_rate = 60;
3402 }
3403
3404 xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
3405 xgi_video_info.video_vwidth = xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres;
3406 xgi_video_info.video_vheight = xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres;
3407 xgi_video_info.org_x = xgi_video_info.org_y = 0;
3408 xgi_video_info.video_linelength = xgi_video_info.video_width * (xgi_video_info.video_bpp >> 3);
3409 switch(xgi_video_info.video_bpp) {
3410 case 8:
3411 xgi_video_info.DstColor = 0x0000;
3412 xgi_video_info.XGI310_AccelDepth = 0x00000000;
3413 xgi_video_info.video_cmap_len = 256;
3414 break;
3415 case 16:
3416 xgi_video_info.DstColor = 0x8000;
3417 xgi_video_info.XGI310_AccelDepth = 0x00010000;
3418 xgi_video_info.video_cmap_len = 16;
3419 break;
3420 case 32:
3421 xgi_video_info.DstColor = 0xC000;
3422 xgi_video_info.XGI310_AccelDepth = 0x00020000;
3423 xgi_video_info.video_cmap_len = 16;
3424 break;
3425 default:
3426 xgi_video_info.video_cmap_len = 16;
3427 printk(KERN_INFO "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp);
3428 break;
3429 }
3430
3431
3432
3433 printk(KERN_INFO "XGIfb: Default mode is %dx%dx%d (%dHz)\n",
3434 xgi_video_info.video_width, xgi_video_info.video_height, xgi_video_info.video_bpp,
3435 xgi_video_info.refresh_rate);
3436
3437 default_var.xres = default_var.xres_virtual = xgi_video_info.video_width;
3438 default_var.yres = default_var.yres_virtual = xgi_video_info.video_height;
3439 default_var.bits_per_pixel = xgi_video_info.video_bpp;
3440
3441 XGIfb_bpp_to_var(&default_var);
3442
3443 default_var.pixclock = (u32) (1000000000 /
3444 XGIfb_mode_rate_to_dclock(&XGI_Pr, &XGIhw_ext,
3445 XGIfb_mode_no, XGIfb_rate_idx));
3446
3447 if(XGIfb_mode_rate_to_ddata(&XGI_Pr, &XGIhw_ext,
3448 XGIfb_mode_no, XGIfb_rate_idx,
3449 &default_var.left_margin, &default_var.right_margin,
3450 &default_var.upper_margin, &default_var.lower_margin,
3451 &default_var.hsync_len, &default_var.vsync_len,
3452 &default_var.sync, &default_var.vmode)) {
3453
3454 if((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
3455 default_var.yres <<= 1;
3456 default_var.yres_virtual <<= 1;
3457 } else if((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
3458 default_var.pixclock >>= 1;
3459 default_var.yres >>= 1;
3460 default_var.yres_virtual >>= 1;
3461 }
3462
3463 }
3464
3465
3466#if 0
3467#ifdef XGIFB_PAN
3468 if(XGIfb_ypan) {
3469 default_var.yres_virtual =
3470 xgi_video_info.heapstart / (default_var.xres * (default_var.bits_per_pixel >> 3));
3471 if(default_var.yres_virtual <= default_var.yres) {
3472 default_var.yres_virtual = default_var.yres;
3473 }
3474 }
3475#endif
3476#endif
3477
3478
3479 xgi_video_info.accel = 0;
3480 if(XGIfb_accel) {
3481 xgi_video_info.accel = -1;
3482 default_var.accel_flags |= FB_ACCELF_TEXT;
3483 XGIfb_initaccel();
3484 }
3485
3486 fb_info->flags = FBINFO_FLAG_DEFAULT;
3487 fb_info->var = default_var;
3488 fb_info->fix = XGIfb_fix;
3489 fb_info->par = &xgi_video_info;
3490 fb_info->screen_base = xgi_video_info.video_vbase;
3491 fb_info->fbops = &XGIfb_ops;
3492 XGIfb_get_fix(&fb_info->fix, -1, fb_info);
3493 fb_info->pseudo_palette = pseudo_palette;
3494
3495 fb_alloc_cmap(&fb_info->cmap, 256 , 0);
3496
3497
3498#ifdef CONFIG_MTRR
3499 xgi_video_info.mtrr = mtrr_add((unsigned int) xgi_video_info.video_base,
3500 (unsigned int) xgi_video_info.video_size,
3501 MTRR_TYPE_WRCOMB, 1);
3502 if(xgi_video_info.mtrr) {
3503 printk(KERN_INFO "XGIfb: Added MTRRs\n");
3504 }
3505#endif
3506
3507 if(register_framebuffer(fb_info) < 0)
3508 {
3509 return -EINVAL;
3510 }
3511
3512 XGIfb_registered = 1;
3513
3514 printk(KERN_INFO "XGIfb: Installed XGIFB_GET_INFO ioctl (%x)\n", XGIFB_GET_INFO);
3515
3516/* printk(KERN_INFO "XGIfb: 2D acceleration is %s, scrolling mode %s\n",
3517 XGIfb_accel ? "enabled" : "disabled",
3518 XGIfb_ypan ? "ypan" : "redraw");
3519*/
3520 printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n",
3521 fb_info->node, myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
3522
3523
3524 }
3525
3526 dumpVGAReg();
3527
3528 return 0;
3529}
3530
3531
3532/*****************************************************/
3533/* PCI DEVICE HANDLING */
3534/*****************************************************/
3535
3536static void __devexit xgifb_remove(struct pci_dev *pdev)
3537{
3538 /* Unregister the framebuffer */
3539// if(xgi_video_info.registered) {
3540 unregister_framebuffer(fb_info);
3541#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3))
3542 framebuffer_release(fb_info);
3543#else
3544 kfree(fb_info);
3545#endif
3546// }
3547
3548 pci_set_drvdata(pdev, NULL);
3549
3550};
3551
3552static struct pci_driver xgifb_driver = {
3553 .name = "xgifb",
3554 .id_table = xgifb_pci_table,
3555 .probe = xgifb_probe,
3556 .remove = __devexit_p(xgifb_remove)
3557};
3558
3559XGIINITSTATIC int __init xgifb_init(void)
3560{
3561#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
3562#ifndef MODULE
3563 char *option = NULL;
3564
3565 if (fb_get_options("xgifb", &option))
3566 return -ENODEV;
3567 XGIfb_setup(option);
3568#endif
3569#endif
3570 return(pci_register_driver(&xgifb_driver));
3571}
3572
3573#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
3574#ifndef MODULE
3575module_init(xgifb_init);
3576#endif
3577#endif
3578
3579/*****************************************************/
3580/* MODULE */
3581/*****************************************************/
3582
3583#ifdef MODULE
3584
3585static char *mode = NULL;
3586static int vesa = 0;
3587static unsigned int rate = 0;
3588static unsigned int crt1off = 1;
3589static unsigned int mem = 0;
3590static char *forcecrt2type = NULL;
3591static int forcecrt1 = -1;
3592static int pdc = -1;
3593static int pdc1 = -1;
3594static int noaccel = -1;
3595static int noypan = -1;
3596static int nomax = -1;
3597static int userom = -1;
3598static int useoem = -1;
3599static char *tvstandard = NULL;
3600static int nocrt2rate = 0;
3601static int scalelcd = -1;
3602static char *specialtiming = NULL;
3603static int lvdshl = -1;
3604static int tvxposoffset = 0, tvyposoffset = 0;
3605#if !defined(__i386__) && !defined(__x86_64__)
3606static int resetcard = 0;
3607static int videoram = 0;
3608#endif
3609
3610MODULE_DESCRIPTION("Z7 Z9 Z9S Z11 framebuffer device driver");
3611MODULE_LICENSE("GPL");
3612MODULE_AUTHOR("XGITECH , Others");
3613
3614
3615
3616module_param(mem, int, 0);
3617module_param(noaccel, int, 0);
3618module_param(noypan, int, 0);
3619module_param(nomax, int, 0);
3620module_param(userom, int, 0);
3621module_param(useoem, int, 0);
3622module_param(mode, charp, 0);
3623module_param(vesa, int, 0);
3624module_param(rate, int, 0);
3625module_param(forcecrt1, int, 0);
3626module_param(forcecrt2type, charp, 0);
3627module_param(scalelcd, int, 0);
3628module_param(pdc, int, 0);
3629module_param(pdc1, int, 0);
3630module_param(specialtiming, charp, 0);
3631module_param(lvdshl, int, 0);
3632module_param(tvstandard, charp, 0);
3633module_param(tvxposoffset, int, 0);
3634module_param(tvyposoffset, int, 0);
3635module_param(filter, int, 0);
3636module_param(nocrt2rate, int, 0);
3637#if !defined(__i386__) && !defined(__x86_64__)
3638module_param(resetcard, int, 0);
3639module_param(videoram, int, 0);
3640#endif
3641
3642
3643MODULE_PARM_DESC(mem,
3644 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
3645 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
3646 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
3647 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
3648 "otherwise at 12288KB. On 315 and Xabre series, the heap size is 32KB by default.\n"
3649 "The value is to be specified without 'KB' and must match the MaxXFBMem setting\n"
3650 "for XFree86 4.x/X.org 6.7 and later.\n");
3651
3652MODULE_PARM_DESC(noaccel,
3653 "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
3654 "(default: 0)\n");
3655
3656MODULE_PARM_DESC(noypan,
3657 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
3658 "will be performed by redrawing the screen. (default: 0)\n");
3659
3660MODULE_PARM_DESC(nomax,
3661 "\nIf y-panning is enabled, xgifb will by default use the entire available video\n"
3662 "memory for the virtual screen in order to optimize scrolling performance. If\n"
3663 "this is set to anything other than 0, xgifb will not do this and thereby \n"
3664 "enable the user to positively specify a virtual Y size of the screen using\n"
3665 "fbset. (default: 0)\n");
3666
3667
3668
3669MODULE_PARM_DESC(mode,
3670 "\nSelects the desired default display mode in the format XxYxDepth,\n"
3671 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
3672 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
3673 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
3674
3675MODULE_PARM_DESC(vesa,
3676 "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
3677 "0x117 (default: 0x0103)\n");
3678
3679
3680MODULE_PARM_DESC(rate,
3681 "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
3682 "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
3683 "will be ignored (default: 60)\n");
3684
3685MODULE_PARM_DESC(forcecrt1,
3686 "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
3687 "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
3688 "0=CRT1 OFF) (default: [autodetected])\n");
3689
3690MODULE_PARM_DESC(forcecrt2type,
3691 "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
3692 "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
3693 "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
3694 "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
3695 "be used instead of TV to override the TV detection. Furthermore, on systems\n"
3696 "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
3697 "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
3698 "depends on the very hardware in use. (default: [autodetected])\n");
3699
3700MODULE_PARM_DESC(scalelcd,
3701 "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
3702 "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
3703 "show black bars around the image, TMDS panels will probably do the scaling\n"
3704 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
3705
3706MODULE_PARM_DESC(pdc,
3707 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
3708 "should detect this correctly in most cases; however, sometimes this is not\n"
3709 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
3710 "on a 300 series chipset; 6 on a 315 series chipset. If the problem persists,\n"
3711 "try other values (on 300 series: between 4 and 60 in steps of 4; on 315 series:\n"
3712 "any value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
3713
3714MODULE_PARM_DESC(pdc1,
3715 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330\n"
3716 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
3717 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
3718 "implemented yet.\n");
3719
3720MODULE_PARM_DESC(specialtiming,
3721 "\nPlease refer to documentation for more information on this option.\n");
3722
3723MODULE_PARM_DESC(lvdshl,
3724 "\nPlease refer to documentation for more information on this option.\n");
3725
3726MODULE_PARM_DESC(tvstandard,
3727 "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
3728 "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
3729
3730MODULE_PARM_DESC(tvxposoffset,
3731 "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
3732 "Default: 0\n");
3733
3734MODULE_PARM_DESC(tvyposoffset,
3735 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
3736 "Default: 0\n");
3737
3738MODULE_PARM_DESC(filter,
3739 "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n"
3740 "(Possible values 0-7, default: [no filter])\n");
3741
3742MODULE_PARM_DESC(nocrt2rate,
3743 "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
3744 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
3745
3746
3747
3748
3749int __init xgifb_init_module(void)
3750{
3751 printk("\nXGIfb_init_module");
3752 if(mode)
3753 XGIfb_search_mode(mode);
3754 else if (vesa != -1)
3755 XGIfb_search_vesamode(vesa);
3756
3757 return(xgifb_init());
3758}
3759
3760static void __exit xgifb_remove_module(void)
3761{
3762 pci_unregister_driver(&xgifb_driver);
3763 printk(KERN_DEBUG "xgifb: Module unloaded\n");
3764}
3765
3766module_init(xgifb_init_module);
3767module_exit(xgifb_remove_module);
3768
3769#endif /* /MODULE */
3770
3771EXPORT_SYMBOL(XGI_malloc);
3772EXPORT_SYMBOL(XGI_free);
3773
diff --git a/drivers/staging/xgifb/XGIfb.h b/drivers/staging/xgifb/XGIfb.h
new file mode 100644
index 000000000000..41bf163d4e6b
--- /dev/null
+++ b/drivers/staging/xgifb/XGIfb.h
@@ -0,0 +1,215 @@
1#ifndef _LINUX_XGIFB
2#define _LINUX_XGIFB
3#include <linux/spinlock.h>
4#include <asm/ioctl.h>
5#include <asm/types.h>
6
7#define DISPTYPE_CRT1 0x00000008L
8#define DISPTYPE_CRT2 0x00000004L
9#define DISPTYPE_LCD 0x00000002L
10#define DISPTYPE_TV 0x00000001L
11#define DISPTYPE_DISP1 DISPTYPE_CRT1
12#define DISPTYPE_DISP2 (DISPTYPE_CRT2 | DISPTYPE_LCD | DISPTYPE_TV)
13#define DISPMODE_SINGLE 0x00000020L
14#define DISPMODE_MIRROR 0x00000010L
15#define DISPMODE_DUALVIEW 0x00000040L
16
17#define HASVB_NONE 0x00
18#define HASVB_301 0x01
19#define HASVB_LVDS 0x02
20#define HASVB_TRUMPION 0x04
21#define HASVB_LVDS_CHRONTEL 0x10
22#define HASVB_302 0x20
23#define HASVB_303 0x40
24#define HASVB_CHRONTEL 0x80
25
26#ifndef XGIFB_ID
27#define XGIFB_ID 0x53495346 /* Identify myself with 'XGIF' */
28#endif
29
30typedef enum _XGI_CHIP_TYPE {
31 XGI_VGALegacy = 0,
32 XGI_300,
33 XGI_630,
34 XGI_730,
35 XGI_540,
36 XGI_315H,
37 XGI_315,
38 XGI_315PRO,
39 XGI_550,
40 XGI_640,
41 XGI_740,
42 XGI_650,
43 XGI_650M,
44 XGI_330 = 16,
45 XGI_660,
46 XGI_661,
47 XGI_760,
48 XG40 = 32,
49 XG41,
50 XG42,
51 XG45,
52 XG20 = 48,
53 XG21,
54 XG27,
55 MAX_XGI_CHIP
56} XGI_CHIP_TYPE;
57
58typedef enum _TVTYPE {
59 TVMODE_NTSC = 0,
60 TVMODE_PAL,
61 TVMODE_HIVISION,
62 TVTYPE_PALM, // vicki@030226
63 TVTYPE_PALN, // vicki@030226
64 TVTYPE_NTSCJ, // vicki@030226
65 TVMODE_TOTAL
66} XGI_TV_TYPE;
67
68
69typedef struct _XGIFB_INFO XGIfb_info;
70struct _XGIFB_INFO {
71
72unsigned long XGIfb_id;
73 int chip_id; /* PCI ID of detected chip */
74 int memory; /* video memory in KB which XGIfb manages */
75 int heapstart; /* heap start (= XGIfb "mem" argument) in KB */
76 unsigned char fbvidmode; /* current XGIfb mode */
77
78 unsigned char XGIfb_version;
79 unsigned char XGIfb_revision;
80 unsigned char XGIfb_patchlevel;
81
82 unsigned char XGIfb_caps; /* XGIfb capabilities */
83
84 int XGIfb_tqlen; /* turbo queue length (in KB) */
85
86 unsigned int XGIfb_pcibus; /* The card's PCI ID */
87 unsigned int XGIfb_pcislot;
88 unsigned int XGIfb_pcifunc;
89
90 unsigned char XGIfb_lcdpdc; /* PanelDelayCompensation */
91
92 unsigned char XGIfb_lcda; /* Detected status of LCDA for low res/text modes */
93
94 char reserved[235]; /* for future use */
95};
96
97
98
99
100typedef enum _TVPLUGTYPE { // vicki@030226
101// TVPLUG_Legacy = 0,
102// TVPLUG_COMPOSITE,
103// TVPLUG_SVIDEO,
104// TVPLUG_SCART,
105// TVPLUG_TOTAL
106 TVPLUG_UNKNOWN = 0,
107 TVPLUG_COMPOSITE = 1,
108 TVPLUG_SVIDEO = 2,
109 TVPLUG_COMPOSITE_AND_SVIDEO = 3,
110 TVPLUG_SCART = 4,
111 TVPLUG_YPBPR_525i = 5,
112 TVPLUG_YPBPR_525P = 6,
113 TVPLUG_YPBPR_750P = 7,
114 TVPLUG_YPBPR_1080i = 8,
115 TVPLUG_TOTAL
116} XGI_TV_PLUG;
117
118
119struct mode_info {
120 int bpp;
121 int xres;
122 int yres;
123 int v_xres;
124 int v_yres;
125 int org_x;
126 int org_y;
127 unsigned int vrate;
128};
129
130struct ap_data {
131 struct mode_info minfo;
132 unsigned long iobase;
133 unsigned int mem_size;
134 unsigned long disp_state;
135 XGI_CHIP_TYPE chip;
136 unsigned char hasVB;
137 XGI_TV_TYPE TV_type;
138 XGI_TV_PLUG TV_plug;
139 unsigned long version;
140 char reserved[256];
141};
142
143
144
145/* If changing this, vgatypes.h must also be changed (for X driver) */
146
147
148/*
149 * NOTE! The ioctl types used to be "size_t" by mistake, but were
150 * really meant to be __u32. Changed to "__u32" even though that
151 * changes the value on 64-bit architectures, because the value
152 * (with a 4-byte size) is also hardwired in vgatypes.h for user
153 * space exports. So "__u32" is actually more compatible, duh!
154 */
155#define XGIFB_GET_INFO _IOR('n',0xF8,__u32)
156#define XGIFB_GET_VBRSTATUS _IOR('n',0xF9,__u32)
157
158
159
160struct video_info{
161 int chip_id;
162 unsigned int video_size;
163 unsigned long video_base;
164 char * video_vbase;
165 unsigned long mmio_base;
166 char * mmio_vbase;
167 unsigned long vga_base;
168 unsigned long mtrr;
169 unsigned long heapstart;
170
171 int video_bpp;
172 int video_cmap_len;
173 int video_width;
174 int video_height;
175 int video_vwidth;
176 int video_vheight;
177 int org_x;
178 int org_y;
179 int video_linelength;
180 unsigned int refresh_rate;
181
182 unsigned long disp_state;
183 unsigned char hasVB;
184 unsigned char TV_type;
185 unsigned char TV_plug;
186
187 XGI_CHIP_TYPE chip;
188 unsigned char revision_id;
189
190 unsigned short DstColor;
191 unsigned long XGI310_AccelDepth;
192 unsigned long CommandReg;
193
194 spinlock_t lockaccel;
195
196 unsigned int pcibus;
197 unsigned int pcislot;
198 unsigned int pcifunc;
199
200 int accel;
201 unsigned short subsysvendor;
202 unsigned short subsysdevice;
203
204 char reserved[236];
205};
206
207
208extern struct video_info xgi_video_info;
209
210#ifdef __KERNEL__
211//extern void xgi_malloc(struct xgi_memreq *req);
212extern void xgi_free(unsigned long base);
213extern void xgi_dispinfo(struct ap_data *rec);
214#endif
215#endif
diff --git a/drivers/staging/xgifb/osdef.h b/drivers/staging/xgifb/osdef.h
new file mode 100644
index 000000000000..4bc7d3a7440c
--- /dev/null
+++ b/drivers/staging/xgifb/osdef.h
@@ -0,0 +1,153 @@
1#ifndef _OSDEF_H_
2#define _OSDEF_H_
3
4/* #define WINCE_HEADER*/
5/*#define WIN2000*/
6/* #define TC */
7#define LINUX_KERNEL
8/* #define LINUX_XF86 */
9
10/**********************************************************************/
11#ifdef LINUX_KERNEL
12//#include <linux/config.h>
13#endif
14
15
16/**********************************************************************/
17#ifdef TC
18#endif
19#ifdef WIN2000
20#endif
21#ifdef WINCE_HEADER
22#endif
23#ifdef LINUX_XF86
24#define LINUX
25#endif
26#ifdef LINUX_KERNEL
27#define LINUX
28#endif
29
30/**********************************************************************/
31#ifdef TC
32#define XGI_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize);
33#endif
34#ifdef WIN2000
35#define XGI_SetMemory(MemoryAddress,MemorySize,value) MemFill((PVOID) MemoryAddress,(ULONG) MemorySize,(UCHAR) value);
36#endif
37#ifdef WINCE_HEADER
38#define XGI_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize);
39#endif
40#ifdef LINUX_XF86
41#define XGI_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize)
42#endif
43#ifdef LINUX_KERNEL
44#define XGI_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize)
45#endif
46/**********************************************************************/
47
48/**********************************************************************/
49
50#ifdef TC
51#define XGI_MemoryCopy(Destination,Soruce,Length) memmove(Destination, Soruce, Length);
52#endif
53#ifdef WIN2000
54#define XGI_MemoryCopy(Destination,Soruce,Length) /*VideoPortMoveMemory((PUCHAR)Destination , Soruce,length);*/
55#endif
56#ifdef WINCE_HEADER
57#define XGI_MemoryCopy(Destination,Soruce,Length) memmove(Destination, Soruce, Length);
58#endif
59#ifdef LINUX_XF86
60#define XGI_MemoryCopy(Destination,Soruce,Length) memcpy(Destination,Soruce,Length)
61#endif
62#ifdef LINUX_KERNEL
63#define XGI_MemoryCopy(Destination,Soruce,Length) memcpy(Destination,Soruce,Length)
64#endif
65
66/**********************************************************************/
67
68#ifdef OutPortByte
69#undef OutPortByte
70#endif /* OutPortByte */
71
72#ifdef OutPortWord
73#undef OutPortWord
74#endif /* OutPortWord */
75
76#ifdef OutPortLong
77#undef OutPortLong
78#endif /* OutPortLong */
79
80#ifdef InPortByte
81#undef InPortByte
82#endif /* InPortByte */
83
84#ifdef InPortWord
85#undef InPortWord
86#endif /* InPortWord */
87
88#ifdef InPortLong
89#undef InPortLong
90#endif /* InPortLong */
91
92/**********************************************************************/
93/* TC */
94/**********************************************************************/
95
96#ifdef TC
97#define OutPortByte(p,v) outp((unsigned short)(p),(unsigned char)(v))
98#define OutPortWord(p,v) outp((unsigned short)(p),(unsigned short)(v))
99#define OutPortLong(p,v) outp((unsigned short)(p),(unsigned long)(v))
100#define InPortByte(p) inp((unsigned short)(p))
101#define InPortWord(p) inp((unsigned short)(p))
102#define InPortLong(p) ((inp((unsigned short)(p+2))<<16) | inp((unsigned short)(p)))
103#endif
104
105/**********************************************************************/
106/* LINUX XF86 */
107/**********************************************************************/
108
109#ifdef LINUX_XF86
110#define OutPortByte(p,v) outb((CARD16)(p),(CARD8)(v))
111#define OutPortWord(p,v) outw((CARD16)(p),(CARD16)(v))
112#define OutPortLong(p,v) outl((CARD16)(p),(CARD32)(v))
113#define InPortByte(p) inb((CARD16)(p))
114#define InPortWord(p) inw((CARD16)(p))
115#define InPortLong(p) inl((CARD16)(p))
116#endif
117
118#ifdef LINUX_KERNEL
119#define OutPortByte(p,v) outb((u8)(v),(p))
120#define OutPortWord(p,v) outw((u16)(v),(p))
121#define OutPortLong(p,v) outl((u32)(v),(p))
122#define InPortByte(p) inb(p)
123#define InPortWord(p) inw(p)
124#define InPortLong(p) inl(p)
125#endif
126
127/**********************************************************************/
128/* WIN 2000 */
129/**********************************************************************/
130
131#ifdef WIN2000
132#define OutPortByte(p,v) VideoPortWritePortUchar ((PUCHAR) (p), (UCHAR) (v))
133#define OutPortWord(p,v) VideoPortWritePortUshort((PUSHORT) (p), (USHORT) (v))
134#define OutPortLong(p,v) VideoPortWritePortUlong ((PULONG) (p), (ULONG) (v))
135#define InPortByte(p) VideoPortReadPortUchar ((PUCHAR) (p))
136#define InPortWord(p) VideoPortReadPortUshort ((PUSHORT) (p))
137#define InPortLong(p) VideoPortReadPortUlong ((PULONG) (p))
138#endif
139
140
141/**********************************************************************/
142/* WIN CE */
143/**********************************************************************/
144
145#ifdef WINCE_HEADER
146#define OutPortByte(p,v) WRITE_PORT_UCHAR ((PUCHAR) (p), (UCHAR) (v))
147#define OutPortWord(p,v) WRITE_PORT_USHORT((PUSHORT) (p), (USHORT) (v))
148#define OutPortLong(p,v) WRITE_PORT_ULONG ((PULONG) (p), (ULONG) (v))
149#define InPortByte(p) READ_PORT_UCHAR ((PUCHAR) (p))
150#define InPortWord(p) READ_PORT_USHORT ((PUSHORT) (p))
151#define InPortLong(p) READ_PORT_ULONG ((PULONG) (p))
152#endif
153#endif // _OSDEF_H_
diff --git a/drivers/staging/xgifb/vb_def.h b/drivers/staging/xgifb/vb_def.h
new file mode 100644
index 000000000000..17a7ada4926e
--- /dev/null
+++ b/drivers/staging/xgifb/vb_def.h
@@ -0,0 +1,1017 @@
1/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/xgi/initdef.h,v 1.4 2000/12/02 01:16:17 dawes Exp $ */
2#ifndef _INITDEF_
3#define _INITDEF_
4
5#ifndef NewScratch
6#define NewScratch
7#endif
8/* shampoo */
9#ifdef LINUX_KERNEL
10#define SEQ_ADDRESS_PORT 0x0014
11#define SEQ_DATA_PORT 0x0015
12#define MISC_OUTPUT_REG_READ_PORT 0x001C
13#define MISC_OUTPUT_REG_WRITE_PORT 0x0012
14#define GRAPH_DATA_PORT 0x1F
15#define GRAPH_ADDRESS_PORT 0x1E
16#define XGI_MASK_DUAL_CHIP 0x04 /* SR3A */
17#define CRTC_ADDRESS_PORT_COLOR 0x0024
18#define VIDEO_SUBSYSTEM_ENABLE_PORT 0x0013
19#define PCI_COMMAND 0x04
20#endif
21/* ~shampoo */
22
23
24#define VB_XGI301 0x0001 /*301b*/
25#define VB_XGI301B 0x0002
26#define VB_XGI302B 0x0004
27#define VB_XGI301LV 0x0008 /*301lv*/
28#define VB_XGI302LV 0x0010
29#define VB_XGI301C 0x0020 /* for 301C */
30#define VB_NoLCD 0x8000
31/*end 301b*/
32
33#define VB_YPbPrInfo 0x07 /*301lv*/
34#define VB_YPbPr525i 0x00
35#define VB_YPbPr525p 0x01
36#define VB_YPbPr750p 0x02
37#define VB_YPbPr1080i 0x03
38
39/* #define CRT1Len 17 */
40#define LVDSCRT1Len 15
41#define CHTVRegDataLen 5
42
43/* #define ModeInfoFlag 0x07 */
44/* #define IsTextMode 0x07 */
45/* #define ModeText 0x00 */
46/* #define ModeCGA 0x01 */
47/* #define ModeEGA 0x02 */
48/* #define ModeVGA 0x03 */
49/* #define Mode15Bpp 0x04 */
50/* #define Mode16Bpp 0x05 */
51/* #define Mode24Bpp 0x06 */
52/* #define Mode32Bpp 0x07 */
53
54/* #define DACInfoFlag 0x18 */
55/* #define MemoryInfoFlag 0x1E0 */
56/* #define MemorySizeShift 0x05 */
57
58#define Charx8Dot 0x0200
59#define LineCompareOff 0x0400
60#define CRT2Mode 0x0800
61#define HalfDCLK 0x1000
62#define NoSupportSimuTV 0x2000
63#define DoubleScanMode 0x8000
64
65#define SupportAllCRT2 0x0078
66#define SupportTV 0x0008
67#define SupportHiVisionTV 0x0010
68#define SupportLCD 0x0020
69#define SupportRAMDAC2 0x0040
70#define NoSupportTV 0x0070
71#define NoSupportHiVisionTV 0x0060
72#define NoSupportLCD 0x0058
73#define SupportCHTV 0x0800
74#define SupportCRT2in301C 0x0100 /* for 301C */
75#define SupportTV1024 0x0800 /*301b*/
76#define SupportYPbPr 0x1000 /*301lv*/
77#define InterlaceMode 0x0080
78#define SyncPP 0x0000
79#define SyncPN 0x4000
80#define SyncNP 0x8000
81/* #define SyncNN 0xc000 */
82#define ECLKindex0 0x0000
83#define ECLKindex1 0x0100
84#define ECLKindex2 0x0200
85#define ECLKindex3 0x0300
86#define ECLKindex4 0x0400
87
88#define SetSimuScanMode 0x0001
89#define SwitchToCRT2 0x0002
90/* #define SetCRT2ToTV 0x009C */
91#define SetCRT2ToAVIDEO 0x0004
92#define SetCRT2ToSVIDEO 0x0008
93#define SetCRT2ToSCART 0x0010
94#define SetCRT2ToLCD 0x0020
95#define SetCRT2ToRAMDAC 0x0040
96#define SetCRT2ToHiVisionTV 0x0080
97#define SetNTSCTV 0x0000
98/* #define SetPALTV 0x0100 */
99#define SetInSlaveMode 0x0200
100#define SetNotSimuMode 0x0400
101#define SetNotSimuTVMode 0x0400
102#define SetDispDevSwitch 0x0800
103#define LoadDACFlag 0x1000
104#define DisableCRT2Display 0x2000
105#define DriverMode 0x4000
106#define HotKeySwitch 0x8000
107#define SetCHTVOverScan 0x8000
108/* #define SetCRT2ToLCDA 0x8000 301b */
109#define PanelRGB18Bit 0x0100
110#define PanelRGB24Bit 0x0000
111
112#define TVOverScan 0x10
113#define TVOverScanShift 4
114#define ClearBufferFlag 0x20
115#define EnableDualEdge 0x01 /*301b*/
116#define SetToLCDA 0x02
117
118#define YPbPrModeInfo 0x38
119/* #define YPbPrMode525i 0x00 */
120/* #define YPbPrMode525p 0x08 */
121/* #define YPbPrMode750p 0x10 */
122/* #define YPbPrMode1080i 0x18 */
123
124#define SetSCARTOutput 0x01
125#define BoardTVType 0x02
126#define EnablePALMN 0x40
127/* #define ProgrammingCRT2 0x01 */
128/* #define TVSimuMode 0x02 */
129/* #define RPLLDIV2XO 0x04 */
130/* #define LCDVESATiming 0x08 */
131/* #define EnableLVDSDDA 0x10 */
132#define SetDispDevSwitchFlag 0x20
133#define CheckWinDos 0x40
134#define SetJDOSMode 0x80
135
136#define Panel320x480 0x07/*fstn*/
137/* [ycchen] 02/12/03 Modify for Multi-Sync. LCD Support */
138#define PanelResInfo 0x1F /* CR36 Panel Type/LCDResInfo */
139#define PanelRefInfo 0x60
140#define Panel800x600 0x01
141#define Panel1024x768 0x02
142#define Panel1024x768x75 0x22
143#define Panel1280x1024 0x03
144#define Panel1280x1024x75 0x23
145#define Panel640x480 0x04
146#define Panel1024x600 0x05
147#define Panel1152x864 0x06
148#define Panel1280x960 0x07
149#define Panel1152x768 0x08
150#define Panel1400x1050 0x09
151#define Panel1280x768 0x0A
152#define Panel1600x1200 0x0B
153
154#define PanelRef60Hz 0x00
155#define PanelRef75Hz 0x20
156#define LCDRGB18Bit 0x01
157
158#define ExtChipTrumpion 0x06
159#define ExtChipCH7005 0x08
160#define ExtChipMitacTV 0x0a
161#define LCDNonExpanding 0x10
162#define LCDNonExpandingShift 4
163#define LCDSync 0x20
164#define LCDSyncBit 0xe0
165#define LCDSyncShift 6
166
167/* #define DDC2DelayTime 300 */
168
169#define CRT2DisplayFlag 0x2000
170/* #define LCDDataLen 8 */
171/* #define HiTVDataLen 12 */
172/* #define TVDataLen 16 */
173/* #define SetPALTV 0x0100 */
174#define HalfDCLK 0x1000
175#define NTSCHT 1716
176#define NTSCVT 525
177#define PALHT 1728
178#define PALVT 625
179#define StHiTVHT 892
180#define StHiTVVT 1126
181#define StHiTextTVHT 1000
182#define StHiTextTVVT 1126
183#define ExtHiTVHT 2100
184#define ExtHiTVVT 1125
185
186#define St750pTVHT 1716
187#define St750pTVVT 525
188#define Ext750pTVHT 1716
189#define Ext750pTVVT 525
190#define St525pTVHT 1716
191#define St525pTVVT 525
192#define Ext525pTVHT 1716
193#define Ext525pTVVT 525
194#define St525iTVHT 1716
195#define St525iTVVT 525
196#define Ext525iTVHT 1716
197#define Ext525iTVVT 525
198
199#define VCLKStartFreq 25
200#define SoftDramType 0x80
201#define VCLK40 0x04
202
203#define VCLK162 0x21
204
205#define LCDRGB18Bit 0x01
206#define LoadDACFlag 0x1000
207#define AfterLockCRT2 0x4000
208#define SetCRT2ToAVIDEO 0x0004
209#define SetCRT2ToSCART 0x0010
210#define Ext2StructSize 5
211
212
213#define YPbPr525iVCLK 0x03B
214#define YPbPr525iVCLK_2 0x03A
215
216#define SwitchToCRT2 0x0002
217/* #define LCDVESATiming 0x08 */
218#define SetSCARTOutput 0x01
219#define AVIDEOSense 0x01
220#define SVIDEOSense 0x02
221#define SCARTSense 0x04
222#define LCDSense 0x08
223#define Monitor1Sense 0x20
224#define Monitor2Sense 0x10
225#define HiTVSense 0x40
226#define BoardTVType 0x02
227#define HotPlugFunction 0x08
228#define StStructSize 0x06
229
230
231#define XGI_CRT2_PORT_00 0x00 - 0x030
232#define XGI_CRT2_PORT_04 0x04 - 0x030
233#define XGI_CRT2_PORT_10 0x10 - 0x30
234#define XGI_CRT2_PORT_12 0x12 - 0x30
235#define XGI_CRT2_PORT_14 0x14 - 0x30
236
237
238#define LCDNonExpanding 0x10
239#define ADR_CRT2PtrData 0x20E
240#define offset_Zurac 0x210
241#define ADR_LVDSDesPtrData 0x212
242#define ADR_LVDSCRT1DataPtr 0x214
243#define ADR_CHTVVCLKPtr 0x216
244#define ADR_CHTVRegDataPtr 0x218
245
246#define LVDSDataLen 6
247/* #define EnableLVDSDDA 0x10 */
248/* #define LVDSDesDataLen 3 */
249#define ActiveNonExpanding 0x40
250#define ActiveNonExpandingShift 6
251/* #define ActivePAL 0x20 */
252#define ActivePALShift 5
253/* #define ModeSwitchStatus 0x0F */
254#define SoftTVType 0x40
255#define SoftSettingAddr 0x52
256#define ModeSettingAddr 0x53
257
258/* #define SelectCRT1Rate 0x4 */
259
260#define _PanelType00 0x00
261#define _PanelType01 0x08
262#define _PanelType02 0x10
263#define _PanelType03 0x18
264#define _PanelType04 0x20
265#define _PanelType05 0x28
266#define _PanelType06 0x30
267#define _PanelType07 0x38
268#define _PanelType08 0x40
269#define _PanelType09 0x48
270#define _PanelType0A 0x50
271#define _PanelType0B 0x58
272#define _PanelType0C 0x60
273#define _PanelType0D 0x68
274#define _PanelType0E 0x70
275#define _PanelType0F 0x78
276
277
278#define PRIMARY_VGA 0 /* 1: XGI is primary vga 0:XGI is secondary vga */
279#define BIOSIDCodeAddr 0x235
280#define OEMUtilIDCodeAddr 0x237
281#define VBModeIDTableAddr 0x239
282#define OEMTVPtrAddr 0x241
283#define PhaseTableAddr 0x243
284#define NTSCFilterTableAddr 0x245
285#define PALFilterTableAddr 0x247
286#define OEMLCDPtr_1Addr 0x249
287#define OEMLCDPtr_2Addr 0x24B
288#define LCDHPosTable_1Addr 0x24D
289#define LCDHPosTable_2Addr 0x24F
290#define LCDVPosTable_1Addr 0x251
291#define LCDVPosTable_2Addr 0x253
292#define OEMLCDPIDTableAddr 0x255
293
294#define VBModeStructSize 5
295#define PhaseTableSize 4
296#define FilterTableSize 4
297#define LCDHPosTableSize 7
298#define LCDVPosTableSize 5
299#define OEMLVDSPIDTableSize 4
300#define LVDSHPosTableSize 4
301#define LVDSVPosTableSize 6
302
303#define VB_ModeID 0
304#define VB_TVTableIndex 1
305#define VB_LCDTableIndex 2
306#define VB_LCDHIndex 3
307#define VB_LCDVIndex 4
308
309#define OEMLCDEnable 0x0001
310#define OEMLCDDelayEnable 0x0002
311#define OEMLCDPOSEnable 0x0004
312#define OEMTVEnable 0x0100
313#define OEMTVDelayEnable 0x0200
314#define OEMTVFlickerEnable 0x0400
315#define OEMTVPhaseEnable 0x0800
316#define OEMTVFilterEnable 0x1000
317
318#define OEMLCDPanelIDSupport 0x0080
319
320/* #define LCDVESATiming 0x0001 //LCD Info CR37 */
321/* #define EnableLVDSDDA 0x0002 */
322#define EnableScalingLCD 0x0008
323#define SetPWDEnable 0x0004
324#define SetLCDtoNonExpanding 0x0010
325/* #define SetLCDPolarity 0x00E0 */
326#define SetLCDDualLink 0x0100
327#define SetLCDLowResolution 0x0200
328#define SetLCDStdMode 0x0400
329#define SetTVStdMode 0x0200
330#define SetTVLowResolution 0x0400
331/* =============================================================
332 for 310
333============================================================== */
334#define SoftDRAMType 0x80
335#define SoftSetting_OFFSET 0x52
336#define SR07_OFFSET 0x7C
337#define SR15_OFFSET 0x7D
338#define SR16_OFFSET 0x81
339#define SR17_OFFSET 0x85
340#define SR19_OFFSET 0x8D
341#define SR1F_OFFSET 0x99
342#define SR21_OFFSET 0x9A
343#define SR22_OFFSET 0x9B
344#define SR23_OFFSET 0x9C
345#define SR24_OFFSET 0x9D
346#define SR25_OFFSET 0x9E
347#define SR31_OFFSET 0x9F
348#define SR32_OFFSET 0xA0
349#define SR33_OFFSET 0xA1
350
351#define CR40_OFFSET 0xA2
352#define SR25_1_OFFSET 0xF6
353#define CR49_OFFSET 0xF7
354
355#define VB310Data_1_2_Offset 0xB6
356#define VB310Data_4_D_Offset 0xB7
357#define VB310Data_4_E_Offset 0xB8
358#define VB310Data_4_10_Offset 0xBB
359
360#define RGBSenseDataOffset 0xBD
361#define YCSenseDataOffset 0xBF
362#define VideoSenseDataOffset 0xC1
363#define OutputSelectOffset 0xF3
364
365#define ECLK_MCLK_DISTANCE 0x14
366#define VBIOSTablePointerStart 0x200
367#define StandTablePtrOffset VBIOSTablePointerStart+0x02
368#define EModeIDTablePtrOffset VBIOSTablePointerStart+0x04
369#define CRT1TablePtrOffset VBIOSTablePointerStart+0x06
370#define ScreenOffsetPtrOffset VBIOSTablePointerStart+0x08
371#define VCLKDataPtrOffset VBIOSTablePointerStart+0x0A
372#define MCLKDataPtrOffset VBIOSTablePointerStart+0x0E
373#define CRT2PtrDataPtrOffset VBIOSTablePointerStart+0x10
374#define TVAntiFlickPtrOffset VBIOSTablePointerStart+0x12
375#define TVDelayPtr1Offset VBIOSTablePointerStart+0x14
376#define TVPhaseIncrPtr1Offset VBIOSTablePointerStart+0x16
377#define TVYFilterPtr1Offset VBIOSTablePointerStart+0x18
378#define LCDDelayPtr1Offset VBIOSTablePointerStart+0x20
379#define TVEdgePtr1Offset VBIOSTablePointerStart+0x24
380#define CRT2Delay1Offset VBIOSTablePointerStart+0x28
381#define LCDDataDesOffset VBIOSTablePointerStart-0x02
382#define LCDDataPtrOffset VBIOSTablePointerStart+0x2A
383#define LCDDesDataPtrOffset VBIOSTablePointerStart+0x2C
384#define LCDDataList VBIOSTablePointerStart+0x22 /* add for GetLCDPtr */
385#define TVDataList VBIOSTablePointerStart+0x36 /* add for GetTVPtr */
386/* */
387/* Modify from 310.inc */
388/* */
389/* */
390
391
392#define ShowMsgFlag 0x20 /* SoftSetting */
393#define ShowVESAFlag 0x10
394#define HotPlugFunction 0x08
395#define ModeSoftSetting 0x04
396#define TVSoftSetting 0x02
397#define LCDSoftSetting 0x01
398
399#define GatingCRTinLCDA 0x10
400#define SetHiTVOutput 0x08
401#define SetYPbPrOutput 0x04
402#define BoardTVType 0x02
403#define SetSCARTOutput 0x01
404
405#define ModeSettingYPbPr 0x02 /* TVModeSetting, Others as same as CR30 */
406
407/* TVModeSetting same as CR35 */
408
409/* LCDModeSetting same as CR37 */
410
411#define EnableNewTVFont 0x10 /* MiscCapability */
412
413#define EnableLCDOutput 0x80 /* LCDCfgSetting */
414
415#define SoftDRAMType 0x80 /* DRAMSetting */
416#define SoftDRAMConfig 0x40
417#define MosSelDRAMType 0x20
418#define SDRAM 000h
419#define SGRAM 0x01
420#define ESDRAM 0x02
421
422#define EnableAGPCfgSetting 0x01 /* AGPCfgSetting */
423
424/* ---------------- SetMode Stack */
425#define CRT1Len 15
426#define VCLKLen 4
427#define DefThreshold 0x0100
428#define ExtRegsSize (57+8+37+70+63+28+768+1)/64+1
429
430#define VGA_XGI315 0x0001 /* VGA Type Info */
431#define VGA_SNewis315e 0x0002 /* 315 series */
432#define VGA_XGI550 0x0004
433#define VGA_XGI640 0x0008
434#define VGA_XGI740 0x0010
435#define VGA_XGI650 0x0020
436#define VGA_XGI650M 0x0040
437#define VGA_XGI651 0x0080
438#define VGA_XGI340 0x0001 /* 340 series */
439#define VGA_XGI330 0x0001 /* 330 series */
440#define VGA_XGI660 0x0001 /* 660 series */
441
442#define VB_XGI301 0x0001 /* VB Type Info */
443#define VB_XGI301B 0x0002 /* 301 series */
444#define VB_XGI302B 0x0004
445#define VB_NoLCD 0x8000
446#define VB_XGI301LV 0x0008
447#define VB_XGI302LV 0x0010
448#define VB_LVDS_NS 0x0001 /* 3rd party chip */
449#define VB_CH7017 0x0002
450#define VB_CH7007 0x0080 /* [Billy] 07/05/03 */
451/* #define VB_LVDS_SI 0x0004 */
452
453#define ModeInfoFlag 0x0007
454#define IsTextMode 0x0007
455#define ModeText 0x0000
456#define ModeCGA 0x0001
457#define ModeEGA 0x0002 /* 16 colors mode */
458#define ModeVGA 0x0003 /* 256 colors mode */
459#define Mode15Bpp 0x0004 /* 15 Bpp Color Mode */
460#define Mode16Bpp 0x0005 /* 16 Bpp Color Mode */
461#define Mode24Bpp 0x0006 /* 24 Bpp Color Mode */
462#define Mode32Bpp 0x0007 /* 32 Bpp Color Mode */
463
464#define DACInfoFlag 0x0018
465#define MONODAC 0x0000
466#define CGADAC 0x0008
467#define EGADAC 0x0010
468#define VGADAC 0x0018
469
470#define MemoryInfoFlag 0x01e0
471#define MemorySizeShift 5
472#define Need1MSize 0x0000
473#define Need2MSize 0x0020
474#define Need4MSize 0x0060
475#define Need8MSize 0x00e0
476#define Need16MSize 0x01e0
477
478#define Charx8Dot 0x0200
479#define LineCompareOff 0x0400
480#define CRT2Mode 0x0800
481#define HalfDCLK 0x1000
482#define NoSupportSimuTV 0x2000
483#define DoubleScanMode 0x8000
484
485/* -------------- Ext_InfoFlag */
486#define SupportModeInfo 0x0007
487#define Support256 0x0003
488#define Support15Bpp 0x0004
489#define Support16Bpp 0x0005
490#define Support24Bpp 0x0006
491#define Support32Bpp 0x0007
492
493#define SupportAllCRT2 0x0078
494#define SupportTV 0x0008
495#define SupportHiVisionTV 0x0010
496#define SupportLCD 0x0020
497#define SupportRAMDAC2 0x0040
498#define NoSupportTV 0x0070
499#define NoSupportHiVisionTV 0x0060
500#define NoSupportLCD 0x0058
501#define SupportTV1024 0x0800 /* 301btest */
502#define SupportYPbPr 0x1000 /* 301lv */
503#define InterlaceMode 0x0080
504#define SyncPP 0x0000
505#define SyncPN 0x4000
506#define SyncNP 0x8000
507#define SyncNN 0xC000
508
509/* -------------- SetMode Stack/Scratch */
510#define SetSimuScanMode 0x0001 /* VBInfo/CR30 & CR31 */
511#define SwitchToCRT2 0x0002
512#define SetCRT2ToTV1 0x009C
513#define SetCRT2ToTV 0x089C
514#define SetCRT2ToAVIDEO 0x0004
515#define SetCRT2ToSVIDEO 0x0008
516#define SetCRT2ToSCART 0x0010
517#define SetCRT2ToLCD 0x0020
518#define SetCRT2ToRAMDAC 0x0040
519#define SetCRT2ToHiVisionTV 0x0080
520#define SetCRT2ToLCDA 0x0100
521#define SetInSlaveMode 0x0200
522#define SetNotSimuMode 0x0400
523#define HKEventMode 0x0800
524#define SetCRT2ToYPbPr 0x0800
525#define LoadDACFlag 0x1000
526#define DisableCRT2Display 0x2000
527#define DriverMode 0x4000
528#define SetCRT2ToDualEdge 0x8000
529#define HotKeySwitch 0x8000
530
531#define ProgrammingCRT2 0x0001 /* Set Flag */
532#define EnableVCMode 0x0002
533#define SetHKEventMode 0x0004
534#define ReserveTVOption 0x0008
535#define DisableRelocateIO 0x0010
536#define Win9xDOSMode 0x0020
537#define JDOSMode 0x0040
538/* #define SetWin9xforJap 0x0080 // not used now */
539/* #define SetWin9xforKorea 0x0100 // not used now */
540#define GatingCRT 0x0800
541#define DisableChB 0x1000
542#define EnableChB 0x2000
543#define DisableChA 0x4000
544#define EnableChA 0x8000
545
546#define SetNTSCTV 0x0000 /* TV Info */
547#define SetPALTV 0x0001
548#define SetNTSCJ 0x0002
549#define SetPALMTV 0x0004
550#define SetPALNTV 0x0008
551#define SetCHTVUnderScan 0x0000
552/* #define SetCHTVOverScan 0x0010 */
553#define SetYPbPrMode525i 0x0020
554#define SetYPbPrMode525p 0x0040
555#define SetYPbPrMode750p 0x0080
556#define SetYPbPrMode1080i 0x0100
557#define SetTVStdMode 0x0200
558#define SetTVLowResolution 0x0400
559#define SetTVSimuMode 0x0800
560#define TVSimuMode 0x0800
561#define RPLLDIV2XO 0x1000
562#define NTSC1024x768 0x2000
563#define SetTVLockMode 0x4000
564
565#define LCDVESATiming 0x0001 /* LCD Info/CR37 */
566#define EnableLVDSDDA 0x0002
567#define EnableScalingLCD 0x0008
568#define SetPWDEnable 0x0004
569#define SetLCDtoNonExpanding 0x0010
570#define SetLCDPolarity 0x00e0
571#define SetLCDDualLink 0x0100
572#define SetLCDLowResolution 0x0200
573#define SetLCDStdMode 0x0400
574
575#define DefaultLCDCap 0x80ea /* LCD Capability shampoo */
576#define RLVDSDHL00 0x0000
577#define RLVDSDHL01 0x0001
578#define RLVDSDHL10 0x0002 /* default */
579#define RLVDSDHL11 0x0003
580#define EnableLCD24bpp 0x0004 /* default */
581#define DisableLCD24bpp 0x0000
582#define RLVDSClkSFT0 0x0000
583#define RLVDSClkSFT1 0x0008 /* default */
584#define EnableLVDSDCBal 0x0010
585#define DisableLVDSDCBal 0x0000 /* default */
586#define SinglePolarity 0x0020 /* default */
587#define MultiPolarity 0x0000
588#define LCDPolarity 0x00c0 /* default: SyncNN */
589#define LCDSingleLink 0x0000 /* default */
590#define LCDDualLink 0x0100
591#define EnableSpectrum 0x0200
592#define DisableSpectrum 0x0000 /* default */
593#define PWDEnable 0x0400
594#define PWDDisable 0x0000 /* default */
595#define PWMEnable 0x0800
596#define PWMDisable 0x0000 /* default */
597#define EnableVBCLKDRVLOW 0x4000
598#define EnableVBCLKDRVHigh 0x0000 /* default */
599#define EnablePLLSPLOW 0x8000
600#define EnablePLLSPHigh 0x0000 /* default */
601
602#define LCDBToA 0x20 /* LCD SetFlag */
603#define StLCDBToA 0x40
604#define LockLCDBToA 0x80
605#define LCDToFull 0x10
606#define AVIDEOSense 0x01 /* CR32 */
607#define SVIDEOSense 0x02
608#define SCARTSense 0x04
609#define LCDSense 0x08
610#define Monitor2Sense 0x10
611#define Monitor1Sense 0x20
612#define HiTVSense 0x40
613
614#ifdef NewScratch
615#define YPbPrSense 0x80 /* NEW SCRATCH */
616#endif
617
618#define TVSense 0xc7
619
620#define TVOverScan 0x10 /* CR35 */
621#define TVOverScanShift 4
622
623#ifdef NewScratch
624#define NTSCMode 0x00
625#define PALMode 0x00
626#define NTSCJMode 0x02
627#define PALMNMode 0x0c
628#define YPbPrMode 0xe0
629#define YPbPrMode525i 0x00
630#define YPbPrMode525p 0x20
631#define YPbPrMode750p 0x40
632#define YPbPrMode1080i 0x60
633#else /* Old Scratch */
634#define ClearBufferFlag 0x20
635#endif
636
637
638#define LCDRGB18Bit 0x01 /* CR37 */
639#define LCDNonExpanding 0x10
640#define LCDNonExpandingShift 4
641#define LCDSync 0x20
642#define LCDSyncBit 0xe0 /* H/V polarity & sync ID */
643#define LCDSyncShift 6
644
645#ifdef NewScratch
646#define ScalingLCD 0x08
647#else /* Old Scratch */
648#define ExtChipType 0x0e
649#define ExtChip301 0x02
650#define ExtChipLVDS 0x04
651#define ExtChipCH7019 0x06
652#define ScalingLCD 0x10
653#endif
654
655#define EnableDualEdge 0x01 /* CR38 */
656#define SetToLCDA 0x02
657#ifdef NewScratch
658#define SetYPbPr 0x04
659#define DisableChannelA 0x08
660#define DisableChannelB 0x10
661#define ExtChipType 0xe0
662#define ExtChip301 0x20
663#define ExtChipLVDS 0x40
664#define ExtChipCH7019 0x60
665#else /* Old Scratch */
666#define YPbPrSense 0x04
667#define SetYPbPr 0x08
668#define YPbPrMode 0x30
669#define YPbPrMode525i 0x00
670#define YPbPrMode525p 0x10
671#define YPbPrMode750p 0x20
672#define YPbPrMode1080i 0x30
673#define PALMNMode 0xc0
674#endif
675
676#define BacklightControlBit 0x01 /* CR3A */
677#define Win9xforJap 0x40
678#define Win9xforKorea 0x80
679
680#define ForceMDBits 0x07 /* CR3B */
681#define ForceMD_JDOS 0x00
682#define ForceMD_640x400T 0x01
683#define ForceMD_640x350T 0x02
684#define ForceMD_720x400T 0x03
685#define ForceMD_640x480E 0x04
686#define ForceMD_640x400E 0x05
687#define ForceP1Bit 0x10
688#define ForceP2Bit 0x20
689#define EnableForceMDinBIOS 0x40
690#define EnableForceMDinDrv 0x80
691
692#ifdef NewScratch /* New Scratch */
693/* ---------------------- VUMA Information */
694#define LCDSettingFromCMOS 0x04 /* CR3C */
695#define TVSettingFromCMOS 0x08
696#define DisplayDeviceFromCMOS 0x10
697#define HKSupportInSBIOS 0x20
698#define OSDSupportInSBIOS 0x40
699#define DisableLogo 0x80
700
701/* ---------------------- HK Evnet Definition */
702#define HKEvent 0x0f /* CR3D */
703#define HK_ModeSwitch 0x01
704#define HK_Expanding 0x02
705#define HK_OverScan 0x03
706#define HK_Brightness 0x04
707#define HK_Contrast 0x05
708#define HK_Mute 0x06
709#define HK_Volume 0x07
710#define ModeSwitchStatus 0xf0
711#define ActiveCRT1 0x10
712#define ActiveLCD 0x0020
713#define ActiveTV 0x40
714#define ActiveCRT2 0x80
715
716#define TVSwitchStatus 0x1f /* CR3E */
717#define ActiveAVideo 0x01
718#define ActiveSVideo 0x02
719#define ActiveSCART 0x04
720#define ActiveHiTV 0x08
721#define ActiveYPbPr 0x10
722
723#define EnableHKEvent 0x01 /* CR3F */
724#define EnableOSDEvent 0x02
725#define StartOSDEvent 0x04
726#define IgnoreHKEvent 0x08
727#define IgnoreOSDEvent 0x10
728#else /* Old Scratch */
729#define OSD_SBIOS 0x02 /* SR17 */
730#define DisableLogo 0x04
731#define SelectKDOS 0x08
732#define KorWinMode 0x10
733#define KorMode3Bit 0x0020
734#define PSCCtrlBit 0x40
735#define NPSCCtrlBitShift 6
736#define BlueScreenBit 0x80
737
738#define HKEvent 0x0f /* CR79 */
739#define HK_ModeSwitch 0x01
740#define HK_Expanding 0x02
741#define HK_OverScan 0x03
742#define HK_Brightness 0x04
743#define HK_Contrast 0x05
744#define HK_Mute 0x06
745#define HK_Volume 0x07
746#define ActivePAL 0x0020
747#define ActivePALShift 5
748#define ActiveNonExpanding 0x40
749#define ActiveNonExpandingShift 6
750#define ActiveOverScan 0x80
751#define ActiveOverScanShift 7
752
753#define ModeSwitchStatus 0x0b /* SR15 */
754#define ActiveCRT1 0x01
755#define ActiveLCD 0x02
756#define ActiveCRT2 0x08
757
758#define TVSwitchStatus 0xf0 /* SR16 */
759#define TVConfigShift 3
760#define ActiveTV 0x01
761#define ActiveYPbPr 0x04
762#define ActiveAVideo 0x10
763#define ActiveSVideo 0x0020
764#define ActiveSCART 0x40
765#define ActiveHiTV 0x80
766
767#define EnableHKEvent 0x01 /* CR7A */
768#define EnableOSDEvent 0x02
769#define StartOSDEvent 0x04
770#define CMOSSupport 0x08
771#define HotKeySupport 0x10
772#define IngoreHKOSDEvent 0x20
773#endif
774
775/* //------------- Misc. Definition */
776#define SelectCRT1Rate 00h
777/* #define SelectCRT2Rate 04h */
778
779#define DDC1DelayTime 1000
780#ifdef TRUMPION
781#define DDC2DelayTime 15
782#else
783#define DDC2DelayTime 150
784#endif
785
786#define R_FACTOR 04Dh
787#define G_FACTOR 097h
788#define B_FACTOR 01Ch
789/* --------------------------------------------------------- */
790/* translated from asm code 301def.h */
791/* */
792/* --------------------------------------------------------- */
793#define LCDDataLen 8
794#define HiTVDataLen 12
795#define TVDataLen 12
796#define LVDSCRT1Len_H 8
797#define LVDSCRT1Len_V 7
798#define LVDSDataLen 6
799#define LVDSDesDataLen 6
800#define LCDDesDataLen 6
801#define LVDSDesDataLen2 8
802#define LCDDesDataLen2 8
803#define CHTVRegLen 16
804#define CHLVRegLen 12
805
806#define StHiTVHT 892
807#define StHiTVVT 1126
808#define StHiTextTVHT 1000
809#define StHiTextTVVT 1126
810#define ExtHiTVHT 2100
811#define ExtHiTVVT 1125
812#define NTSCHT 1716
813#define NTSCVT 525
814#define NTSC1024x768HT 1908
815#define NTSC1024x768VT 525
816#define PALHT 1728
817#define PALVT 625
818
819#define YPbPrTV525iHT 1716 /* YPbPr */
820#define YPbPrTV525iVT 525
821#define YPbPrTV525pHT 1716
822#define YPbPrTV525pVT 525
823#define YPbPrTV750pHT 1650
824#define YPbPrTV750pVT 750
825
826#define CRT2VCLKSel 0xc0
827
828#define CRT2Delay1 0x04 /* XGI301 */
829#define CRT2Delay2 0x0A /* 301B,302 */
830
831
832#define VCLK25_175 0x00
833#define VCLK28_322 0x01
834#define VCLK31_5 0x02
835#define VCLK36 0x03
836#define VCLK40 0x04
837#define VCLK43_163 0x05
838#define VCLK44_9 0x06
839#define VCLK49_5 0x07
840#define VCLK50 0x08
841#define VCLK52_406 0x09
842#define VCLK56_25 0x0A
843#define VCLK65 0x0B
844#define VCLK67_765 0x0C
845#define VCLK68_179 0x0D
846#define VCLK72_852 0x0E
847#define VCLK75 0x0F
848#define VCLK75_8 0x10
849#define VCLK78_75 0x11
850#define VCLK79_411 0x12
851#define VCLK83_95 0x13
852#define VCLK84_8 0x14
853#define VCLK86_6 0x15
854#define VCLK94_5 0x16
855#define VCLK104_998 0x17
856#define VCLK105_882 0x18
857#define VCLK108_2 0x19
858#define VCLK109_175 0x1A
859#define VCLK113_309 0x1B
860#define VCLK116_406 0x1C
861#define VCLK132_258 0x1D
862#define VCLK135_5 0x1E
863#define VCLK139_054 0x1F
864#define VCLK157_5 0x20
865#define VCLK162 0x21
866#define VCLK175 0x22
867#define VCLK189 0x23
868#define VCLK194_4 0x24
869#define VCLK202_5 0x25
870#define VCLK229_5 0x26
871#define VCLK234 0x27
872#define VCLK252_699 0x28
873#define VCLK254_817 0x29
874#define VCLK265_728 0x2A
875#define VCLK266_952 0x2B
876#define VCLK269_655 0x2C
877#define VCLK272_042 0x2D
878#define VCLK277_015 0x2E
879#define VCLK286_359 0x2F
880#define VCLK291_132 0x30
881#define VCLK291_766 0x31
882#define VCLK309_789 0x32
883#define VCLK315_195 0x33
884#define VCLK323_586 0x34
885#define VCLK330_615 0x35
886#define VCLK332_177 0x36
887#define VCLK340_477 0x37
888#define VCLK375_847 0x38
889#define VCLK388_631 0x39
890#define VCLK125_999 0x51
891#define VCLK148_5 0x52
892#define VCLK178_992 0x54
893#define VCLK217_325 0x55
894#define VCLK299_505 0x56
895#define YPbPr750pVCLK 0x57
896
897#define TVVCLKDIV2 0x3A
898#define TVVCLK 0x3B
899#define HiTVVCLKDIV2 0x3C
900#define HiTVVCLK 0x3D
901#define HiTVSimuVCLK 0x3E
902#define HiTVTextVCLK 0x3F
903#define VCLK39_77 0x40
904/* #define YPbPr750pVCLK 0x0F */
905#define YPbPr525pVCLK 0x3A
906/* #define ;;YPbPr525iVCLK 0x3B */
907/* #define ;;YPbPr525iVCLK_2 0x3A */
908#define NTSC1024VCLK 0x41
909#define VCLK25_175_41 0x42 /* ; ScaleLCD */
910#define VCLK25_175_42 0x43
911#define VCLK28_322_43 0x44
912#define VCLK40_44 0x45
913#define VCLKQVGA_1 0x46 /* ; QVGA */
914#define VCLKQVGA_2 0x47
915#define VCLKQVGA_3 0x48
916#define VCLK35_2 0x49 /* ; 800x480 */
917#define VCLK122_61 0x4A
918#define VCLK80_350 0x4B
919#define VCLK107_385 0x4C
920
921#define CHTVVCLK30_2 0x50 /* ;;CHTV */
922#define CHTVVCLK28_1 0x51
923#define CHTVVCLK43_6 0x52
924#define CHTVVCLK26_4 0x53
925#define CHTVVCLK24_6 0x54
926#define CHTVVCLK47_8 0x55
927#define CHTVVCLK31_5 0x56
928#define CHTVVCLK26_2 0x57
929#define CHTVVCLK39 0x58
930#define CHTVVCLK36 0x59
931
932#define CH7007TVVCLK30_2 0x00 /* [Billy] 2007/05/18 For CH7007 */
933#define CH7007TVVCLK28_1 0x01
934#define CH7007TVVCLK43_6 0x02
935#define CH7007TVVCLK26_4 0x03
936#define CH7007TVVCLK24_6 0x04
937#define CH7007TVVCLK47_8 0x05
938#define CH7007TVVCLK31_5 0x06
939#define CH7007TVVCLK26_2 0x07
940#define CH7007TVVCLK39 0x08
941#define CH7007TVVCLK36 0x09
942
943#define RES320x200 0x00
944#define RES320x240 0x01
945#define RES400x300 0x02
946#define RES512x384 0x03
947#define RES640x400 0x04
948#define RES640x480x60 0x05
949#define RES640x480x72 0x06
950#define RES640x480x75 0x07
951#define RES640x480x85 0x08
952#define RES640x480x100 0x09
953#define RES640x480x120 0x0A
954#define RES640x480x160 0x0B
955#define RES640x480x200 0x0C
956#define RES800x600x56 0x0D
957#define RES800x600x60 0x0E
958#define RES800x600x72 0x0F
959#define RES800x600x75 0x10
960#define RES800x600x85 0x11
961#define RES800x600x100 0x12
962#define RES800x600x120 0x13
963#define RES800x600x160 0x14
964#define RES1024x768x43 0x15
965#define RES1024x768x60 0x16
966#define RES1024x768x70 0x17
967#define RES1024x768x75 0x18
968#define RES1024x768x85 0x19
969#define RES1024x768x100 0x1A
970#define RES1024x768x120 0x1B
971#define RES1280x1024x43 0x1C
972#define RES1280x1024x60 0x1D
973#define RES1280x1024x75 0x1E
974#define RES1280x1024x85 0x1F
975#define RES1600x1200x60 0x20
976#define RES1600x1200x65 0x21
977#define RES1600x1200x70 0x22
978#define RES1600x1200x75 0x23
979#define RES1600x1200x85 0x24
980#define RES1600x1200x100 0x25
981#define RES1600x1200x120 0x26
982#define RES1920x1440x60 0x27
983#define RES1920x1440x65 0x28
984#define RES1920x1440x70 0x29
985#define RES1920x1440x75 0x2A
986#define RES1920x1440x85 0x2B
987#define RES1920x1440x100 0x2C
988#define RES2048x1536x60 0x2D
989#define RES2048x1536x65 0x2E
990#define RES2048x1536x70 0x2F
991#define RES2048x1536x75 0x30
992#define RES2048x1536x85 0x31
993#define RES800x480x60 0x32
994#define RES800x480x75 0x33
995#define RES800x480x85 0x34
996#define RES1024x576x60 0x35
997#define RES1024x576x75 0x36
998#define RES1024x576x85 0x37
999#define RES1280x720x60 0x38
1000#define RES1280x720x75 0x39
1001#define RES1280x720x85 0x3A
1002#define RES1280x960x60 0x3B
1003#define RES720x480x60 0x3C
1004#define RES720x576x56 0x3D
1005#define RES856x480x79I 0x3E
1006#define RES856x480x60 0x3F
1007#define RES1280x768x60 0x40
1008#define RES1400x1050x60 0x41
1009#define RES1152x864x60 0x42
1010#define RES1152x864x75 0x43
1011#define RES1024x768x160 0x44
1012#define RES1280x960x75 0x45
1013#define RES1280x960x85 0x46
1014#define RES1280x960x120 0x47
1015
1016#define LFBDRAMTrap 0x30
1017#endif
diff --git a/drivers/staging/xgifb/vb_ext.c b/drivers/staging/xgifb/vb_ext.c
new file mode 100644
index 000000000000..49b39ee93a89
--- /dev/null
+++ b/drivers/staging/xgifb/vb_ext.c
@@ -0,0 +1,1370 @@
1#include "osdef.h"
2
3
4
5
6#ifdef WIN2000
7
8#include <dderror.h>
9#include <devioctl.h>
10#include <miniport.h>
11#include <ntddvdeo.h>
12#include <video.h>
13#include "xgiv.h"
14#include "dd_i2c.h"
15#include "tools.h"
16#endif /* WIN2000 */
17
18#ifdef LINUX_XF86
19#include "xf86.h"
20#include "xf86PciInfo.h"
21#include "xgi.h"
22#include "xgi_regs.h"
23#endif
24
25#ifdef LINUX_KERNEL
26#include <linux/version.h>
27#include <asm/io.h>
28#include <linux/types.h>
29#include "XGIfb.h"
30/*#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
31#include <video/XGIfb.h>
32#else
33#include <linux/XGIfb.h>
34#endif*/
35#endif
36
37
38
39#include "vb_def.h"
40#include "vgatypes.h"
41#include "vb_struct.h"
42#include "vb_util.h"
43#include "vb_setmode.h"
44#include "vb_ext.h"
45extern UCHAR XGI330_SoftSetting;
46extern UCHAR XGI330_OutputSelect;
47extern USHORT XGI330_RGBSenseData2;
48extern USHORT XGI330_YCSenseData2;
49extern USHORT XGI330_VideoSenseData2;
50#ifdef WIN2000
51extern UCHAR SenseCHTV(PHW_DEVICE_EXTENSION pHWDE); /* 2007/05/17 Billy */
52#endif
53void XGI_GetSenseStatus( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo );
54BOOLEAN XGINew_GetPanelID(PVB_DEVICE_INFO pVBInfo);
55USHORT XGINew_SenseLCD(PXGI_HW_DEVICE_INFO,PVB_DEVICE_INFO pVBInfo);
56BOOLEAN XGINew_GetLCDDDCInfo(PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo);
57void XGISetDPMS( PXGI_HW_DEVICE_INFO pXGIHWDE , ULONG VESA_POWER_STATE ) ;
58BOOLEAN XGINew_BridgeIsEnable(PXGI_HW_DEVICE_INFO,PVB_DEVICE_INFO pVBInfo );
59BOOLEAN XGINew_Sense(USHORT tempbx,USHORT tempcx, PVB_DEVICE_INFO pVBInfo);
60BOOLEAN XGINew_SenseHiTV( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo ) ;
61
62/**************************************************************
63 Dynamic Sense
64*************************************************************/
65
66void XGI_WaitDisplay(void);
67BOOLEAN XGI_Is301C(PVB_DEVICE_INFO);
68BOOLEAN XGI_Is301LV(PVB_DEVICE_INFO);
69
70#ifdef WIN2000
71UCHAR XGI_SenseLCD(PHW_DEVICE_EXTENSION, PVB_DEVICE_INFO);
72UCHAR XGI_GetLCDDDCInfo(PHW_DEVICE_EXTENSION,PVB_DEVICE_INFO);
73
74extern BOOL bGetDdcInfo(
75PHW_DEVICE_EXTENSION pHWDE,
76ULONG ulWhichOne,
77PUCHAR pjQueryBuffer,
78ULONG ulBufferSize
79 );
80
81#endif
82
83
84/* --------------------------------------------------------------------- */
85/* Function : XGINew_Is301B */
86/* Input : */
87/* Output : */
88/* Description : */
89/* --------------------------------------------------------------------- */
90BOOLEAN XGINew_Is301B( PVB_DEVICE_INFO pVBInfo )
91{
92 USHORT flag ;
93
94 flag = XGINew_GetReg1( pVBInfo->Part4Port , 0x01 ) ;
95
96 if ( flag > 0x0B0 )
97 return( 0 ) ; /* 301b */
98 else
99 return( 1 ) ;
100}
101
102/* --------------------------------------------------------------------- */
103/* Function : XGI_Is301C */
104/* Input : */
105/* Output : */
106/* Description : */
107/* --------------------------------------------------------------------- */
108BOOLEAN XGI_Is301C( PVB_DEVICE_INFO pVBInfo )
109{
110 if ( ( XGINew_GetReg1( pVBInfo->Part4Port , 0x01 ) & 0xF0 ) == 0xC0 )
111 return( 1 ) ;
112
113 if ( XGINew_GetReg1( pVBInfo->Part4Port , 0x01 ) >= 0xD0 )
114 {
115 if ( XGINew_GetReg1( pVBInfo->Part4Port , 0x39 ) == 0xE0 )
116 return( 1 ) ;
117 }
118
119 return( 0 ) ;
120}
121
122
123/* --------------------------------------------------------------------- */
124/* Function : XGI_Is301LV */
125/* Input : */
126/* Output : */
127/* Description : */
128/* --------------------------------------------------------------------- */
129BOOLEAN XGI_Is301LV( PVB_DEVICE_INFO pVBInfo )
130{
131 if ( XGINew_GetReg1( pVBInfo->Part4Port , 0x01 ) >= 0xD0 )
132 {
133 if ( XGINew_GetReg1( pVBInfo->Part4Port , 0x39 ) == 0xFF )
134 {
135 return( 1 ) ;
136 }
137 }
138 return( 0 ) ;
139}
140
141
142/* --------------------------------------------------------------------- */
143/* Function : XGINew_Sense */
144/* Input : */
145/* Output : */
146/* Description : */
147/* --------------------------------------------------------------------- */
148BOOLEAN XGINew_Sense( USHORT tempbx , USHORT tempcx, PVB_DEVICE_INFO pVBInfo )
149{
150 USHORT temp , i , tempch ;
151
152 temp = tempbx & 0xFF ;
153 XGINew_SetReg1( pVBInfo->Part4Port , 0x11 , temp ) ;
154 temp = ( tempbx & 0xFF00 ) >> 8 ;
155 temp |= ( tempcx & 0x00FF ) ;
156 XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x10 , ~0x1F , temp ) ;
157
158 for( i = 0 ; i < 10 ; i++ )
159 XGI_LongWait( pVBInfo) ;
160
161 tempch = ( tempcx & 0x7F00 ) >> 8 ;
162 temp = XGINew_GetReg1( pVBInfo->Part4Port , 0x03 ) ;
163 temp = temp ^ ( 0x0E ) ;
164 temp &= tempch ;
165
166 if ( temp > 0 )
167 return( 1 ) ;
168 else
169 return( 0 ) ;
170}
171
172#ifdef WIN2000
173/* --------------------------------------------------------------------- */
174/* Function : XGI_SenseLCD */
175/* Input : */
176/* Output : */
177/* Description : */
178/* --------------------------------------------------------------------- */
179UCHAR XGI_SenseLCD( PHW_DEVICE_EXTENSION pHWDE, PVB_DEVICE_INFO pVBInfo)
180{
181 USHORT tempax , tempbx , tempcx ;
182 UCHAR SoftSetting = XGI330_SoftSetting ;
183
184 if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV ) )
185 return( 1 ) ;
186
187
188 if ( SoftSetting & HotPlugFunction ) /* Hot Plug Detection */
189 {
190 XGINew_SetRegAND( pVBInfo->Part4Port , 0x0F , 0x3F ) ;
191 tempbx = 0 ;
192 tempcx = 0x9010 ;
193 if ( XGINew_Sense( tempbx , tempcx, pVBInfo ) )
194 return( 1 ) ;
195
196 return( 0 ) ;
197 }
198 else /* Get LCD Info from EDID */
199 return(XGI_GetLCDDDCInfo(pHWDE, pVBInfo));
200}
201
202
203/* --------------------------------------------------------------------- */
204/* Function : XGI_GetLCDDDCInfo */
205/* Input : */
206/* Output : */
207/* Description : */
208/* --------------------------------------------------------------------- */
209UCHAR XGI_GetLCDDDCInfo( PHW_DEVICE_EXTENSION pHWDE , PVB_DEVICE_INFO pVBInfo)
210{
211 UCHAR tempah , tempbl , tempbh ;
212 USHORT tempbx , temp ;
213 UCHAR pjEDIDBuf[ 256 ] ;
214 ULONG ulBufferSize = 256 ;
215 UCHAR bMASK_OUTPUTSTATE_CRT2LCD = 2 ; /* 0423 shampoo */
216
217 bGetDdcInfo( pHWDE , MASK_OUTPUTSTATE_CRT2LCD , pjEDIDBuf , ulBufferSize ) ;
218 if ( ( *( ( PULONG )pjEDIDBuf ) == 0xFFFFFF00 ) && ( *( ( PULONG )( pjEDIDBuf + 4 ) ) == 0x00FFFFFF ) )
219 {
220 tempah = Panel1024x768 ;
221 tempbl=( *( pjEDIDBuf + 0x3A ) ) & 0xf0 ;
222
223 if ( tempbl != 0x40 )
224 {
225 tempah = Panel1600x1200 ;
226 if ( tempbl != 0x60 )
227 {
228 tempah = Panel1280x1024 ;
229 tempbh = ( *( pjEDIDBuf + 0x3B ) ) ;
230 if ( tempbh != 0x00 )
231 {
232 tempah = Panel1280x960 ;
233 if ( tempbh != 0x0C0 )
234 {
235 tempbx = ( ( *( pjEDIDBuf + 0x24 ) ) << 8 ) | ( *( pjEDIDBuf + 0x23 ) ) ;
236 tempah = Panel1280x1024 ;
237 if ( !( tempbx & 0x0100 ) )
238 {
239 tempah = Panel1024x768 ;
240 if ( !( tempbx & 0x0E00 ) )
241 {
242 tempah = Panel1280x1024 ;
243 }
244 }
245 }
246
247 if ( tempbx & 0x00FF )
248 {
249 temp = ScalingLCD ;
250 XGINew_SetRegOR( pVBInfo->P3d4 , 0x37 , temp ) ;
251 }
252 }
253 }
254 }
255 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x36 , ( ~0x07 ) , tempah ) ;
256 tempah = ( ( *( pjEDIDBuf + 0x47 ) ) & 0x06 ) ; /* Polarity */
257 tempah = ( tempah ^ 0x06 ) << 4 ;
258 tempah |= LCDSync ;
259 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x37 , ( ~LCDSyncBit ) , tempah ) ;
260 tempbh= XGINew_GetReg1( pVBInfo->P3d4 , 0x36 ) ;
261 tempbh &= 0x07 ;
262 if ( tempbh == Panel1280x960 )
263 XGINew_SetRegAND( pVBInfo->P3d4 , 0x37 , 0x0E ) ;
264 }
265 else if ( *pjEDIDBuf == 0x20 )
266 {
267 tempah = Panel1024x768 ;
268 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x36 , ( ~0x07 ) , tempah ) ;
269 }
270 else
271 {
272 return( 0 ) ;
273 }
274
275 return( 1 ) ;
276}
277
278
279/* --------------------------------------------------------------------- */
280/* Function : XGI_DySense */
281/* Input : */
282/* Output : */
283/* Description : */
284/* --------------------------------------------------------------------- */
285BOOLEAN XGI_DySense( PHW_DEVICE_EXTENSION pHWDE , PUCHAR ujConnectStatus)
286{
287 UCHAR pre_CRD,pre_SR1E , pre_Part2_0 , pre_Part4_D ;
288 USHORT tempax , tempbx , tempcx , pushax , temp ;
289 VB_DEVICE_INFO VBINF;
290 PVB_DEVICE_INFO pVBInfo = &VBINF;
291 UCHAR OutputSelect = XGI330_OutputSelect ;
292 PXGI_HW_DEVICE_INFO HwDeviceExtension= pHWDE->pXGIHWDE ;
293 UCHAR bConnectStatus = 0 ;
294 pVBInfo->BaseAddr = HwDeviceExtension->pjIOAddress ;
295 pVBInfo->ROMAddr = pHWDE->pjVirtualRomBase ;
296
297 pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ;
298 pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ;
299 pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ;
300 pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ;
301 pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ;
302 pushax = XGINew_GetReg1( pVBInfo->P3d4 , 0x17 ) ; /* 0512 Fix Dysense hanged */
303 temp = ( pushax & 0x00FF ) | 0x80 ;
304 XGINew_SetRegOR( pVBInfo->P3d4 , 0x17 , temp ) ;
305 XGINew_SetReg1( pVBInfo->P3c4 , 0x05 , 0x86 ) ;
306 /* beginning of dynamic sense CRT1 */
307
308 pVBInfo->IF_DEF_CH7007 = 0;
309 if (pHWDE->bCH7007)
310 {
311 InitTo330Pointer( pHWDE->pXGIHWDE->jChipType, pVBInfo ) ;
312 HwDeviceExtension->pDevice = (PVOID)pHWDE;
313 pVBInfo->IF_DEF_CH7007 = 1;
314 /* [Billy] 2007/05/14 For CH7007 */
315 if ( pVBInfo->IF_DEF_CH7007 == 1 )
316 {
317 bConnectStatus = SenseCHTV(HwDeviceExtension->pDevice) ; /* 07/05/28 */
318 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , ~0x03 , (UCHAR)bConnectStatus ) ;
319 }
320 }
321 if(( pHWDE->jChipID >= XG40 ) || ( pHWDE->jChipID >= XG20 ))
322 {
323
324 if ( pHWDE->jChipID >= XG40 )
325 XGINew_SetReg1( pVBInfo->P3d4 , 0x57 , 0x4A ) ; /* write sense pattern 30->4a */
326 else
327 XGINew_SetReg1( pVBInfo->P3d4 , 0x57 , 0x5F ) ; /* write sense pattern */
328
329 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x53 , 0xFF , 0x02 ) ; /* enable sense DAC */
330 XGI_WaitDisply(pVBInfo) ;
331
332 if(XGINew_GetReg2( pVBInfo->P3c2 ) & 0x10 )
333 bConnectStatus |= Monitor1Sense ;
334
335 XGINew_SetRegAND( pVBInfo->P3d4 , 0x53 , 0xFD ) ; /* disable sense DAC */
336 XGINew_SetRegAND( pVBInfo->P3d4 , 0x57 , 0x00 ) ; /* clear sense pattern */
337
338
339 /* ---------- End of dynamic sense CRT1 ----------- */
340
341 /* ---------- beginning of dynamic sense VB ------------ */
342 pre_SR1E = XGINew_GetReg1( pVBInfo->P3c4 , 0x1E ) ;
343 XGINew_SetRegOR( pVBInfo->P3c4 , 0x1E , 0x20 ) ; /* Enable CRT2,work-a-round for 301B/301LV/302LV */
344 pre_Part2_0 = XGINew_GetReg1( pVBInfo->Part2Port , 0x00 ) ;
345 pre_Part4_D = XGINew_GetReg1( pVBInfo->Part4Port , 0x0D ) ;
346
347 if ( XGI_Is301C( pVBInfo ) ) /* 301C only */
348 XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x0D , ~0x07 , 0x01 ) ; /* Set Part4 0x0D D[2:0] to 001b */
349
350 /* tempax = 0 ; */
351 if ( !XGI_Is301LV( pVBInfo ) )
352 {
353 tempbx = XGI330_RGBSenseData2 ;
354 tempcx = 0x0E08 ;
355 if(XGINew_Sense( tempbx , tempcx, pVBInfo ) )
356 {
357 bConnectStatus |= Monitor2Sense ;
358 if ( OutputSelect & SetSCARTOutput )
359 {
360 bConnectStatus ^= ( Monitor2Sense | SCARTSense ) ;
361 }
362 }
363 }
364 if ( XGI_Is301C( pVBInfo ) ) /* 301C only */
365 XGINew_SetRegOR( pVBInfo->Part4Port , 0x0D , 0x04 ) ; /* Set Part4 0x0D D[2]=1 for dynamic sense */
366
367 if ( ( XGINew_Is301B( pVBInfo ) ) )
368 XGINew_SetRegOR( pVBInfo->Part2Port , 0x00 , 0x0C ) ; /* ????????? */
369
370 if ( XGINew_SenseHiTV( HwDeviceExtension , pVBInfo) ) /* add by kuku for Dysense HiTV //start */
371 {
372 bConnectStatus|= YPbPrSense ;
373 }
374 else
375 {
376 tempbx = XGI330_YCSenseData2 ; /* Y/C Sense Data Ptr */
377 tempcx = 0x0604 ;
378 if ( XGINew_Sense( tempbx , tempcx , pVBInfo) )
379 bConnectStatus |= SVIDEOSense ;
380
381 if ( OutputSelect & BoardTVType )
382 {
383 tempbx = XGI330_VideoSenseData2 ;
384 tempcx = 0x0804 ;
385 if ( XGINew_Sense(tempbx , tempcx, pVBInfo) )
386 bConnectStatus|= AVIDEOSense ;
387 }
388 else
389 {
390 if ( !( bConnectStatus & SVIDEOSense ) )
391 {
392 tempbx = XGI330_VideoSenseData2 ;
393 tempcx = 0x0804 ;
394 if ( XGINew_Sense( tempbx , tempcx, pVBInfo ) )
395 bConnectStatus |= AVIDEOSense ;
396 }
397 }
398 } /* end */
399 /* DySenseVBCnt */
400
401 tempbx = 0 ;
402 tempcx = 0 ;
403 XGINew_Sense(tempbx , tempcx, pVBInfo ) ;
404
405 if ( !( bConnectStatus & Monitor2Sense ) )
406 {
407 if ( XGI_SenseLCD( pHWDE , pVBInfo ) )
408 bConnectStatus |= LCDSense ;
409 }
410
411 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , ~( AVIDEOSense | SVIDEOSense | LCDSense | Monitor2Sense | Monitor1Sense ) , bConnectStatus ) ;
412
413 XGINew_SetReg1( pVBInfo->Part4Port , 0x0D , pre_Part4_D ) ;
414 XGINew_SetReg1( pVBInfo->Part2Port , 0x00 , pre_Part2_0 ) ;
415 XGINew_SetReg1( pVBInfo->P3c4 , 0x1E , pre_SR1E ) ;
416
417 if ( XGI_Is301C( pVBInfo ) ) /* 301C only */
418 {
419 tempax = XGINew_GetReg1( pVBInfo->Part2Port , 0x00 ) ;
420 if ( tempax & 0x20 )
421 {
422 /* Reset VBPro */
423 for( tempcx = 2 ; tempcx > 0 ; tempcx-- )
424 {
425 tempax ^= 0x20 ;
426 XGINew_SetReg1( pVBInfo->Part2Port , 0x00 , tempax ) ;
427 }
428 }
429 }
430 /* End of dynamic sense VB */
431 }
432 else
433 {
434 XGI_SenseCRT1(pVBInfo) ;
435 XGI_GetSenseStatus( HwDeviceExtension, pVBInfo ) ; /* sense CRT2 */
436 bConnectStatus = XGINew_GetReg1( pVBInfo->P3d4 , 0x32 ) ;
437 }
438 temp = pushax & 0x00FF ; /* 0512 Fix Dysense hanged */
439 XGINew_SetReg1( pVBInfo->P3d4 , 0x17 , temp ) ;
440 if ( bConnectStatus )
441 {
442 *ujConnectStatus = bConnectStatus ;
443 return( 1 ) ;
444 }
445 else
446 return( 0 ) ;
447}
448
449#endif /* WIN2000 */
450
451/* --------------------------------------------------------------------- */
452/* Function : XGISetDPMS */
453/* Input : */
454/* Output : */
455/* Description : */
456/* --------------------------------------------------------------------- */
457VOID XGISetDPMS( PXGI_HW_DEVICE_INFO pXGIHWDE , ULONG VESA_POWER_STATE )
458{
459 USHORT ModeNo, ModeIdIndex ;
460 UCHAR temp ;
461 VB_DEVICE_INFO VBINF;
462 PVB_DEVICE_INFO pVBInfo = &VBINF;
463 pVBInfo->BaseAddr = (ULONG)pXGIHWDE->pjIOAddress ;
464 pVBInfo->ROMAddr = pXGIHWDE->pjVirtualRomBase ;
465
466
467 pVBInfo->IF_DEF_LVDS = 0 ;
468 pVBInfo->IF_DEF_CH7005 = 0 ;
469 pVBInfo->IF_DEF_HiVision = 1 ;
470 pVBInfo->IF_DEF_LCDA = 1 ;
471 pVBInfo->IF_DEF_CH7017 = 0 ;
472 pVBInfo->IF_DEF_YPbPr = 1 ;
473 pVBInfo->IF_DEF_CRT2Monitor = 0 ;
474 pVBInfo->IF_DEF_VideoCapture = 0 ;
475 pVBInfo->IF_DEF_ScaleLCD = 0 ;
476 pVBInfo->IF_DEF_OEMUtil = 0 ;
477 pVBInfo->IF_DEF_PWD = 0 ;
478
479 InitTo330Pointer( pXGIHWDE->jChipType, pVBInfo ) ;
480 ReadVBIOSTablData( pXGIHWDE->jChipType , pVBInfo) ;
481
482 pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ;
483 pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ;
484 pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10 ;
485 pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e ;
486 pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ;
487 pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a ;
488 pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16 ;
489 pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17 ;
490 pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18 ;
491 pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19 ;
492 pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A ;
493 pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00 ;
494 pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04 ;
495 pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ;
496 pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12 ;
497 pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ;
498 pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2 ;
499
500 if ( pXGIHWDE->jChipType == XG27 )
501 {
502 if ( ( XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) & 0xE0 ) == 0xC0 )
503 {
504 if ( XGINew_GetReg1( pVBInfo->P3d4 , 0x30 ) & 0x20 )
505 {
506 pVBInfo->IF_DEF_LVDS = 1 ;
507 }
508 }
509 }
510
511 if ( pVBInfo->IF_DEF_CH7007 == 0 )
512 {
513 XGINew_SetModeScratch ( pXGIHWDE , pVBInfo ) ;
514 }
515 XGINew_SetReg1( pVBInfo->P3c4 , 0x05 , 0x86 ) ; /* 1.Openkey */
516 XGI_UnLockCRT2( pXGIHWDE , pVBInfo) ;
517 ModeNo = XGINew_GetReg1( pVBInfo->P3d4 , 0x34 ) ;
518 XGI_SearchModeID( ModeNo , &ModeIdIndex, pVBInfo ) ;
519 XGI_GetVGAType( pXGIHWDE , pVBInfo ) ;
520
521 if ( ( pXGIHWDE->ujVBChipID == VB_CHIP_301 ) || ( pXGIHWDE->ujVBChipID == VB_CHIP_302 ) || ( pVBInfo->IF_DEF_CH7007 == 1 ))
522 {
523 XGI_GetVBType( pVBInfo ) ;
524 XGI_GetVBInfo( ModeNo , ModeIdIndex , pXGIHWDE, pVBInfo ) ;
525 XGI_GetTVInfo( ModeNo , ModeIdIndex, pVBInfo ) ;
526 XGI_GetLCDInfo( ModeNo , ModeIdIndex, pVBInfo ) ;
527 }
528
529 if ( VESA_POWER_STATE == 0x00000400 )
530 XGINew_SetReg1( pVBInfo->Part4Port , 0x31 , ( UCHAR )( XGINew_GetReg1( pVBInfo->Part4Port , 0x31 ) & 0xFE ) ) ;
531 else
532 XGINew_SetReg1( pVBInfo->Part4Port , 0x31 , ( UCHAR )( XGINew_GetReg1( pVBInfo->Part4Port , 0x31 ) | 0x01 ) ) ;
533
534 temp = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x1f ) ;
535 temp &= 0x3f ;
536 switch ( VESA_POWER_STATE )
537 {
538 case 0x00000000: /* on */
539 if ( ( pXGIHWDE->ujVBChipID == VB_CHIP_301 ) || ( pXGIHWDE->ujVBChipID == VB_CHIP_302 ) )
540 {
541 XGINew_SetReg1( pVBInfo->P3c4 , 0x1f , ( UCHAR )( temp | 0x00 ) ) ;
542 XGI_EnableBridge( pXGIHWDE, pVBInfo ) ;
543 }
544 else
545 {
546 if ( pXGIHWDE->jChipType == XG21 )
547 {
548 if ( pVBInfo->IF_DEF_LVDS == 1 )
549 {
550 XGI_XG21BLSignalVDD( 0x01 , 0x01, pVBInfo ) ; /* LVDS VDD on */
551 XGI_XG21SetPanelDelay( 2,pVBInfo ) ;
552 }
553 }
554 if ( pXGIHWDE->jChipType == XG27 )
555 {
556 if ( pVBInfo->IF_DEF_LVDS == 1 )
557 {
558 XGI_XG27BLSignalVDD( 0x01 , 0x01, pVBInfo ) ; /* LVDS VDD on */
559 XGI_XG21SetPanelDelay( 2,pVBInfo ) ;
560 }
561 }
562 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x1F , ~0xC0 , 0x00 ) ;
563 XGINew_SetRegAND( pVBInfo->P3c4 , 0x01 , ~0x20 ) ; /* CRT on */
564
565 if ( pXGIHWDE->jChipType == XG21 )
566 {
567 temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) ;
568 if ( temp & 0xE0 )
569 {
570 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x09 , ~0x80 , 0x80 ) ; /* DVO ON */
571 XGI_SetXG21FPBits( pVBInfo );
572 XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~0x20 ) ; /* Enable write GPIOF */
573 /*XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x48 , ~0x20 , 0x20 ) ;*/ /* LCD Display ON */
574 }
575 XGI_XG21BLSignalVDD( 0x20 , 0x20, pVBInfo ) ; /* LVDS signal on */
576 XGI_DisplayOn( pXGIHWDE, pVBInfo );
577 }
578 if ( pXGIHWDE->jChipType == XG27 )
579 {
580 temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) ;
581 if ( temp & 0xE0 )
582 {
583 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x09 , ~0x80 , 0x80 ) ; /* DVO ON */
584 XGI_SetXG27FPBits( pVBInfo );
585 XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~0x20 ) ; /* Enable write GPIOF */
586 /*XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x48 , ~0x20 , 0x20 ) ;*/ /* LCD Display ON */
587 }
588 XGI_XG27BLSignalVDD( 0x20 , 0x20, pVBInfo ) ; /* LVDS signal on */
589 XGI_DisplayOn( pXGIHWDE, pVBInfo );
590 }
591 }
592 break ;
593 case 0x00000100: /* standby */
594 if ( pXGIHWDE->jChipType >= XG21 )
595 {
596 XGI_DisplayOff( pXGIHWDE, pVBInfo );
597 }
598
599 XGINew_SetReg1( pVBInfo->P3c4 , 0x1f , ( UCHAR )( temp | 0x40 ) ) ;
600 break ;
601 case 0x00000200: /* suspend */
602 if ( pXGIHWDE->jChipType == XG21 )
603 {
604 XGI_DisplayOff( pXGIHWDE, pVBInfo );
605 XGI_XG21BLSignalVDD( 0x20 , 0x00, pVBInfo ) ; /* LVDS signal off */
606 }
607 if ( pXGIHWDE->jChipType == XG27 )
608 {
609 XGI_DisplayOff( pXGIHWDE, pVBInfo );
610 XGI_XG27BLSignalVDD( 0x20 , 0x00, pVBInfo ) ; /* LVDS signal off */
611 }
612 XGINew_SetReg1( pVBInfo->P3c4 , 0x1f , ( UCHAR )( temp | 0x80 ) ) ;
613 break ;
614 case 0x00000400: /* off */
615 if ( (pXGIHWDE->ujVBChipID == VB_CHIP_301 ) || ( pXGIHWDE->ujVBChipID == VB_CHIP_302 ) )
616 {
617 XGINew_SetReg1( pVBInfo->P3c4 , 0x1f , ( UCHAR )( temp | 0xc0 ) ) ;
618 XGI_DisableBridge( pXGIHWDE, pVBInfo ) ;
619 }
620 else
621 {
622 if ( pXGIHWDE->jChipType == XG21 )
623 {
624 XGI_DisplayOff( pXGIHWDE, pVBInfo );
625
626 XGI_XG21BLSignalVDD( 0x20 , 0x00, pVBInfo ) ; /* LVDS signal off */
627
628 temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) ;
629 if ( temp & 0xE0 )
630 {
631 XGINew_SetRegAND( pVBInfo->P3c4 , 0x09 , ~0x80 ) ; /* DVO Off */
632 XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~0x20 ) ; /* Enable write GPIOF */
633 /*XGINew_SetRegAND( pVBInfo->P3d4 , 0x48 , ~0x20 ) ;*/ /* LCD Display OFF */
634 }
635 }
636 if ( pXGIHWDE->jChipType == XG27 )
637 {
638 XGI_DisplayOff( pXGIHWDE, pVBInfo );
639
640 XGI_XG27BLSignalVDD( 0x20 , 0x00, pVBInfo ) ; /* LVDS signal off */
641
642 temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) ;
643 if ( temp & 0xE0 )
644 {
645 XGINew_SetRegAND( pVBInfo->P3c4 , 0x09 , ~0x80 ) ; /* DVO Off */
646 }
647 }
648 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x1F , ~0xC0 , 0xC0 ) ;
649 XGINew_SetRegOR( pVBInfo->P3c4 , 0x01 , 0x20 ) ; /* CRT Off */
650
651 if ( ( pXGIHWDE->jChipType == XG21 ) && ( pVBInfo->IF_DEF_LVDS == 1 ) )
652 {
653 XGI_XG21SetPanelDelay( 4,pVBInfo ) ;
654 XGI_XG21BLSignalVDD( 0x01 , 0x00, pVBInfo ) ; /* LVDS VDD off */
655 XGI_XG21SetPanelDelay( 5,pVBInfo ) ;
656 }
657 if ( ( pXGIHWDE->jChipType == XG27 ) && ( pVBInfo->IF_DEF_LVDS == 1 ) )
658 {
659 XGI_XG21SetPanelDelay( 4,pVBInfo ) ;
660 XGI_XG27BLSignalVDD( 0x01 , 0x00, pVBInfo ) ; /* LVDS VDD off */
661 XGI_XG21SetPanelDelay( 5,pVBInfo ) ;
662 }
663 }
664 break ;
665
666 default:
667 break ;
668 }
669 XGI_LockCRT2( pXGIHWDE , pVBInfo ) ;
670}
671
672
673
674/* --------------------------------------------------------------------- */
675/* Function : XGI_GetSenseStatus */
676/* Input : */
677/* Output : */
678/* Description : */
679/* --------------------------------------------------------------------- */
680void XGI_GetSenseStatus( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
681{
682 USHORT tempax = 0 , tempbx , tempcx , temp ,
683 P2reg0 = 0 , SenseModeNo = 0 , OutputSelect = *pVBInfo->pOutputSelect ,
684 ModeIdIndex , i ;
685 pVBInfo->BaseAddr = (ULONG)HwDeviceExtension->pjIOAddress ;
686
687 if ( pVBInfo->IF_DEF_LVDS == 1 )
688 {
689 tempax = XGINew_GetReg1( pVBInfo->P3c4 , 0x1A ) ; /* ynlai 02/27/2002 */
690 tempbx = XGINew_GetReg1( pVBInfo->P3c4 , 0x1B ) ;
691 tempax = ( ( tempax & 0xFE ) >> 1 ) | ( tempbx << 8 ) ;
692 if ( tempax == 0x00 )
693 { /* Get Panel id from DDC */
694 temp = XGINew_GetLCDDDCInfo( HwDeviceExtension, pVBInfo ) ;
695 if ( temp == 1 )
696 { /* LCD connect */
697 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x39 , 0xFF , 0x01 ) ; /* set CR39 bit0="1" */
698 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x37 , 0xEF , 0x00 ) ; /* clean CR37 bit4="0" */
699 temp = LCDSense ;
700 }
701 else
702 { /* LCD don't connect */
703 temp = 0 ;
704 }
705 }
706 else
707 {
708 XGINew_GetPanelID(pVBInfo) ;
709 temp = LCDSense ;
710 }
711
712 tempbx = ~( LCDSense | AVIDEOSense | SVIDEOSense ) ;
713 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , tempbx , temp ) ;
714 }
715 else
716 { /* for 301 */
717 if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
718 { /* for HiVision */
719 tempax = XGINew_GetReg1( pVBInfo->P3c4 , 0x38 ) ;
720 temp = tempax & 0x01 ;
721 tempax = XGINew_GetReg1( pVBInfo->P3c4 , 0x3A ) ;
722 temp = temp | ( tempax & 0x02 ) ;
723 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , 0xA0 , temp ) ;
724 }
725 else
726 {
727 if ( XGI_BridgeIsOn( pVBInfo ) )
728 {
729 P2reg0 = XGINew_GetReg1( pVBInfo->Part2Port , 0x00 ) ;
730 if ( !XGINew_BridgeIsEnable( HwDeviceExtension, pVBInfo ) )
731 {
732 SenseModeNo = 0x2e ;
733 /* XGINew_SetReg1( pVBInfo->P3d4 , 0x30 , 0x41 ) ; */
734 /* XGISetModeNew( HwDeviceExtension , 0x2e ) ; // ynlai InitMode */
735
736 temp = XGI_SearchModeID( SenseModeNo , &ModeIdIndex, pVBInfo ) ;
737 XGI_GetVGAType( HwDeviceExtension , pVBInfo) ;
738 XGI_GetVBType( pVBInfo ) ;
739 pVBInfo->SetFlag = 0x00 ;
740 pVBInfo->ModeType = ModeVGA ;
741 pVBInfo->VBInfo = SetCRT2ToRAMDAC | LoadDACFlag | SetInSlaveMode ;
742 XGI_GetLCDInfo( 0x2e , ModeIdIndex, pVBInfo ) ;
743 XGI_GetTVInfo( 0x2e , ModeIdIndex, pVBInfo ) ;
744 XGI_EnableBridge( HwDeviceExtension, pVBInfo ) ;
745 XGI_SetCRT2Group301( SenseModeNo , HwDeviceExtension, pVBInfo ) ;
746 XGI_SetCRT2ModeRegs( 0x2e , HwDeviceExtension, pVBInfo ) ;
747 /* XGI_DisableBridge( HwDeviceExtension, pVBInfo ) ; */
748 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x01 , 0xDF , 0x20 ) ; /* Display Off 0212 */
749 for( i = 0 ; i < 20 ; i++ )
750 {
751 XGI_LongWait(pVBInfo) ;
752 }
753 }
754 XGINew_SetReg1( pVBInfo->Part2Port , 0x00 , 0x1c ) ;
755 tempax = 0 ;
756 tempbx = *pVBInfo->pRGBSenseData ;
757
758 if ( !( XGINew_Is301B( pVBInfo ) ) )
759 {
760 tempbx = *pVBInfo->pRGBSenseData2 ;
761 }
762
763 tempcx = 0x0E08 ;
764 if ( XGINew_Sense(tempbx , tempcx, pVBInfo ) )
765 {
766 if ( XGINew_Sense(tempbx , tempcx, pVBInfo ) )
767 {
768 tempax |= Monitor2Sense ;
769 }
770 }
771
772 if ( pVBInfo->VBType & VB_XGI301C)
773 {
774 XGINew_SetRegOR( pVBInfo->Part4Port , 0x0d , 0x04 ) ;
775 }
776
777 if ( XGINew_SenseHiTV( HwDeviceExtension , pVBInfo) ) /* add by kuku for Multi-adapter sense HiTV */
778 {
779 tempax |= HiTVSense ;
780 if ( ( pVBInfo->VBType & VB_XGI301C ) )
781 {
782 tempax ^= ( HiTVSense | YPbPrSense ) ;
783 }
784 }
785
786 if ( !( tempax & ( HiTVSense | YPbPrSense ) ) ) /* start */
787 {
788
789 tempbx = *pVBInfo->pYCSenseData ;
790
791 if ( !( XGINew_Is301B( pVBInfo ) ) )
792 {
793 tempbx=*pVBInfo->pYCSenseData2;
794 }
795
796 tempcx = 0x0604 ;
797 if ( XGINew_Sense(tempbx , tempcx, pVBInfo ) )
798 {
799 if ( XGINew_Sense(tempbx , tempcx, pVBInfo ) )
800 {
801 tempax |= SVIDEOSense ;
802 }
803 }
804
805 if ( OutputSelect & BoardTVType )
806 {
807 tempbx = *pVBInfo->pVideoSenseData ;
808
809 if ( !( XGINew_Is301B( pVBInfo ) ) )
810 {
811 tempbx = *pVBInfo->pVideoSenseData2 ;
812 }
813
814 tempcx = 0x0804 ;
815 if ( XGINew_Sense(tempbx , tempcx, pVBInfo ) )
816 {
817 if ( XGINew_Sense(tempbx , tempcx, pVBInfo ) )
818 {
819 tempax |= AVIDEOSense ;
820 }
821 }
822 }
823 else
824 {
825 if ( !( tempax & SVIDEOSense ) )
826 {
827 tempbx = *pVBInfo->pVideoSenseData ;
828
829 if ( !( XGINew_Is301B( pVBInfo ) ) )
830 {
831 tempbx=*pVBInfo->pVideoSenseData2;
832 }
833
834 tempcx = 0x0804 ;
835 if ( XGINew_Sense(tempbx , tempcx, pVBInfo ) )
836 {
837 if ( XGINew_Sense(tempbx , tempcx, pVBInfo ) )
838 {
839 tempax |= AVIDEOSense ;
840 }
841 }
842 }
843 }
844 }
845 } /* end */
846 if ( !( tempax & Monitor2Sense ) )
847 {
848 if ( XGINew_SenseLCD( HwDeviceExtension, pVBInfo ) )
849 {
850 tempax |= LCDSense ;
851 }
852 }
853 tempbx = 0 ;
854 tempcx = 0 ;
855 XGINew_Sense(tempbx , tempcx, pVBInfo ) ;
856
857 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , ~0xDF , tempax ) ;
858 XGINew_SetReg1( pVBInfo->Part2Port , 0x00 , P2reg0 ) ;
859
860 if ( !( P2reg0 & 0x20 ) )
861 {
862 pVBInfo->VBInfo = DisableCRT2Display ;
863 /* XGI_SetCRT2Group301( SenseModeNo , HwDeviceExtension, pVBInfo ) ; */
864 }
865 }
866 }
867 XGI_DisableBridge( HwDeviceExtension, pVBInfo ) ; /* shampoo 0226 */
868
869}
870
871
872
873/* --------------------------------------------------------------------- */
874/* Function : XGINew_SenseLCD */
875/* Input : */
876/* Output : */
877/* Description : */
878/* --------------------------------------------------------------------- */
879USHORT XGINew_SenseLCD( PXGI_HW_DEVICE_INFO HwDeviceExtension ,PVB_DEVICE_INFO pVBInfo)
880{
881 /* USHORT SoftSetting ; */
882 USHORT temp ;
883
884 if ( ( HwDeviceExtension->jChipType >= XG20 ) || ( HwDeviceExtension->jChipType >= XG40 ) )
885 temp = 0 ;
886 else
887 temp=XGINew_GetPanelID(pVBInfo) ;
888
889 if( !temp )
890 temp = XGINew_GetLCDDDCInfo( HwDeviceExtension, pVBInfo ) ;
891
892 return( temp ) ;
893}
894
895
896/* --------------------------------------------------------------------- */
897/* Function : XGINew_GetLCDDDCInfo */
898/* Input : */
899/* Output : */
900/* Description : */
901/* --------------------------------------------------------------------- */
902BOOLEAN XGINew_GetLCDDDCInfo( PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo)
903{
904 USHORT temp ;
905
906 /* add lcd sense */
907 if ( HwDeviceExtension->ulCRT2LCDType == LCD_UNKNOWN )
908 {
909 return( 0 ) ;
910 }
911 else
912 {
913 temp = ( USHORT )HwDeviceExtension->ulCRT2LCDType ;
914 switch( HwDeviceExtension->ulCRT2LCDType )
915 {
916 case LCD_INVALID:
917 case LCD_800x600:
918 case LCD_1024x768:
919 case LCD_1280x1024:
920 break ;
921
922 case LCD_640x480:
923 case LCD_1024x600:
924 case LCD_1152x864:
925 case LCD_1280x960:
926 case LCD_1152x768:
927 temp = 0 ;
928 break ;
929
930 case LCD_1400x1050:
931 case LCD_1280x768:
932 case LCD_1600x1200:
933 break ;
934
935 case LCD_1920x1440:
936 case LCD_2048x1536:
937 temp = 0 ;
938 break ;
939
940 default:
941 break ;
942 }
943 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x36 , 0xF0 , temp ) ;
944 return( 1 ) ;
945 }
946}
947
948
949/* --------------------------------------------------------------------- */
950/* Function : */
951/* Input : */
952/* Output : */
953/* Description : */
954/* --------------------------------------------------------------------- */
955BOOLEAN XGINew_GetPanelID(PVB_DEVICE_INFO pVBInfo )
956{
957 USHORT PanelTypeTable[ 16 ] = { SyncNN | PanelRGB18Bit | Panel800x600 | _PanelType00 ,
958 SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType01 ,
959 SyncNN | PanelRGB18Bit | Panel800x600 | _PanelType02 ,
960 SyncNN | PanelRGB18Bit | Panel640x480 | _PanelType03 ,
961 SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType04 ,
962 SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType05 ,
963 SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType06 ,
964 SyncNN | PanelRGB24Bit | Panel1024x768 | _PanelType07 ,
965 SyncNN | PanelRGB18Bit | Panel800x600 | _PanelType08 ,
966 SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType09 ,
967 SyncNN | PanelRGB18Bit | Panel800x600 | _PanelType0A ,
968 SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType0B ,
969 SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType0C ,
970 SyncNN | PanelRGB24Bit | Panel1024x768 | _PanelType0D ,
971 SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType0E ,
972 SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType0F } ;
973 USHORT tempax , tempbx , temp ;
974 /* USHORT return_flag ; */
975
976 tempax = XGINew_GetReg1( pVBInfo->P3c4 , 0x1A ) ;
977 tempbx = tempax & 0x1E ;
978
979 if ( tempax == 0 )
980 return( 0 ) ;
981 else
982 {
983/*
984 if ( !( tempax & 0x10 ) )
985 {
986 if ( pVBInfo->IF_DEF_LVDS == 1 )
987 {
988 tempbx = 0 ;
989 temp = XGINew_GetReg1( pVBInfo->P3c4 , 0x38 ) ;
990 if ( temp & 0x40 )
991 tempbx |= 0x08 ;
992 if ( temp & 0x20 )
993 tempbx |= 0x02 ;
994 if ( temp & 0x01 )
995 tempbx |= 0x01 ;
996
997 temp = XGINew_GetReg1( pVBInfo->P3c4 , 0x39 ) ;
998 if ( temp & 0x80 )
999 tempbx |= 0x04 ;
1000 }
1001 else
1002 {
1003 return( 0 ) ;
1004 }
1005 }
1006*/
1007
1008 tempbx = tempbx >> 1 ;
1009 temp = tempbx & 0x00F ;
1010 XGINew_SetReg1( pVBInfo->P3d4 , 0x36 , temp ) ;
1011 tempbx-- ;
1012 tempbx = PanelTypeTable[ tempbx ] ;
1013
1014 temp = ( tempbx & 0xFF00 ) >> 8 ;
1015 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x37 , ~( LCDSyncBit | LCDRGB18Bit ) , temp ) ;
1016 return( 1 ) ;
1017 }
1018}
1019
1020
1021/* --------------------------------------------------------------------- */
1022/* Function : XGINew_BridgeIsEnable */
1023/* Input : */
1024/* Output : */
1025/* Description : */
1026/* --------------------------------------------------------------------- */
1027BOOLEAN XGINew_BridgeIsEnable( PXGI_HW_DEVICE_INFO HwDeviceExtension ,PVB_DEVICE_INFO pVBInfo)
1028{
1029 USHORT flag ;
1030
1031 if ( XGI_BridgeIsOn( pVBInfo ) == 0 )
1032 {
1033 flag = XGINew_GetReg1( pVBInfo->Part1Port , 0x0 ) ;
1034
1035 if ( flag & 0x050 )
1036 {
1037 return( 1 ) ;
1038 }
1039 else
1040 {
1041 return( 0 ) ;
1042 }
1043
1044 }
1045 return( 0 ) ;
1046}
1047
1048/* ------------------------------------------------------ */
1049/* Function : XGINew_SenseHiTV */
1050/* Input : */
1051/* Output : */
1052/* Description : */
1053/* ------------------------------------------------------ */
1054BOOLEAN XGINew_SenseHiTV( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo )
1055{
1056 USHORT tempbx , tempcx , temp , i , tempch;
1057
1058 tempbx = *pVBInfo->pYCSenseData2 ;
1059
1060 tempcx = 0x0604 ;
1061
1062 temp = tempbx & 0xFF ;
1063 XGINew_SetReg1( pVBInfo->Part4Port , 0x11 , temp ) ;
1064 temp = ( tempbx & 0xFF00 ) >> 8 ;
1065 temp |= ( tempcx & 0x00FF ) ;
1066 XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x10 , ~0x1F , temp ) ;
1067
1068 for( i = 0 ; i < 10 ; i++ )
1069 XGI_LongWait(pVBInfo) ;
1070
1071 tempch = ( tempcx & 0xFF00 ) >> 8;
1072 temp = XGINew_GetReg1( pVBInfo->Part4Port , 0x03 ) ;
1073 temp = temp ^ ( 0x0E ) ;
1074 temp &= tempch ;
1075
1076 if ( temp != tempch )
1077 return( 0 ) ;
1078
1079 tempbx = *pVBInfo->pVideoSenseData2 ;
1080
1081 tempcx = 0x0804 ;
1082 temp = tempbx & 0xFF ;
1083 XGINew_SetReg1( pVBInfo->Part4Port , 0x11 , temp ) ;
1084 temp = ( tempbx & 0xFF00 ) >> 8 ;
1085 temp |= ( tempcx & 0x00FF ) ;
1086 XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x10 , ~0x1F , temp ) ;
1087
1088 for( i = 0 ; i < 10 ; i++ )
1089 XGI_LongWait(pVBInfo) ;
1090
1091 tempch = ( tempcx & 0xFF00 ) >> 8;
1092 temp = XGINew_GetReg1( pVBInfo->Part4Port , 0x03 ) ;
1093 temp = temp ^ ( 0x0E ) ;
1094 temp &= tempch ;
1095
1096 if ( temp != tempch )
1097 return( 0 ) ;
1098 else
1099 {
1100 tempbx = 0x3FF ;
1101 tempcx = 0x0804 ;
1102 temp = tempbx & 0xFF ;
1103 XGINew_SetReg1( pVBInfo->Part4Port , 0x11 , temp ) ;
1104 temp = ( tempbx & 0xFF00 ) >> 8 ;
1105 temp |= ( tempcx & 0x00FF ) ;
1106 XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x10 , ~0x1F , temp ) ;
1107
1108 for( i = 0 ; i < 10 ; i++ )
1109 XGI_LongWait(pVBInfo) ;
1110
1111 tempch = ( tempcx & 0xFF00 ) >> 8;
1112 temp = XGINew_GetReg1( pVBInfo->Part4Port , 0x03 ) ;
1113 temp = temp ^ ( 0x0E ) ;
1114 temp &= tempch ;
1115
1116 if ( temp != tempch )
1117 return( 1 ) ;
1118 else
1119 return( 0 ) ;
1120 }
1121}
1122
1123
1124
1125/*
1126;-----------------------------------------------------------------------------
1127; Description: Get Panel support
1128; O/P :
1129; BL: Panel ID=81h for no scaler LVDS
1130; BH: Panel enhanced Mode Count
1131; CX: Panel H. resolution
1132; DX: PAnel V. resolution
1133;-----------------------------------------------------------------------------
1134*/
1135void XGI_XG21Fun14Sub70( PVB_DEVICE_INFO pVBInfo , PX86_REGS pBiosArguments )
1136{
1137
1138 USHORT ModeIdIndex;
1139 USHORT ModeNo;
1140
1141 USHORT EModeCount;
1142 USHORT lvdstableindex;
1143
1144 lvdstableindex = XGI_GetLVDSOEMTableIndex( pVBInfo );
1145 pBiosArguments->h.bl = 0x81;
1146 pBiosArguments->x.cx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHDE;
1147 pBiosArguments->x.dx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE;
1148 EModeCount = 0;
1149
1150 pBiosArguments->x.ax = 0x0014;
1151 for( ModeIdIndex = 0 ; ; ModeIdIndex ++ )
1152 {
1153 ModeNo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeID;
1154 if ( pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeID == 0xFF )
1155 {
1156 pBiosArguments->h.bh = (UCHAR) EModeCount;
1157 return;
1158 }
1159 if ( !XGI_XG21CheckLVDSMode( ModeNo , ModeIdIndex, pVBInfo) )
1160 {
1161 continue;
1162 }
1163 EModeCount++ ;
1164 }
1165}
1166/*(
1167;-----------------------------------------------------------------------------
1168;
1169; Description: Get Panel mode ID for enhanced mode
1170; I/P : BH: EModeIndex ( which < Panel enhanced Mode Count )
1171; O/P :
1172; BL: Mode ID
1173; CX: H. resolution of the assigned by the index
1174; DX: V. resolution of the assigned by the index
1175;
1176;-----------------------------------------------------------------------------
1177*/
1178void XGI_XG21Fun14Sub71( PVB_DEVICE_INFO pVBInfo , PX86_REGS pBiosArguments )
1179{
1180
1181 USHORT EModeCount;
1182 USHORT ModeIdIndex,resindex;
1183 USHORT ModeNo;
1184 USHORT EModeIndex = pBiosArguments->h.bh;
1185
1186 EModeCount = 0;
1187 for( ModeIdIndex = 0 ; ; ModeIdIndex ++ )
1188 {
1189 ModeNo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeID;
1190 if ( pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeID == 0xFF )
1191 {
1192 pBiosArguments->x.ax = 0x0114;
1193 return;
1194 }
1195 if ( !XGI_XG21CheckLVDSMode( ModeNo , ModeIdIndex, pVBInfo) )
1196 {
1197 continue;
1198 }
1199 if (EModeCount == EModeIndex)
1200 {
1201 resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo ) ;
1202 pBiosArguments->h.bl = (UCHAR) ModeNo;
1203 pBiosArguments->x.cx = pVBInfo->ModeResInfo[ resindex ].HTotal ; /* xres->ax */
1204 pBiosArguments->x.dx = pVBInfo->ModeResInfo[ resindex ].VTotal ; /* yres->bx */
1205 pBiosArguments->x.ax = 0x0014;
1206 }
1207 EModeCount++ ;
1208
1209 }
1210
1211}
1212/*
1213;-----------------------------------------------------------------------------
1214;
1215; Description: Validate Panel modes ID support
1216; I/P :
1217; BL: ModeID
1218; O/P :
1219; CX: H. resolution of the assigned by the index
1220; DX: V. resolution of the assigned by the index
1221;
1222;-----------------------------------------------------------------------------
1223*/
1224void XGI_XG21Fun14Sub72( PVB_DEVICE_INFO pVBInfo , PX86_REGS pBiosArguments )
1225{
1226 USHORT ModeIdIndex,resindex;
1227 USHORT ModeNo;
1228
1229
1230 ModeNo = pBiosArguments->h.bl ;
1231 XGI_SearchModeID( ModeNo, &ModeIdIndex, pVBInfo);
1232 if ( !XGI_XG21CheckLVDSMode( ModeNo , ModeIdIndex, pVBInfo) )
1233 {
1234 pBiosArguments->x.cx = 0;
1235 pBiosArguments->x.dx = 0;
1236 pBiosArguments->x.ax = 0x0114;
1237 return;
1238 }
1239 resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo ) ;
1240 if ( ModeNo <= 0x13 )
1241 {
1242 pBiosArguments->x.cx = pVBInfo->StResInfo[ resindex ].HTotal ;
1243 pBiosArguments->x.dx = pVBInfo->StResInfo[ resindex ].VTotal ;
1244 }
1245 else
1246 {
1247 pBiosArguments->x.cx = pVBInfo->ModeResInfo[ resindex ].HTotal ; /* xres->ax */
1248 pBiosArguments->x.dx = pVBInfo->ModeResInfo[ resindex ].VTotal ; /* yres->bx */
1249 }
1250
1251 pBiosArguments->x.ax = 0x0014;
1252
1253}
1254
1255/*
1256;-----------------------------------------------------------------------------
1257; Description: Get Customized Panel misc. information support
1258; I/P : Select
1259; to get panel horizontal timing
1260; to get panel vertical timing
1261; to get channel clock parameter
1262; to get panel misc information
1263;
1264; O/P :
1265; BL: for input Select = 0 ;
1266; BX: *Value1 = Horizontal total
1267; CX: *Value2 = Horizontal front porch
1268; DX: *Value2 = Horizontal sync width
1269; BL: for input Select = 1 ;
1270; BX: *Value1 = Vertical total
1271; CX: *Value2 = Vertical front porch
1272; DX: *Value2 = Vertical sync width
1273; BL: for input Select = 2 ;
1274; BX: Value1 = The first CLK parameter
1275; CX: Value2 = The second CLK parameter
1276; BL: for input Select = 4 ;
1277; BX[15]: *Value1 D[15] VESA V. Polarity
1278; BX[14]: *Value1 D[14] VESA H. Polarity
1279; BX[7]: *Value1 D[7] Panel V. Polarity
1280; BX[6]: *Value1 D[6] Panel H. Polarity
1281;-----------------------------------------------------------------------------
1282*/
1283void XGI_XG21Fun14Sub73( PVB_DEVICE_INFO pVBInfo , PX86_REGS pBiosArguments )
1284{
1285 UCHAR Select;
1286
1287 USHORT lvdstableindex;
1288
1289 lvdstableindex = XGI_GetLVDSOEMTableIndex( pVBInfo );
1290 Select = pBiosArguments->h.bl;
1291
1292 switch (Select)
1293 {
1294 case 0:
1295 pBiosArguments->x.bx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHT;
1296 pBiosArguments->x.cx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHFP;
1297 pBiosArguments->x.dx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHSYNC;
1298 break;
1299 case 1:
1300 pBiosArguments->x.bx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVT;
1301 pBiosArguments->x.cx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVFP;
1302 pBiosArguments->x.dx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVSYNC;
1303 break;
1304 case 2:
1305 pBiosArguments->x.bx = pVBInfo->XG21_LVDSCapList[lvdstableindex].VCLKData1;
1306 pBiosArguments->x.cx = pVBInfo->XG21_LVDSCapList[lvdstableindex].VCLKData2;
1307 break;
1308 case 4:
1309 pBiosArguments->x.bx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDS_Capability;
1310 break;
1311 }
1312
1313 pBiosArguments->x.ax = 0x0014;
1314}
1315
1316
1317void XGI_XG21Fun14( PXGI_HW_DEVICE_INFO pXGIHWDE, PX86_REGS pBiosArguments)
1318{
1319 VB_DEVICE_INFO VBINF;
1320 PVB_DEVICE_INFO pVBInfo = &VBINF;
1321
1322 pVBInfo->IF_DEF_LVDS = 0 ;
1323 pVBInfo->IF_DEF_CH7005 = 0 ;
1324 pVBInfo->IF_DEF_HiVision = 1 ;
1325 pVBInfo->IF_DEF_LCDA = 1 ;
1326 pVBInfo->IF_DEF_CH7017 = 0 ;
1327 pVBInfo->IF_DEF_YPbPr = 1 ;
1328 pVBInfo->IF_DEF_CRT2Monitor = 0 ;
1329 pVBInfo->IF_DEF_VideoCapture = 0 ;
1330 pVBInfo->IF_DEF_ScaleLCD = 0 ;
1331 pVBInfo->IF_DEF_OEMUtil = 0 ;
1332 pVBInfo->IF_DEF_PWD = 0 ;
1333
1334 InitTo330Pointer( pXGIHWDE->jChipType, pVBInfo ) ;
1335 ReadVBIOSTablData( pXGIHWDE->jChipType , pVBInfo) ;
1336
1337 pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ;
1338 pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ;
1339 pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10 ;
1340 pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e ;
1341 pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ;
1342 pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a ;
1343 pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16 ;
1344 pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17 ;
1345 pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18 ;
1346 pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19 ;
1347 pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A ;
1348 pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00 ;
1349 pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04 ;
1350 pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ;
1351 pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12 ;
1352 pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ;
1353 pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2 ;
1354
1355 switch(pBiosArguments->x.ax)
1356 {
1357 case 0x1470:
1358 XGI_XG21Fun14Sub70( pVBInfo , pBiosArguments ) ;
1359 break;
1360 case 0x1471:
1361 XGI_XG21Fun14Sub71( pVBInfo , pBiosArguments ) ;
1362 break;
1363 case 0x1472:
1364 XGI_XG21Fun14Sub72( pVBInfo , pBiosArguments ) ;
1365 break;
1366 case 0x1473:
1367 XGI_XG21Fun14Sub73( pVBInfo , pBiosArguments ) ;
1368 break;
1369 }
1370}
diff --git a/drivers/staging/xgifb/vb_ext.h b/drivers/staging/xgifb/vb_ext.h
new file mode 100644
index 000000000000..9a72f5ecb713
--- /dev/null
+++ b/drivers/staging/xgifb/vb_ext.h
@@ -0,0 +1,32 @@
1#ifndef _VBEXT_
2#define _VBEXT_
3
4struct DWORDREGS {
5 ULONG Eax, Ebx, Ecx, Edx, Esi, Edi, Ebp;
6};
7
8struct WORDREGS {
9 USHORT ax, hi_ax, bx, hi_bx, cx, hi_cx, dx, hi_dx, si, hi_si, di ,hi_di, bp, hi_bp;
10};
11
12struct BYTEREGS {
13 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;
14};
15
16typedef union _X86_REGS {
17 struct DWORDREGS e;
18 struct WORDREGS x;
19 struct BYTEREGS h;
20} X86_REGS, *PX86_REGS;
21
22extern void XGI_XG21Fun14( PXGI_HW_DEVICE_INFO pXGIHWDE, PX86_REGS pBiosArguments);
23extern void XGISetDPMS( PXGI_HW_DEVICE_INFO pXGIHWDE , ULONG VESA_POWER_STATE ) ;
24extern void XGI_GetSenseStatus( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo );
25extern void XGINew_SetModeScratch ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo ) ;
26extern void ReadVBIOSTablData( UCHAR ChipType , PVB_DEVICE_INFO pVBInfo);
27extern USHORT XGINew_SenseLCD(PXGI_HW_DEVICE_INFO,PVB_DEVICE_INFO pVBInfo);
28#ifdef WIN2000
29extern BOOLEAN XGI_DySense( PHW_DEVICE_EXTENSION pHWDE , PUCHAR ujConnectStatus );
30#endif /* WIN2000 */
31
32#endif
diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c
new file mode 100644
index 000000000000..b85ca9ba8076
--- /dev/null
+++ b/drivers/staging/xgifb/vb_init.c
@@ -0,0 +1,3444 @@
1#include "osdef.h"
2#include "vgatypes.h"
3
4
5#ifdef LINUX_KERNEL
6#include <linux/version.h>
7#include <linux/types.h>
8#include <linux/delay.h> /* udelay */
9#include "XGIfb.h"
10/*#if LINUX_VERSxION_CODE >= KERNEL_VERSION(2,5,0)
11#include <video/XGIfb.h>
12#else
13#include <linux/XGIfb.h>
14#endif */
15#endif
16
17#ifdef WIN2000
18#include <dderror.h>
19#include <devioctl.h>
20#include <miniport.h>
21#include <ntddvdeo.h>
22#include <video.h>
23#include "xgiv.h"
24#include "dd_i2c.h"
25#include "tools.h"
26#endif
27
28#include "vb_def.h"
29#include "vb_struct.h"
30#include "vb_util.h"
31#include "vb_setmode.h"
32#include "vb_init.h"
33#include "vb_ext.h"
34
35#ifdef LINUX_XF86
36#include "xf86.h"
37#include "xf86PciInfo.h"
38#include "xgi.h"
39#include "xgi_regs.h"
40#endif
41
42#ifdef LINUX_KERNEL
43#include <asm/io.h>
44#include <linux/types.h>
45#endif
46
47
48
49
50UCHAR XGINew_ChannelAB,XGINew_DataBusWidth;
51
52USHORT XGINew_DRAMType[17][5]={{0x0C,0x0A,0x02,0x40,0x39},{0x0D,0x0A,0x01,0x40,0x48},
53 {0x0C,0x09,0x02,0x20,0x35},{0x0D,0x09,0x01,0x20,0x44},
54 {0x0C,0x08,0x02,0x10,0x31},{0x0D,0x08,0x01,0x10,0x40},
55 {0x0C,0x0A,0x01,0x20,0x34},{0x0C,0x09,0x01,0x08,0x32},
56 {0x0B,0x08,0x02,0x08,0x21},{0x0C,0x08,0x01,0x08,0x30},
57 {0x0A,0x08,0x02,0x04,0x11},{0x0B,0x0A,0x01,0x10,0x28},
58 {0x09,0x08,0x02,0x02,0x01},{0x0B,0x09,0x01,0x08,0x24},
59 {0x0B,0x08,0x01,0x04,0x20},{0x0A,0x08,0x01,0x02,0x10},
60 {0x09,0x08,0x01,0x01,0x00}};
61
62USHORT XGINew_SDRDRAM_TYPE[13][5]=
63{
64{ 2,12, 9,64,0x35},
65{ 1,13, 9,64,0x44},
66{ 2,12, 8,32,0x31},
67{ 2,11, 9,32,0x25},
68{ 1,12, 9,32,0x34},
69{ 1,13, 8,32,0x40},
70{ 2,11, 8,16,0x21},
71{ 1,12, 8,16,0x30},
72{ 1,11, 9,16,0x24},
73{ 1,11, 8, 8,0x20},
74{ 2, 9, 8, 4,0x01},
75{ 1,10, 8, 4,0x10},
76{ 1, 9, 8, 2,0x00}
77};
78
79USHORT XGINew_DDRDRAM_TYPE[4][5]=
80{
81{ 2,12, 9,64,0x35},
82{ 2,12, 8,32,0x31},
83{ 2,11, 8,16,0x21},
84{ 2, 9, 8, 4,0x01}
85};
86USHORT XGINew_DDRDRAM_TYPE340[4][5]=
87{
88{ 2,13, 9,64,0x45},
89{ 2,12, 9,32,0x35},
90{ 2,12, 8,16,0x31},
91{ 2,11, 8, 8,0x21}
92};
93USHORT XGINew_DDRDRAM_TYPE20[12][5]=
94{
95{ 2,14,11,128,0x5D},
96{ 2,14,10,64,0x59},
97{ 2,13,11,64,0x4D},
98{ 2,14, 9,32,0x55},
99{ 2,13,10,32,0x49},
100{ 2,12,11,32,0x3D},
101{ 2,14, 8,16,0x51},
102{ 2,13, 9,16,0x45},
103{ 2,12,10,16,0x39},
104{ 2,13, 8, 8,0x41},
105{ 2,12, 9, 8,0x35},
106{ 2,12, 8, 4,0x31}
107};
108
109void XGINew_SetDRAMSize_340(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO);
110void XGINew_SetDRAMSize_310(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO);
111void XGINew_SetMemoryClock(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
112void XGINew_SetDRAMModeRegister(PVB_DEVICE_INFO );
113void XGINew_SetDRAMModeRegister340( PXGI_HW_DEVICE_INFO HwDeviceExtension );
114void XGINew_SetDRAMDefaultRegister340(PXGI_HW_DEVICE_INFO HwDeviceExtension, ULONG, PVB_DEVICE_INFO );
115UCHAR XGINew_GetXG20DRAMType( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo);
116BOOLEAN XGIInitNew( PXGI_HW_DEVICE_INFO HwDeviceExtension) ;
117
118int XGINew_DDRSizing340( PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO );
119void XGINew_DisableRefresh( PXGI_HW_DEVICE_INFO ,PVB_DEVICE_INFO) ;
120void XGINew_CheckBusWidth_310( PVB_DEVICE_INFO) ;
121int XGINew_SDRSizing(PVB_DEVICE_INFO);
122int XGINew_DDRSizing( PVB_DEVICE_INFO );
123void XGINew_EnableRefresh( PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO);
124int XGINew_RAMType; /*int ModeIDOffset,StandTable,CRT1Table,ScreenOffset,REFIndex;*/
125ULONG UNIROM; /* UNIROM */
126BOOLEAN ChkLFB( PVB_DEVICE_INFO );
127void XGINew_Delay15us(ULONG);
128void SetPowerConsume (PXGI_HW_DEVICE_INFO HwDeviceExtension,ULONG XGI_P3d4Port);
129void ReadVBIOSTablData( UCHAR ChipType , PVB_DEVICE_INFO pVBInfo);
130void XGINew_DDR1x_MRS_XG20( ULONG P3c4 , PVB_DEVICE_INFO pVBInfo);
131void XGINew_SetDRAMModeRegister_XG20( PXGI_HW_DEVICE_INFO HwDeviceExtension );
132void XGINew_SetDRAMModeRegister_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension );
133void XGINew_ChkSenseStatus ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo ) ;
134void XGINew_SetModeScratch ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo ) ;
135void XGINew_GetXG21Sense(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo) ;
136UCHAR GetXG21FPBits(PVB_DEVICE_INFO pVBInfo);
137void XGINew_GetXG27Sense(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo) ;
138UCHAR GetXG27FPBits(PVB_DEVICE_INFO pVBInfo);
139
140#ifdef WIN2000
141/* [Billy] 2007/05/20 For CH7007 */
142extern UCHAR CH7007TVReg_UNTSC[][8],CH7007TVReg_ONTSC[][8],CH7007TVReg_UPAL[][8],CH7007TVReg_OPAL[][8];
143extern UCHAR XGI7007_CHTVVCLKUNTSC[],XGI7007_CHTVVCLKONTSC[],XGI7007_CHTVVCLKUPAL[],XGI7007_CHTVVCLKOPAL[];
144#endif
145
146#ifdef LINUX_KERNEL
147void DelayUS(ULONG MicroSeconds)
148{
149 udelay(MicroSeconds);
150}
151#endif
152
153/* --------------------------------------------------------------------- */
154/* Function : XGIInitNew */
155/* Input : */
156/* Output : */
157/* Description : */
158/* --------------------------------------------------------------------- */
159BOOLEAN XGIInitNew( PXGI_HW_DEVICE_INFO HwDeviceExtension )
160{
161
162 VB_DEVICE_INFO VBINF;
163 PVB_DEVICE_INFO pVBInfo = &VBINF;
164 UCHAR i , temp = 0 , temp1 ;
165 // VBIOSVersion[ 5 ] ;
166 PUCHAR volatile pVideoMemory;
167
168 /* ULONG j, k ; */
169
170 PXGI_DSReg pSR ;
171
172 ULONG Temp ;
173
174 pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
175
176 pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ;
177
178 pVBInfo->BaseAddr = (ULONG)HwDeviceExtension->pjIOAddress ;
179
180 pVideoMemory = ( PUCHAR )pVBInfo->ROMAddr;
181
182
183// Newdebugcode( 0x99 ) ;
184
185
186 /* if ( pVBInfo->ROMAddr == 0 ) */
187 /* return( FALSE ) ; */
188
189 if ( pVBInfo->FBAddr == 0 )
190{
191 printk("\n pVBInfo->FBAddr == 0 ");
192 return( FALSE ) ;
193}
194printk("1");
195 if ( pVBInfo->BaseAddr == 0 )
196{
197 printk("\npVBInfo->BaseAddr == 0 ");
198 return( FALSE ) ;
199}
200printk("2");
201
202 XGINew_SetReg3( ( pVBInfo->BaseAddr + 0x12 ) , 0x67 ) ; /* 3c2 <- 67 ,ynlai */
203
204 pVBInfo->ISXPDOS = 0 ;
205printk("3");
206
207if ( !HwDeviceExtension->bIntegratedMMEnabled )
208{
209 return( FALSE ) ; /* alan */
210}
211printk("4");
212
213// XGI_MemoryCopy( VBIOSVersion , HwDeviceExtension->szVBIOSVer , 4 ) ;
214
215 // VBIOSVersion[ 4 ] = 0x0 ;
216
217 /* 09/07/99 modify by domao */
218
219 pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ;
220 pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ;
221 pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10 ;
222 pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e ;
223 pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ;
224 pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a ;
225 pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16 ;
226 pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17 ;
227 pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18 ;
228 pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19 ;
229 pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A ;
230 pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00 ;
231 pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04 ;
232 pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ;
233 pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12 ;
234 pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ;
235 pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2 ;
236printk("5");
237
238 if ( HwDeviceExtension->jChipType < XG20 ) /* kuku 2004/06/25 */
239 XGI_GetVBType( pVBInfo ) ; /* Run XGI_GetVBType before InitTo330Pointer */
240
241 InitTo330Pointer( HwDeviceExtension->jChipType, pVBInfo ) ;
242
243 /* ReadVBIOSData */
244 ReadVBIOSTablData( HwDeviceExtension->jChipType , pVBInfo) ;
245
246 /* 1.Openkey */
247 XGINew_SetReg1( pVBInfo->P3c4 , 0x05 , 0x86 ) ;
248printk("6");
249
250 /* GetXG21Sense (GPIO) */
251 if ( HwDeviceExtension->jChipType == XG21 )
252 {
253 XGINew_GetXG21Sense(HwDeviceExtension, pVBInfo) ;
254 }
255 if ( HwDeviceExtension->jChipType == XG27 )
256 {
257 XGINew_GetXG27Sense(HwDeviceExtension, pVBInfo) ;
258 }
259printk("7");
260
261 /* 2.Reset Extended register */
262
263 for( i = 0x06 ; i < 0x20 ; i++ )
264 XGINew_SetReg1( pVBInfo->P3c4 , i , 0 ) ;
265
266 for( i = 0x21 ; i <= 0x27 ; i++ )
267 XGINew_SetReg1( pVBInfo->P3c4 , i , 0 ) ;
268
269 /* for( i = 0x06 ; i <= 0x27 ; i++ ) */
270 /* XGINew_SetReg1( pVBInfo->P3c4 , i , 0 ) ; */
271
272printk("8");
273
274 if(( HwDeviceExtension->jChipType >= XG20 ) || ( HwDeviceExtension->jChipType >= XG40))
275 {
276 for( i = 0x31 ; i <= 0x3B ; i++ )
277 XGINew_SetReg1( pVBInfo->P3c4 , i , 0 ) ;
278 }
279 else
280 {
281 for( i = 0x31 ; i <= 0x3D ; i++ )
282 XGINew_SetReg1( pVBInfo->P3c4 , i , 0 ) ;
283 }
284printk("9");
285
286 if ( HwDeviceExtension->jChipType == XG42 ) /* [Hsuan] 2004/08/20 Auto over driver for XG42 */
287 XGINew_SetReg1( pVBInfo->P3c4 , 0x3B , 0xC0 ) ;
288
289 /* for( i = 0x30 ; i <= 0x3F ; i++ ) */
290 /* XGINew_SetReg1( pVBInfo->P3d4 , i , 0 ) ; */
291
292 for( i = 0x79 ; i <= 0x7C ; i++ )
293 XGINew_SetReg1( pVBInfo->P3d4 , i , 0 ) ; /* shampoo 0208 */
294
295printk("10");
296
297 if ( HwDeviceExtension->jChipType >= XG20 )
298 XGINew_SetReg1( pVBInfo->P3d4 , 0x97 , *pVBInfo->pXGINew_CR97 ) ;
299
300 /* 3.SetMemoryClock
301
302 if ( HwDeviceExtension->jChipType >= XG40 )
303 XGINew_RAMType = ( int )XGINew_GetXG20DRAMType( HwDeviceExtension , pVBInfo) ;
304
305 if ( HwDeviceExtension->jChipType < XG40 )
306 XGINew_SetMemoryClock( HwDeviceExtension , pVBInfo ) ; */
307
308printk("11");
309
310 /* 4.SetDefExt1Regs begin */
311 XGINew_SetReg1( pVBInfo->P3c4 , 0x07 , *pVBInfo->pSR07 ) ;
312 if ( HwDeviceExtension->jChipType == XG27 )
313 {
314 XGINew_SetReg1( pVBInfo->P3c4 , 0x40 , *pVBInfo->pSR40 ) ;
315 XGINew_SetReg1( pVBInfo->P3c4 , 0x41 , *pVBInfo->pSR41 ) ;
316 }
317 XGINew_SetReg1( pVBInfo->P3c4 , 0x11 , 0x0F ) ;
318 XGINew_SetReg1( pVBInfo->P3c4 , 0x1F , *pVBInfo->pSR1F ) ;
319 /* XGINew_SetReg1( pVBInfo->P3c4 , 0x20 , 0x20 ) ; */
320 XGINew_SetReg1( pVBInfo->P3c4 , 0x20 , 0xA0 ) ; /* alan, 2001/6/26 Frame buffer can read/write SR20 */
321 XGINew_SetReg1( pVBInfo->P3c4 , 0x36 , 0x70 ) ; /* Hsuan, 2006/01/01 H/W request for slow corner chip */
322 if ( HwDeviceExtension->jChipType == XG27 ) /* Alan 12/07/2006 */
323 XGINew_SetReg1( pVBInfo->P3c4 , 0x36 , *pVBInfo->pSR36 ) ;
324
325 /* SR11 = 0x0F ; */
326 /* XGINew_SetReg1( pVBInfo->P3c4 , 0x11 , SR11 ) ; */
327
328printk("12");
329
330 if ( HwDeviceExtension->jChipType < XG20 ) /* kuku 2004/06/25 */
331 {
332// /* Set AGP Rate */
333// temp1 = XGINew_GetReg1( pVBInfo->P3c4 , 0x3B ) ;
334// temp1 &= 0x02 ;
335// if ( temp1 == 0x02 )
336// {
337// XGINew_SetReg4( 0xcf8 , 0x80000000 ) ;
338// ChipsetID = XGINew_GetReg3( 0x0cfc ) ;
339// XGINew_SetReg4( 0xcf8 , 0x8000002C ) ;
340// VendorID = XGINew_GetReg3( 0x0cfc ) ;
341// VendorID &= 0x0000FFFF ;
342// XGINew_SetReg4( 0xcf8 , 0x8001002C ) ;
343// GraphicVendorID = XGINew_GetReg3( 0x0cfc ) ;
344// GraphicVendorID &= 0x0000FFFF;
345//
346// if ( ChipsetID == 0x7301039 )
347/// XGINew_SetReg1( pVBInfo->P3d4 , 0x5F , 0x09 ) ;
348//
349// ChipsetID &= 0x0000FFFF ;
350///
351// if ( ( ChipsetID == 0x700E ) || ( ChipsetID == 0x1022 ) || ( ChipsetID == 0x1106 ) || ( ChipsetID == 0x10DE ) )
352// {
353// if ( ChipsetID == 0x1106 )
354// {
355// if ( ( VendorID == 0x1019 ) && ( GraphicVendorID == 0x1019 ) )
356// XGINew_SetReg1( pVBInfo->P3d4 , 0x5F , 0x0D ) ;
357// else
358// XGINew_SetReg1( pVBInfo->P3d4 , 0x5F , 0x0B ) ;
359// }
360// else
361// XGINew_SetReg1( pVBInfo->P3d4 , 0x5F , 0x0B ) ;
362// }
363// }
364
365printk("13");
366
367 if ( HwDeviceExtension->jChipType >= XG40 )
368 {
369 /* Set AGP customize registers (in SetDefAGPRegs) Start */
370 for( i = 0x47 ; i <= 0x4C ; i++ )
371 XGINew_SetReg1( pVBInfo->P3d4 , i , pVBInfo->AGPReg[ i - 0x47 ] ) ;
372
373 for( i = 0x70 ; i <= 0x71 ; i++ )
374 XGINew_SetReg1( pVBInfo->P3d4 , i , pVBInfo->AGPReg[ 6 + i - 0x70 ] ) ;
375
376 for( i = 0x74 ; i <= 0x77 ; i++ )
377 XGINew_SetReg1( pVBInfo->P3d4 , i , pVBInfo->AGPReg[ 8 + i - 0x74 ] ) ;
378 /* Set AGP customize registers (in SetDefAGPRegs) End */
379 /*[Hsuan]2004/12/14 AGP Input Delay Adjustment on 850 */
380// XGINew_SetReg4( 0xcf8 , 0x80000000 ) ;
381// ChipsetID = XGINew_GetReg3( 0x0cfc ) ;
382// if ( ChipsetID == 0x25308086 )
383// XGINew_SetReg1( pVBInfo->P3d4 , 0x77 , 0xF0 ) ;
384
385 HwDeviceExtension->pQueryVGAConfigSpace( HwDeviceExtension , 0x50 , 0 , &Temp ) ; /* Get */
386 Temp >>= 20 ;
387 Temp &= 0xF ;
388
389 if ( Temp == 1 )
390 XGINew_SetReg1( pVBInfo->P3d4 , 0x48 , 0x20 ) ; /* CR48 */
391 }
392printk("14");
393
394 if ( HwDeviceExtension->jChipType < XG40 )
395 XGINew_SetReg1( pVBInfo->P3d4 , 0x49 , pVBInfo->CR49[ 0 ] ) ;
396 } /* != XG20 */
397
398 /* Set PCI */
399 XGINew_SetReg1( pVBInfo->P3c4 , 0x23 , *pVBInfo->pSR23 ) ;
400 XGINew_SetReg1( pVBInfo->P3c4 , 0x24 , *pVBInfo->pSR24 ) ;
401 XGINew_SetReg1( pVBInfo->P3c4 , 0x25 , pVBInfo->SR25[ 0 ] ) ;
402printk("15");
403
404 if ( HwDeviceExtension->jChipType < XG20 ) /* kuku 2004/06/25 */
405 {
406 /* Set VB */
407 XGI_UnLockCRT2( HwDeviceExtension, pVBInfo) ;
408 XGINew_SetRegANDOR( pVBInfo->Part0Port , 0x3F , 0xEF , 0x00 ) ; /* alan, disable VideoCapture */
409 XGINew_SetReg1( pVBInfo->Part1Port , 0x00 , 0x00 ) ;
410 temp1 = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x7B ) ; /* chk if BCLK>=100MHz */
411 temp = ( UCHAR )( ( temp1 >> 4 ) & 0x0F ) ;
412
413
414 XGINew_SetReg1( pVBInfo->Part1Port , 0x02 , ( *pVBInfo->pCRT2Data_1_2 ) ) ;
415
416printk("16");
417
418 XGINew_SetReg1( pVBInfo->Part1Port , 0x2E , 0x08 ) ; /* use VB */
419 } /* != XG20 */
420
421
422 XGINew_SetReg1( pVBInfo->P3c4 , 0x27 , 0x1F ) ;
423
424 if ( ( HwDeviceExtension->jChipType == XG42 ) && XGINew_GetXG20DRAMType( HwDeviceExtension , pVBInfo) != 0 ) /* Not DDR */
425 {
426 XGINew_SetReg1( pVBInfo->P3c4 , 0x31 , ( *pVBInfo->pSR31 & 0x3F ) | 0x40 ) ;
427 XGINew_SetReg1( pVBInfo->P3c4 , 0x32 , ( *pVBInfo->pSR32 & 0xFC ) | 0x01 ) ;
428 }
429 else
430 {
431 XGINew_SetReg1( pVBInfo->P3c4 , 0x31 , *pVBInfo->pSR31 ) ;
432 XGINew_SetReg1( pVBInfo->P3c4 , 0x32 , *pVBInfo->pSR32 ) ;
433 }
434 XGINew_SetReg1( pVBInfo->P3c4 , 0x33 , *pVBInfo->pSR33 ) ;
435printk("17");
436
437/*
438 if ( HwDeviceExtension->jChipType >= XG40 )
439 SetPowerConsume ( HwDeviceExtension , pVBInfo->P3c4); */
440
441 if ( HwDeviceExtension->jChipType < XG20 ) /* kuku 2004/06/25 */
442 {
443 if ( XGI_BridgeIsOn( pVBInfo ) == 1 )
444 {
445 if ( pVBInfo->IF_DEF_LVDS == 0 )
446 {
447 XGINew_SetReg1( pVBInfo->Part2Port , 0x00 , 0x1C ) ;
448 XGINew_SetReg1( pVBInfo->Part4Port , 0x0D , *pVBInfo->pCRT2Data_4_D ) ;
449 XGINew_SetReg1( pVBInfo->Part4Port , 0x0E , *pVBInfo->pCRT2Data_4_E ) ;
450 XGINew_SetReg1( pVBInfo->Part4Port , 0x10 , *pVBInfo->pCRT2Data_4_10 ) ;
451 XGINew_SetReg1( pVBInfo->Part4Port , 0x0F , 0x3F ) ;
452 }
453
454 XGI_LockCRT2( HwDeviceExtension, pVBInfo ) ;
455 }
456 } /* != XG20 */
457printk("18");
458
459 if ( HwDeviceExtension->jChipType < XG40 )
460 XGINew_SetReg1( pVBInfo->P3d4 , 0x83 , 0x00 ) ;
461printk("181");
462
463 if ( HwDeviceExtension->bSkipSense == FALSE )
464 {
465printk("182");
466
467 XGI_SenseCRT1(pVBInfo) ;
468
469printk("183");
470 /* XGINew_DetectMonitor( HwDeviceExtension ) ; */
471pVBInfo->IF_DEF_CH7007 = 0;
472 if ( ( HwDeviceExtension->jChipType == XG21 ) && (pVBInfo->IF_DEF_CH7007) )
473 {
474printk("184");
475 XGI_GetSenseStatus( HwDeviceExtension , pVBInfo ) ; /* sense CRT2 */
476printk("185");
477
478 }
479 if ( HwDeviceExtension->jChipType == XG21 )
480 {
481printk("186");
482
483 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , ~Monitor1Sense , Monitor1Sense ) ; /* Z9 default has CRT */
484 temp = GetXG21FPBits( pVBInfo ) ;
485 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x37 , ~0x01, temp ) ;
486printk("187");
487
488 }
489 if ( HwDeviceExtension->jChipType == XG27 )
490 {
491 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , ~Monitor1Sense , Monitor1Sense ) ; /* Z9 default has CRT */
492 temp = GetXG27FPBits( pVBInfo ) ;
493 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x37 , ~0x03, temp ) ;
494 }
495 }
496printk("19");
497
498 if ( HwDeviceExtension->jChipType >= XG40 )
499 {
500 if ( HwDeviceExtension->jChipType >= XG40 )
501 {
502 XGINew_RAMType = ( int )XGINew_GetXG20DRAMType( HwDeviceExtension , pVBInfo ) ;
503 }
504
505 XGINew_SetDRAMDefaultRegister340( HwDeviceExtension , pVBInfo->P3d4, pVBInfo ) ;
506
507 if ( HwDeviceExtension->bSkipDramSizing == TRUE )
508 {
509 pSR = HwDeviceExtension->pSR ;
510 if ( pSR!=NULL )
511 {
512 while( pSR->jIdx != 0xFF )
513 {
514 XGINew_SetReg1( pVBInfo->P3c4 , pSR->jIdx , pSR->jVal ) ;
515 pSR++ ;
516 }
517 }
518 /* XGINew_SetDRAMModeRegister340( pVBInfo ) ; */
519 } /* SkipDramSizing */
520 else
521 {
522#if 0
523 if ( HwDeviceExtension->jChipType == XG20 )
524 {
525 XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , pVBInfo->SR15[0][XGINew_RAMType] ) ;
526 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , pVBInfo->SR15[1][XGINew_RAMType] ) ;
527 XGINew_SetReg1( pVBInfo->P3c4 , 0x20 , 0x20 ) ;
528 }
529 else
530#endif
531{
532printk("20");
533
534 XGINew_SetDRAMSize_340( HwDeviceExtension , pVBInfo) ;
535}
536printk("21");
537
538 }
539 } /* XG40 */
540
541printk("22");
542
543
544 /* SetDefExt2Regs begin */
545/*
546 AGP = 1 ;
547 temp =( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x3A ) ;
548 temp &= 0x30 ;
549 if ( temp == 0x30 )
550 AGP = 0 ;
551
552 if ( AGP == 0 )
553 *pVBInfo->pSR21 &= 0xEF ;
554
555 XGINew_SetReg1( pVBInfo->P3c4 , 0x21 , *pVBInfo->pSR21 ) ;
556 if ( AGP == 1 )
557 *pVBInfo->pSR22 &= 0x20 ;
558 XGINew_SetReg1( pVBInfo->P3c4 , 0x22 , *pVBInfo->pSR22 ) ;
559*/
560
561// base = 0x80000000 ;
562// OutPortLong( 0xcf8 , base ) ;
563// Temp = ( InPortLong( 0xcfc ) & 0xFFFF ) ;
564// if ( Temp == 0x1039 )
565// {
566 XGINew_SetReg1( pVBInfo->P3c4 , 0x22 , ( UCHAR )( ( *pVBInfo->pSR22 ) & 0xFE ) ) ;
567// }
568// else
569// {
570// XGINew_SetReg1( pVBInfo->P3c4 , 0x22 , *pVBInfo->pSR22 ) ;
571// }
572
573 XGINew_SetReg1( pVBInfo->P3c4 , 0x21 , *pVBInfo->pSR21 ) ;
574
575printk("23");
576
577
578 XGINew_ChkSenseStatus ( HwDeviceExtension , pVBInfo ) ;
579 XGINew_SetModeScratch ( HwDeviceExtension , pVBInfo ) ;
580
581printk("24");
582
583
584XGINew_SetReg1( pVBInfo->P3d4 , 0x8c , 0x87);
585XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x31);
586printk("25");
587
588 return( TRUE ) ;
589} /* end of init */
590
591
592
593
594
595/* ============== alan ====================== */
596
597/* --------------------------------------------------------------------- */
598/* Function : XGINew_GetXG20DRAMType */
599/* Input : */
600/* Output : */
601/* Description : */
602/* --------------------------------------------------------------------- */
603UCHAR XGINew_GetXG20DRAMType( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
604{
605 UCHAR data, temp ;
606
607 if ( HwDeviceExtension->jChipType < XG20 )
608 {
609 if ( *pVBInfo->pSoftSetting & SoftDRAMType )
610 {
611 data = *pVBInfo->pSoftSetting & 0x07 ;
612 return( data ) ;
613 }
614 else
615 {
616 data = XGINew_GetReg1( pVBInfo->P3c4 , 0x39 ) & 0x02 ;
617
618 if ( data == 0 )
619 data = ( XGINew_GetReg1( pVBInfo->P3c4 , 0x3A ) & 0x02 ) >> 1 ;
620
621 return( data ) ;
622 }
623 }
624 else if ( HwDeviceExtension->jChipType == XG27 )
625 {
626 if ( *pVBInfo->pSoftSetting & SoftDRAMType )
627 {
628 data = *pVBInfo->pSoftSetting & 0x07 ;
629 return( data ) ;
630 }
631 temp = XGINew_GetReg1( pVBInfo->P3c4 , 0x3B ) ;
632
633 if (( temp & 0x88 )==0x80) /* SR3B[7][3]MAA15 MAA11 (Power on Trapping) */
634 data = 0 ; /*DDR*/
635 else
636 data = 1 ; /*DDRII*/
637 return( data ) ;
638 }
639 else if ( HwDeviceExtension->jChipType == XG21 )
640 {
641 XGINew_SetRegAND( pVBInfo->P3d4 , 0xB4 , ~0x02 ) ; /* Independent GPIO control */
642 DelayUS(800);
643 XGINew_SetRegOR( pVBInfo->P3d4 , 0x4A , 0x80 ) ; /* Enable GPIOH read */
644 temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x48 ) ; /* GPIOF 0:DVI 1:DVO */
645// HOTPLUG_SUPPORT
646// for current XG20 & XG21, GPIOH is floating, driver will fix DDR temporarily
647 if ( temp & 0x01 ) /* DVI read GPIOH */
648 data = 1 ; /*DDRII*/
649 else
650 data = 0 ; /*DDR*/
651//~HOTPLUG_SUPPORT
652 XGINew_SetRegOR( pVBInfo->P3d4 , 0xB4 , 0x02 ) ;
653 return( data ) ;
654 }
655 else
656 {
657 data = XGINew_GetReg1( pVBInfo->P3d4 , 0x97 ) & 0x01 ;
658
659 if ( data == 1 )
660 data ++ ;
661
662 return( data );
663 }
664}
665
666
667/* --------------------------------------------------------------------- */
668/* Function : XGINew_Get310DRAMType */
669/* Input : */
670/* Output : */
671/* Description : */
672/* --------------------------------------------------------------------- */
673UCHAR XGINew_Get310DRAMType(PVB_DEVICE_INFO pVBInfo)
674{
675 UCHAR data ;
676
677 /* index = XGINew_GetReg1( pVBInfo->P3c4 , 0x1A ) ; */
678 /* index &= 07 ; */
679
680 if ( *pVBInfo->pSoftSetting & SoftDRAMType )
681 data = *pVBInfo->pSoftSetting & 0x03 ;
682 else
683 data = XGINew_GetReg1( pVBInfo->P3c4 , 0x3a ) & 0x03 ;
684
685 return( data ) ;
686}
687
688
689
690/* --------------------------------------------------------------------- */
691/* Function : XGINew_Delay15us */
692/* Input : */
693/* Output : */
694/* Description : */
695/* --------------------------------------------------------------------- */
696/*
697void XGINew_Delay15us(ULONG ulMicrsoSec)
698{
699}
700*/
701
702
703/* --------------------------------------------------------------------- */
704/* Function : XGINew_SDR_MRS */
705/* Input : */
706/* Output : */
707/* Description : */
708/* --------------------------------------------------------------------- */
709void XGINew_SDR_MRS( PVB_DEVICE_INFO pVBInfo )
710{
711 USHORT data ;
712
713 data = XGINew_GetReg1( pVBInfo->P3c4 , 0x16 ) ;
714 data &= 0x3F ; /* SR16 D7=0,D6=0 */
715 XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ; /* enable mode register set(MRS) low */
716 /* XGINew_Delay15us( 0x100 ) ; */
717 data |= 0x80 ; /* SR16 D7=1,D6=0 */
718 XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ; /* enable mode register set(MRS) high */
719 /* XGINew_Delay15us( 0x100 ) ; */
720}
721
722
723/* --------------------------------------------------------------------- */
724/* Function : XGINew_DDR1x_MRS_340 */
725/* Input : */
726/* Output : */
727/* Description : */
728/* --------------------------------------------------------------------- */
729void XGINew_DDR1x_MRS_340( ULONG P3c4 , PVB_DEVICE_INFO pVBInfo)
730{
731 XGINew_SetReg1( P3c4 , 0x18 , 0x01 ) ;
732 XGINew_SetReg1( P3c4 , 0x19 , 0x20 ) ;
733 XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ;
734 XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ;
735
736 if ( *pVBInfo->pXGINew_DRAMTypeDefinition != 0x0C ) /* Samsung F Die */
737 {
738 DelayUS( 3000 ) ; /* Delay 67 x 3 Delay15us */
739 XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ;
740 XGINew_SetReg1( P3c4 , 0x19 , 0x20 ) ;
741 XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ;
742 XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ;
743 }
744
745 DelayUS( 60 ) ;
746 XGINew_SetReg1( P3c4 , 0x18 , pVBInfo->SR15[ 2 ][ XGINew_RAMType ] ) ; /* SR18 */
747 XGINew_SetReg1( P3c4 , 0x19 , 0x01 ) ;
748 XGINew_SetReg1( P3c4 , 0x16 , pVBInfo->SR16[ 0 ] ) ;
749 XGINew_SetReg1( P3c4 , 0x16 , pVBInfo->SR16[ 1 ] ) ;
750 DelayUS( 1000 ) ;
751 XGINew_SetReg1( P3c4 , 0x1B , 0x03 ) ;
752 DelayUS( 500 ) ;
753 XGINew_SetReg1( P3c4 , 0x18 , pVBInfo->SR15[ 2 ][ XGINew_RAMType ] ) ; /* SR18 */
754 XGINew_SetReg1( P3c4 , 0x19 , 0x00 ) ;
755 XGINew_SetReg1( P3c4 , 0x16 , pVBInfo->SR16[ 2 ] ) ;
756 XGINew_SetReg1( P3c4 , 0x16 , pVBInfo->SR16[ 3 ] ) ;
757 XGINew_SetReg1( P3c4 , 0x1B , 0x00 ) ;
758}
759
760
761/* --------------------------------------------------------------------- */
762/* Function : XGINew_DDR2x_MRS_340 */
763/* Input : */
764/* Output : */
765/* Description : */
766/* --------------------------------------------------------------------- */
767void XGINew_DDR2x_MRS_340( ULONG P3c4 , PVB_DEVICE_INFO pVBInfo)
768{
769 XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ;
770 XGINew_SetReg1( P3c4 , 0x19 , 0x20 ) ;
771 XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ;
772 XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ;
773 DelayUS( 60 ) ;
774 XGINew_SetReg1( P3c4 , 0x18 , pVBInfo->SR15[ 2 ][ XGINew_RAMType ] ) ; /* SR18 */
775 /* XGINew_SetReg1( P3c4 , 0x18 , 0x31 ) ; */
776 XGINew_SetReg1( P3c4 , 0x19 , 0x01 ) ;
777 XGINew_SetReg1( P3c4 , 0x16 , 0x05 ) ;
778 XGINew_SetReg1( P3c4 , 0x16 , 0x85 ) ;
779 DelayUS( 1000 ) ;
780 XGINew_SetReg1( P3c4 , 0x1B , 0x03 ) ;
781 DelayUS( 500 ) ;
782 /* XGINew_SetReg1( P3c4 , 0x18 , 0x31 ) ; */
783 XGINew_SetReg1( P3c4 , 0x18 , pVBInfo->SR15[ 2 ][ XGINew_RAMType ] ) ; /* SR18 */
784 XGINew_SetReg1( P3c4 , 0x19 , 0x00 ) ;
785 XGINew_SetReg1( P3c4 , 0x16 , 0x05 ) ;
786 XGINew_SetReg1( P3c4 , 0x16 , 0x85 ) ;
787 XGINew_SetReg1( P3c4 , 0x1B , 0x00 ) ;
788}
789
790/* --------------------------------------------------------------------- */
791/* Function : XGINew_DDRII_Bootup_XG27 */
792/* Input : */
793/* Output : */
794/* Description : */
795/* --------------------------------------------------------------------- */
796void XGINew_DDRII_Bootup_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension , ULONG P3c4 , PVB_DEVICE_INFO pVBInfo)
797{
798 ULONG P3d4 = P3c4 + 0x10 ;
799 XGINew_RAMType = ( int )XGINew_GetXG20DRAMType( HwDeviceExtension , pVBInfo ) ;
800 XGINew_SetMemoryClock( HwDeviceExtension , pVBInfo ) ;
801
802 /* Set Double Frequency */
803 /* XGINew_SetReg1( P3d4 , 0x97 , 0x11 ) ; */ /* CR97 */
804 XGINew_SetReg1( P3d4 , 0x97 , *pVBInfo->pXGINew_CR97 ) ; /* CR97 */
805
806 DelayUS( 200 ) ;
807
808 XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ; /* Set SR18 */ //EMRS2
809 XGINew_SetReg1( P3c4 , 0x19 , 0x80 ) ; /* Set SR19 */
810 XGINew_SetReg1( P3c4 , 0x16 , 0x20 ) ; /* Set SR16 */
811 DelayUS( 15 ) ;
812 XGINew_SetReg1( P3c4 , 0x16 , 0xA0 ) ; /* Set SR16 */
813 DelayUS( 15 ) ;
814
815 XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ; /* Set SR18 */ //EMRS3
816 XGINew_SetReg1( P3c4 , 0x19 , 0xC0 ) ; /* Set SR19 */
817 XGINew_SetReg1( P3c4 , 0x16 , 0x20 ) ; /* Set SR16 */
818 DelayUS( 15 ) ;
819 XGINew_SetReg1( P3c4 , 0x16 , 0xA0 ) ; /* Set SR16 */
820 DelayUS( 15) ;
821
822 XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ; /* Set SR18 */ //EMRS1
823 XGINew_SetReg1( P3c4 , 0x19 , 0x40 ) ; /* Set SR19 */
824 XGINew_SetReg1( P3c4 , 0x16 , 0x20 ) ; /* Set SR16 */
825 DelayUS( 30 ) ;
826 XGINew_SetReg1( P3c4 , 0x16 , 0xA0 ) ; /* Set SR16 */
827 DelayUS( 15 ) ;
828
829 XGINew_SetReg1( P3c4 , 0x18 , 0x42 ) ; /* Set SR18 */ //MRS, DLL Enable
830 XGINew_SetReg1( P3c4 , 0x19 , 0x0A ) ; /* Set SR19 */
831 XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ; /* Set SR16 */
832 DelayUS( 30 ) ;
833 XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ; /* Set SR16 */
834 XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ; /* Set SR16 */
835 /* DelayUS( 15 ) ; */
836
837 XGINew_SetReg1( P3c4 , 0x1B , 0x04 ) ; /* Set SR1B */
838 DelayUS( 60 ) ;
839 XGINew_SetReg1( P3c4 , 0x1B , 0x00 ) ; /* Set SR1B */
840
841 XGINew_SetReg1( P3c4 , 0x18 , 0x42 ) ; /* Set SR18 */ //MRS, DLL Reset
842 XGINew_SetReg1( P3c4 , 0x19 , 0x08 ) ; /* Set SR19 */
843 XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ; /* Set SR16 */
844
845 DelayUS( 30 ) ;
846 XGINew_SetReg1( P3c4 , 0x16 , 0x83 ) ; /* Set SR16 */
847 DelayUS( 15 ) ;
848
849 XGINew_SetReg1( P3c4 , 0x18 , 0x80 ) ; /* Set SR18 */ //MRS, ODT
850 XGINew_SetReg1( P3c4 , 0x19 , 0x46 ) ; /* Set SR19 */
851 XGINew_SetReg1( P3c4 , 0x16 , 0x20 ) ; /* Set SR16 */
852 DelayUS( 30 ) ;
853 XGINew_SetReg1( P3c4 , 0x16 , 0xA0 ) ; /* Set SR16 */
854 DelayUS( 15 ) ;
855
856 XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ; /* Set SR18 */ //EMRS
857 XGINew_SetReg1( P3c4 , 0x19 , 0x40 ) ; /* Set SR19 */
858 XGINew_SetReg1( P3c4 , 0x16 , 0x20 ) ; /* Set SR16 */
859 DelayUS( 30 ) ;
860 XGINew_SetReg1( P3c4 , 0x16 , 0xA0 ) ; /* Set SR16 */
861 DelayUS( 15 ) ;
862
863 XGINew_SetReg1( P3c4 , 0x1B , 0x04 ) ; /* Set SR1B refresh control 000:close; 010:open */
864 DelayUS( 200 ) ;
865
866
867}
868/* --------------------------------------------------------------------- */
869/* Function : XGINew_DDR2_MRS_XG20 */
870/* Input : */
871/* Output : */
872/* Description : */
873/* --------------------------------------------------------------------- */
874void XGINew_DDR2_MRS_XG20( PXGI_HW_DEVICE_INFO HwDeviceExtension , ULONG P3c4 , PVB_DEVICE_INFO pVBInfo)
875{
876 ULONG P3d4 = P3c4 + 0x10 ;
877
878 XGINew_RAMType = ( int )XGINew_GetXG20DRAMType( HwDeviceExtension , pVBInfo ) ;
879 XGINew_SetMemoryClock( HwDeviceExtension , pVBInfo ) ;
880
881 XGINew_SetReg1( P3d4 , 0x97 , 0x11 ) ; /* CR97 */
882
883 DelayUS( 200 ) ;
884 XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ; /* EMRS2 */
885 XGINew_SetReg1( P3c4 , 0x19 , 0x80 ) ;
886 XGINew_SetReg1( P3c4 , 0x16 , 0x05 ) ;
887 XGINew_SetReg1( P3c4 , 0x16 , 0x85 ) ;
888
889 XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ; /* EMRS3 */
890 XGINew_SetReg1( P3c4 , 0x19 , 0xC0 ) ;
891 XGINew_SetReg1( P3c4 , 0x16 , 0x05 ) ;
892 XGINew_SetReg1( P3c4 , 0x16 , 0x85 ) ;
893
894 XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ; /* EMRS1 */
895 XGINew_SetReg1( P3c4 , 0x19 , 0x40 ) ;
896 XGINew_SetReg1( P3c4 , 0x16 , 0x05 ) ;
897 XGINew_SetReg1( P3c4 , 0x16 , 0x85 ) ;
898
899 // XGINew_SetReg1( P3c4 , 0x18 , 0x52 ) ; /* MRS1 */
900 XGINew_SetReg1( P3c4 , 0x18 , 0x42 ) ; /* MRS1 */
901 XGINew_SetReg1( P3c4 , 0x19 , 0x02 ) ;
902 XGINew_SetReg1( P3c4 , 0x16 , 0x05 ) ;
903 XGINew_SetReg1( P3c4 , 0x16 , 0x85 ) ;
904
905 DelayUS( 15 ) ;
906 XGINew_SetReg1( P3c4 , 0x1B , 0x04 ) ; /* SR1B */
907 DelayUS( 30 ) ;
908 XGINew_SetReg1( P3c4 , 0x1B , 0x00 ) ; /* SR1B */
909 DelayUS( 100 ) ;
910
911 //XGINew_SetReg1( P3c4 , 0x18 , 0x52 ) ; /* MRS2 */
912 XGINew_SetReg1( P3c4 , 0x18 , 0x42 ) ; /* MRS1 */
913 XGINew_SetReg1( P3c4 , 0x19 , 0x00 ) ;
914 XGINew_SetReg1( P3c4 , 0x16 , 0x05 ) ;
915 XGINew_SetReg1( P3c4 , 0x16 , 0x85 ) ;
916
917 DelayUS( 200 ) ;
918}
919
920/* --------------------------------------------------------------------- */
921/* Function : XGINew_DDR2_MRS_XG20 */
922/* Input : */
923/* Output : */
924/* Description : */
925/* --------------------------------------------------------------------- */
926void XGINew_DDR2_MRS_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension , ULONG P3c4 , PVB_DEVICE_INFO pVBInfo)
927{
928 ULONG P3d4 = P3c4 + 0x10 ;
929
930 XGINew_RAMType = ( int )XGINew_GetXG20DRAMType( HwDeviceExtension , pVBInfo ) ;
931 XGINew_SetMemoryClock( HwDeviceExtension , pVBInfo ) ;
932
933 XGINew_SetReg1( P3d4 , 0x97 , 0x11 ) ; /* CR97 */
934 DelayUS( 200 ) ;
935 XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ; /* EMRS2 */
936 XGINew_SetReg1( P3c4 , 0x19 , 0x80 ) ;
937
938 XGINew_SetReg1( P3c4 , 0x16 , 0x10 ) ;
939 DelayUS( 15 ) ; ////06/11/23 XG27 A0 for CKE enable
940 XGINew_SetReg1( P3c4 , 0x16 , 0x90 ) ;
941
942 XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ; /* EMRS3 */
943 XGINew_SetReg1( P3c4 , 0x19 , 0xC0 ) ;
944
945 XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ;
946 DelayUS( 15 ) ; ////06/11/22 XG27 A0
947 XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ;
948
949
950 XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ; /* EMRS1 */
951 XGINew_SetReg1( P3c4 , 0x19 , 0x40 ) ;
952
953 XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ;
954 DelayUS( 15 ) ; ////06/11/22 XG27 A0
955 XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ;
956
957 XGINew_SetReg1( P3c4 , 0x18 , 0x42 ) ; /* MRS1 */
958 XGINew_SetReg1( P3c4 , 0x19 , 0x06 ) ; ////[Billy]06/11/22 DLL Reset for XG27 Hynix DRAM
959
960 XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ;
961 DelayUS( 15 ) ; ////06/11/23 XG27 A0
962 XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ;
963
964 DelayUS( 30 ) ; ////06/11/23 XG27 A0 Start Auto-PreCharge
965 XGINew_SetReg1( P3c4 , 0x1B , 0x04 ) ; /* SR1B */
966 DelayUS( 60 ) ;
967 XGINew_SetReg1( P3c4 , 0x1B , 0x00 ) ; /* SR1B */
968
969
970 XGINew_SetReg1( P3c4 , 0x18 , 0x42 ) ; /* MRS1 */
971 XGINew_SetReg1( P3c4 , 0x19 , 0x04 ) ; //// DLL without Reset for XG27 Hynix DRAM
972
973 XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ;
974 DelayUS( 30 ) ;
975 XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ;
976
977 XGINew_SetReg1( P3c4 , 0x18 , 0x80 ); ////XG27 OCD ON
978 XGINew_SetReg1( P3c4 , 0x19 , 0x46 );
979
980 XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ;
981 DelayUS( 30 ) ;
982 XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ;
983
984 XGINew_SetReg1( P3c4 , 0x18 , 0x00 );
985 XGINew_SetReg1( P3c4 , 0x19 , 0x40 );
986
987 XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ;
988 DelayUS( 30 ) ;
989 XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ;
990
991 DelayUS( 15 ) ; ////Start Auto-PreCharge
992 XGINew_SetReg1( P3c4 , 0x1B , 0x04 ) ; /* SR1B */
993 DelayUS( 200 ) ;
994 XGINew_SetReg1( P3c4 , 0x1B , 0x03 ) ; /* SR1B */
995
996}
997
998/* --------------------------------------------------------------------- */
999/* Function : XGINew_DDR1x_DefaultRegister */
1000/* Input : */
1001/* Output : */
1002/* Description : */
1003/* --------------------------------------------------------------------- */
1004void XGINew_DDR1x_DefaultRegister( PXGI_HW_DEVICE_INFO HwDeviceExtension , ULONG Port , PVB_DEVICE_INFO pVBInfo)
1005{
1006 ULONG P3d4 = Port ,
1007 P3c4 = Port - 0x10 ;
1008
1009 if ( HwDeviceExtension->jChipType >= XG20 )
1010 {
1011 XGINew_SetMemoryClock( HwDeviceExtension , pVBInfo ) ;
1012 XGINew_SetReg1( P3d4 , 0x82 , pVBInfo->CR40[ 11 ][ XGINew_RAMType ] ) ; /* CR82 */
1013 XGINew_SetReg1( P3d4 , 0x85 , pVBInfo->CR40[ 12 ][ XGINew_RAMType ] ) ; /* CR85 */
1014 XGINew_SetReg1( P3d4 , 0x86 , pVBInfo->CR40[ 13 ][ XGINew_RAMType ] ) ; /* CR86 */
1015
1016 XGINew_SetReg1( P3d4 , 0x98 , 0x01 ) ;
1017 XGINew_SetReg1( P3d4 , 0x9A , 0x02 ) ;
1018
1019 XGINew_DDR1x_MRS_XG20( P3c4 , pVBInfo) ;
1020 }
1021 else
1022 {
1023 XGINew_SetMemoryClock( HwDeviceExtension , pVBInfo ) ;
1024
1025 switch( HwDeviceExtension->jChipType )
1026 {
1027 case XG41:
1028 case XG42:
1029 XGINew_SetReg1( P3d4 , 0x82 , pVBInfo->CR40[ 11 ][ XGINew_RAMType ] ) ; /* CR82 */
1030 XGINew_SetReg1( P3d4 , 0x85 , pVBInfo->CR40[ 12 ][ XGINew_RAMType ] ) ; /* CR85 */
1031 XGINew_SetReg1( P3d4 , 0x86 , pVBInfo->CR40[ 13 ][ XGINew_RAMType ] ) ; /* CR86 */
1032 break ;
1033 default:
1034 XGINew_SetReg1( P3d4 , 0x82 , 0x88 ) ;
1035 XGINew_SetReg1( P3d4 , 0x86 , 0x00 ) ;
1036 XGINew_GetReg1( P3d4 , 0x86 ) ; /* Insert read command for delay */
1037 XGINew_SetReg1( P3d4 , 0x86 , 0x88 ) ;
1038 XGINew_GetReg1( P3d4 , 0x86 ) ;
1039 XGINew_SetReg1( P3d4 , 0x86 , pVBInfo->CR40[ 13 ][ XGINew_RAMType ] ) ;
1040 XGINew_SetReg1( P3d4 , 0x82 , 0x77 ) ;
1041 XGINew_SetReg1( P3d4 , 0x85 , 0x00 ) ;
1042 XGINew_GetReg1( P3d4 , 0x85 ) ; /* Insert read command for delay */
1043 XGINew_SetReg1( P3d4 , 0x85 , 0x88 ) ;
1044 XGINew_GetReg1( P3d4 , 0x85 ) ; /* Insert read command for delay */
1045 XGINew_SetReg1( P3d4 , 0x85 , pVBInfo->CR40[ 12 ][ XGINew_RAMType ] ) ; /* CR85 */
1046 XGINew_SetReg1( P3d4 , 0x82 , pVBInfo->CR40[ 11 ][ XGINew_RAMType ] ) ; /* CR82 */
1047 break ;
1048 }
1049
1050 XGINew_SetReg1( P3d4 , 0x97 , 0x00 ) ;
1051 XGINew_SetReg1( P3d4 , 0x98 , 0x01 ) ;
1052 XGINew_SetReg1( P3d4 , 0x9A , 0x02 ) ;
1053 XGINew_DDR1x_MRS_340( P3c4 , pVBInfo ) ;
1054 }
1055}
1056
1057
1058/* --------------------------------------------------------------------- */
1059/* Function : XGINew_DDR2x_DefaultRegister */
1060/* Input : */
1061/* Output : */
1062/* Description : */
1063/* --------------------------------------------------------------------- */
1064void XGINew_DDR2x_DefaultRegister( PXGI_HW_DEVICE_INFO HwDeviceExtension , ULONG Port ,PVB_DEVICE_INFO pVBInfo)
1065{
1066 ULONG P3d4 = Port ,
1067 P3c4 = Port - 0x10 ;
1068
1069 XGINew_SetMemoryClock( HwDeviceExtension , pVBInfo ) ;
1070
1071 /* 20040906 Hsuan modify CR82, CR85, CR86 for XG42 */
1072 switch( HwDeviceExtension->jChipType )
1073 {
1074 case XG41:
1075 case XG42:
1076 XGINew_SetReg1( P3d4 , 0x82 , pVBInfo->CR40[ 11 ][ XGINew_RAMType ] ) ; /* CR82 */
1077 XGINew_SetReg1( P3d4 , 0x85 , pVBInfo->CR40[ 12 ][ XGINew_RAMType ] ) ; /* CR85 */
1078 XGINew_SetReg1( P3d4 , 0x86 , pVBInfo->CR40[ 13 ][ XGINew_RAMType ] ) ; /* CR86 */
1079 break ;
1080 default:
1081 /* keep following setting sequence, each setting in the same reg insert idle */
1082 XGINew_SetReg1( P3d4 , 0x82 , 0x88 ) ;
1083 XGINew_SetReg1( P3d4 , 0x86 , 0x00 ) ;
1084 XGINew_GetReg1( P3d4 , 0x86 ) ; /* Insert read command for delay */
1085 XGINew_SetReg1( P3d4 , 0x86 , 0x88 ) ;
1086 XGINew_SetReg1( P3d4 , 0x82 , 0x77 ) ;
1087 XGINew_SetReg1( P3d4 , 0x85 , 0x00 ) ;
1088 XGINew_GetReg1( P3d4 , 0x85 ) ; /* Insert read command for delay */
1089 XGINew_SetReg1( P3d4 , 0x85 , 0x88 ) ;
1090 XGINew_GetReg1( P3d4 , 0x85 ) ; /* Insert read command for delay */
1091 XGINew_SetReg1( P3d4 , 0x85 , pVBInfo->CR40[ 12 ][ XGINew_RAMType ] ) ; /* CR85 */
1092 XGINew_SetReg1( P3d4 , 0x82 , pVBInfo->CR40[ 11 ][ XGINew_RAMType ] ) ; /* CR82 */
1093 }
1094 XGINew_SetReg1( P3d4 , 0x97 , 0x11 ) ;
1095 if ( HwDeviceExtension->jChipType == XG42 )
1096 {
1097 XGINew_SetReg1( P3d4 , 0x98 , 0x01 ) ;
1098 }
1099 else
1100 {
1101 XGINew_SetReg1( P3d4 , 0x98 , 0x03 ) ;
1102 }
1103 XGINew_SetReg1( P3d4 , 0x9A , 0x02 ) ;
1104
1105 XGINew_DDR2x_MRS_340( P3c4 , pVBInfo ) ;
1106}
1107
1108
1109/* --------------------------------------------------------------------- */
1110/* Function : XGINew_DDR2_DefaultRegister */
1111/* Input : */
1112/* Output : */
1113/* Description : */
1114/* --------------------------------------------------------------------- */
1115void XGINew_DDR2_DefaultRegister( PXGI_HW_DEVICE_INFO HwDeviceExtension, ULONG Port , PVB_DEVICE_INFO pVBInfo)
1116{
1117 ULONG P3d4 = Port ,
1118 P3c4 = Port - 0x10 ;
1119
1120 /* keep following setting sequence, each setting in the same reg insert idle */
1121 XGINew_SetReg1( P3d4 , 0x82 , 0x77 ) ;
1122 XGINew_SetReg1( P3d4 , 0x86 , 0x00 ) ;
1123 XGINew_GetReg1( P3d4 , 0x86 ) ; /* Insert read command for delay */
1124 XGINew_SetReg1( P3d4 , 0x86 , 0x88 ) ;
1125 XGINew_GetReg1( P3d4 , 0x86 ) ; /* Insert read command for delay */
1126 XGINew_SetReg1( P3d4 , 0x86 , pVBInfo->CR40[ 13 ][ XGINew_RAMType ] ) ; /* CR86 */
1127 XGINew_SetReg1( P3d4 , 0x82 , 0x77 ) ;
1128 XGINew_SetReg1( P3d4 , 0x85 , 0x00 ) ;
1129 XGINew_GetReg1( P3d4 , 0x85 ) ; /* Insert read command for delay */
1130 XGINew_SetReg1( P3d4 , 0x85 , 0x88 ) ;
1131 XGINew_GetReg1( P3d4 , 0x85 ) ; /* Insert read command for delay */
1132 XGINew_SetReg1( P3d4 , 0x85 , pVBInfo->CR40[ 12 ][ XGINew_RAMType ] ) ; /* CR85 */
1133 if ( HwDeviceExtension->jChipType == XG27 )
1134 XGINew_SetReg1( P3d4 , 0x82 , pVBInfo->CR40[ 11 ][ XGINew_RAMType ] ) ; /* CR82 */
1135 else
1136 XGINew_SetReg1( P3d4 , 0x82 , 0xA8 ) ; /* CR82 */
1137
1138 XGINew_SetReg1( P3d4 , 0x98 , 0x01 ) ;
1139 XGINew_SetReg1( P3d4 , 0x9A , 0x02 ) ;
1140 if ( HwDeviceExtension->jChipType == XG27 )
1141 XGINew_DDRII_Bootup_XG27( HwDeviceExtension , P3c4 , pVBInfo) ;
1142 else
1143 XGINew_DDR2_MRS_XG20( HwDeviceExtension , P3c4, pVBInfo ) ;
1144}
1145
1146
1147/* --------------------------------------------------------------------- */
1148/* Function : XGINew_SetDRAMDefaultRegister340 */
1149/* Input : */
1150/* Output : */
1151/* Description : */
1152/* --------------------------------------------------------------------- */
1153void XGINew_SetDRAMDefaultRegister340( PXGI_HW_DEVICE_INFO HwDeviceExtension , ULONG Port , PVB_DEVICE_INFO pVBInfo)
1154{
1155 UCHAR temp , temp1 , temp2 , temp3 ,
1156 i , j , k ;
1157
1158 ULONG P3d4 = Port ,
1159 P3c4 = Port - 0x10 ;
1160
1161 XGINew_SetReg1( P3d4 , 0x6D , pVBInfo->CR40[ 8 ][ XGINew_RAMType ] ) ;
1162 XGINew_SetReg1( P3d4 , 0x68 , pVBInfo->CR40[ 5 ][ XGINew_RAMType ] ) ;
1163 XGINew_SetReg1( P3d4 , 0x69 , pVBInfo->CR40[ 6 ][ XGINew_RAMType ] ) ;
1164 XGINew_SetReg1( P3d4 , 0x6A , pVBInfo->CR40[ 7 ][ XGINew_RAMType ] ) ;
1165
1166 temp2 = 0 ;
1167 for( i = 0 ; i < 4 ; i++ )
1168 {
1169 temp = pVBInfo->CR6B[ XGINew_RAMType ][ i ] ; /* CR6B DQS fine tune delay */
1170 for( j = 0 ; j < 4 ; j++ )
1171 {
1172 temp1 = ( ( temp >> ( 2 * j ) ) & 0x03 ) << 2 ;
1173 temp2 |= temp1 ;
1174 XGINew_SetReg1( P3d4 , 0x6B , temp2 ) ;
1175 XGINew_GetReg1( P3d4 , 0x6B ) ; /* Insert read command for delay */
1176 temp2 &= 0xF0 ;
1177 temp2 += 0x10 ;
1178 }
1179 }
1180
1181 temp2 = 0 ;
1182 for( i = 0 ; i < 4 ; i++ )
1183 {
1184 temp = pVBInfo->CR6E[ XGINew_RAMType ][ i ] ; /* CR6E DQM fine tune delay */
1185 for( j = 0 ; j < 4 ; j++ )
1186 {
1187 temp1 = ( ( temp >> ( 2 * j ) ) & 0x03 ) << 2 ;
1188 temp2 |= temp1 ;
1189 XGINew_SetReg1( P3d4 , 0x6E , temp2 ) ;
1190 XGINew_GetReg1( P3d4 , 0x6E ) ; /* Insert read command for delay */
1191 temp2 &= 0xF0 ;
1192 temp2 += 0x10 ;
1193 }
1194 }
1195
1196 temp3 = 0 ;
1197 for( k = 0 ; k < 4 ; k++ )
1198 {
1199 XGINew_SetRegANDOR( P3d4 , 0x6E , 0xFC , temp3 ) ; /* CR6E_D[1:0] select channel */
1200 temp2 = 0 ;
1201 for( i = 0 ; i < 8 ; i++ )
1202 {
1203 temp = pVBInfo->CR6F[ XGINew_RAMType ][ 8 * k + i ] ; /* CR6F DQ fine tune delay */
1204 for( j = 0 ; j < 4 ; j++ )
1205 {
1206 temp1 = ( temp >> ( 2 * j ) ) & 0x03 ;
1207 temp2 |= temp1 ;
1208 XGINew_SetReg1( P3d4 , 0x6F , temp2 ) ;
1209 XGINew_GetReg1( P3d4 , 0x6F ) ; /* Insert read command for delay */
1210 temp2 &= 0xF8 ;
1211 temp2 += 0x08 ;
1212 }
1213 }
1214 temp3 += 0x01 ;
1215 }
1216
1217 XGINew_SetReg1( P3d4 , 0x80 , pVBInfo->CR40[ 9 ][ XGINew_RAMType ] ) ; /* CR80 */
1218 XGINew_SetReg1( P3d4 , 0x81 , pVBInfo->CR40[ 10 ][ XGINew_RAMType ] ) ; /* CR81 */
1219
1220 temp2 = 0x80 ;
1221 temp = pVBInfo->CR89[ XGINew_RAMType ][ 0 ] ; /* CR89 terminator type select */
1222 for( j = 0 ; j < 4 ; j++ )
1223 {
1224 temp1 = ( temp >> ( 2 * j ) ) & 0x03 ;
1225 temp2 |= temp1 ;
1226 XGINew_SetReg1( P3d4 , 0x89 , temp2 ) ;
1227 XGINew_GetReg1( P3d4 , 0x89 ) ; /* Insert read command for delay */
1228 temp2 &= 0xF0 ;
1229 temp2 += 0x10 ;
1230 }
1231
1232 temp = pVBInfo->CR89[ XGINew_RAMType ][ 1 ] ;
1233 temp1 = temp & 0x03 ;
1234 temp2 |= temp1 ;
1235 XGINew_SetReg1( P3d4 , 0x89 , temp2 ) ;
1236
1237 temp = pVBInfo->CR40[ 3 ][ XGINew_RAMType ] ;
1238 temp1 = temp & 0x0F ;
1239 temp2 = ( temp >> 4 ) & 0x07 ;
1240 temp3 = temp & 0x80 ;
1241 XGINew_SetReg1( P3d4 , 0x45 , temp1 ) ; /* CR45 */
1242 XGINew_SetReg1( P3d4 , 0x99 , temp2 ) ; /* CR99 */
1243 XGINew_SetRegOR( P3d4 , 0x40 , temp3 ) ; /* CR40_D[7] */
1244 XGINew_SetReg1( P3d4 , 0x41 , pVBInfo->CR40[ 0 ][ XGINew_RAMType ] ) ; /* CR41 */
1245
1246 if ( HwDeviceExtension->jChipType == XG27 )
1247 XGINew_SetReg1( P3d4 , 0x8F , *pVBInfo->pCR8F ) ; /* CR8F */
1248
1249 for( j = 0 ; j <= 6 ; j++ )
1250 XGINew_SetReg1( P3d4 , ( 0x90 + j ) , pVBInfo->CR40[ 14 + j ][ XGINew_RAMType ] ) ; /* CR90 - CR96 */
1251
1252 for( j = 0 ; j <= 2 ; j++ )
1253 XGINew_SetReg1( P3d4 , ( 0xC3 + j ) , pVBInfo->CR40[ 21 + j ][ XGINew_RAMType ] ) ; /* CRC3 - CRC5 */
1254
1255 for( j = 0 ; j < 2 ; j++ )
1256 XGINew_SetReg1( P3d4 , ( 0x8A + j ) , pVBInfo->CR40[ 1 + j ][ XGINew_RAMType ] ) ; /* CR8A - CR8B */
1257
1258 if ( ( HwDeviceExtension->jChipType == XG41 ) || ( HwDeviceExtension->jChipType == XG42 ) )
1259 XGINew_SetReg1( P3d4 , 0x8C , 0x87 ) ;
1260
1261 XGINew_SetReg1( P3d4 , 0x59 , pVBInfo->CR40[ 4 ][ XGINew_RAMType ] ) ; /* CR59 */
1262
1263 XGINew_SetReg1( P3d4 , 0x83 , 0x09 ) ; /* CR83 */
1264 XGINew_SetReg1( P3d4 , 0x87 , 0x00 ) ; /* CR87 */
1265 XGINew_SetReg1( P3d4 , 0xCF , *pVBInfo->pCRCF ) ; /* CRCF */
1266 if ( XGINew_RAMType )
1267 {
1268 //XGINew_SetReg1( P3c4 , 0x17 , 0xC0 ) ; /* SR17 DDRII */
1269 XGINew_SetReg1( P3c4 , 0x17 , 0x80 ) ; /* SR17 DDRII */
1270 if ( HwDeviceExtension->jChipType == XG27 )
1271 XGINew_SetReg1( P3c4 , 0x17 , 0x02 ) ; /* SR17 DDRII */
1272
1273 }
1274 else
1275 XGINew_SetReg1( P3c4 , 0x17 , 0x00 ) ; /* SR17 DDR */
1276 XGINew_SetReg1( P3c4 , 0x1A , 0x87 ) ; /* SR1A */
1277
1278 temp = XGINew_GetXG20DRAMType( HwDeviceExtension, pVBInfo) ;
1279 if( temp == 0 )
1280 XGINew_DDR1x_DefaultRegister( HwDeviceExtension, P3d4, pVBInfo ) ;
1281 else
1282 {
1283 XGINew_SetReg1( P3d4 , 0xB0 , 0x80 ) ; /* DDRII Dual frequency mode */
1284 XGINew_DDR2_DefaultRegister( HwDeviceExtension, P3d4, pVBInfo ) ;
1285 }
1286 XGINew_SetReg1( P3c4 , 0x1B , pVBInfo->SR15[ 3 ][ XGINew_RAMType ] ) ; /* SR1B */
1287}
1288
1289
1290/* --------------------------------------------------------------------- */
1291/* Function : XGINew_DDR_MRS */
1292/* Input : */
1293/* Output : */
1294/* Description : */
1295/* --------------------------------------------------------------------- */
1296void XGINew_DDR_MRS(PVB_DEVICE_INFO pVBInfo)
1297{
1298 USHORT data ;
1299
1300 PUCHAR volatile pVideoMemory = ( PUCHAR )pVBInfo->ROMAddr ;
1301
1302 /* SR16 <- 1F,DF,2F,AF */
1303 /* yriver modified SR16 <- 0F,DF,0F,AF */
1304 /* enable DLL of DDR SD/SGRAM , SR16 D4=1 */
1305 data = pVideoMemory[ 0xFB ] ;
1306 /* data = XGINew_GetReg1( pVBInfo->P3c4 , 0x16 ) ; */
1307
1308 data &= 0x0F ;
1309 XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ;
1310 data |= 0xC0 ;
1311 XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ;
1312 data &= 0x0F ;
1313 XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ;
1314 data |= 0x80 ;
1315 XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ;
1316 data &= 0x0F ;
1317 XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ;
1318 data |= 0xD0 ;
1319 XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ;
1320 data &= 0x0F ;
1321 XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ;
1322 data |= 0xA0 ;
1323 XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ;
1324/*
1325 else {
1326 data &= 0x0F;
1327 data |= 0x10;
1328 XGINew_SetReg1(pVBInfo->P3c4,0x16,data);
1329
1330 if (!(pVBInfo->SR15[1][XGINew_RAMType] & 0x10))
1331 {
1332 data &= 0x0F;
1333 }
1334
1335 data |= 0xC0;
1336 XGINew_SetReg1(pVBInfo->P3c4,0x16,data);
1337
1338
1339 data &= 0x0F;
1340 data |= 0x20;
1341 XGINew_SetReg1(pVBInfo->P3c4,0x16,data);
1342 if (!(pVBInfo->SR15[1][XGINew_RAMType] & 0x10))
1343 {
1344 data &= 0x0F;
1345 }
1346
1347 data |= 0x80;
1348 XGINew_SetReg1(pVBInfo->P3c4,0x16,data);
1349 }
1350*/
1351}
1352
1353
1354/* check if read cache pointer is correct */
1355
1356
1357
1358/* --------------------------------------------------------------------- */
1359/* Function : XGINew_VerifyMclk */
1360/* Input : */
1361/* Output : */
1362/* Description : */
1363/* --------------------------------------------------------------------- */
1364void XGINew_VerifyMclk( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
1365{
1366 PUCHAR pVideoMemory = pVBInfo->FBAddr ;
1367 UCHAR i , j ;
1368 USHORT Temp , SR21 ;
1369
1370 pVideoMemory[ 0 ] = 0xaa ; /* alan */
1371 pVideoMemory[ 16 ] = 0x55 ; /* note: PCI read cache is off */
1372
1373 if ( ( pVideoMemory[ 0 ] != 0xaa ) || ( pVideoMemory[ 16 ] != 0x55 ) )
1374 {
1375 for( i = 0 , j = 16 ; i < 2 ; i++ , j += 16 )
1376 {
1377 SR21 = XGINew_GetReg1( pVBInfo->P3c4 , 0x21 ) ;
1378 Temp = SR21 & 0xFB ; /* disable PCI post write buffer empty gating */
1379 XGINew_SetReg1( pVBInfo->P3c4 , 0x21 , Temp ) ;
1380
1381 Temp = XGINew_GetReg1( pVBInfo->P3c4 , 0x3C ) ;
1382 Temp |= 0x01 ; /* MCLK reset */
1383
1384
1385 Temp = XGINew_GetReg1( pVBInfo->P3c4 , 0x3C ) ;
1386 Temp &= 0xFE ; /* MCLK normal operation */
1387
1388 XGINew_SetReg1( pVBInfo->P3c4 , 0x21 , SR21 ) ;
1389
1390 pVideoMemory[ 16 + j ] = j ;
1391 if ( pVideoMemory[ 16 + j ] == j )
1392 {
1393 pVideoMemory[ j ] = j ;
1394 break ;
1395 }
1396 }
1397 }
1398}
1399
1400
1401
1402
1403
1404/* --------------------------------------------------------------------- */
1405/* Function : XGINew_SetDRAMSize_340 */
1406/* Input : */
1407/* Output : */
1408/* Description : */
1409/* --------------------------------------------------------------------- */
1410void XGINew_SetDRAMSize_340( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
1411{
1412 USHORT data ;
1413
1414 pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
1415 pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ;
1416
1417 XGISetModeNew( HwDeviceExtension , 0x2e ) ;
1418
1419
1420 data = XGINew_GetReg1( pVBInfo->P3c4 , 0x21 ) ;
1421 XGINew_SetReg1( pVBInfo->P3c4 , 0x21 , ( USHORT )( data & 0xDF ) ) ; /* disable read cache */
1422 XGI_DisplayOff( HwDeviceExtension, pVBInfo );
1423
1424 /*data = XGINew_GetReg1( pVBInfo->P3c4 , 0x1 ) ;*/
1425 /*data |= 0x20 ;*/
1426 /*XGINew_SetReg1( pVBInfo->P3c4 , 0x01 , data ) ;*/ /* Turn OFF Display */
1427 XGINew_DDRSizing340( HwDeviceExtension, pVBInfo ) ;
1428 data=XGINew_GetReg1( pVBInfo->P3c4 , 0x21 ) ;
1429 XGINew_SetReg1( pVBInfo->P3c4 , 0x21 , ( USHORT )( data | 0x20 ) ) ; /* enable read cache */
1430
1431}
1432
1433
1434/* --------------------------------------------------------------------- */
1435/* Function : */
1436/* Input : */
1437/* Output : */
1438/* Description : */
1439/* --------------------------------------------------------------------- */
1440void XGINew_SetDRAMSize_310( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
1441{
1442 USHORT data ;
1443 pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ,
1444 pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ;
1445#ifdef XGI301
1446 /* XGINew_SetReg1( pVBInfo->P3d4 , 0x30 , 0x40 ) ; */
1447#endif
1448
1449#ifdef XGI302 /* alan,should change value */
1450 XGINew_SetReg1( pVBInfo->P3d4 , 0x30 , 0x4D ) ;
1451 XGINew_SetReg1( pVBInfo->P3d4 , 0x31 , 0xc0 ) ;
1452 XGINew_SetReg1( pVBInfo->P3d4 , 0x34 , 0x3F ) ;
1453#endif
1454
1455 XGISetModeNew( HwDeviceExtension , 0x2e ) ;
1456
1457 data = XGINew_GetReg1( pVBInfo->P3c4 , 0x21 ) ;
1458 XGINew_SetReg1( pVBInfo->P3c4 , 0x21 , ( USHORT )( data & 0xDF ) ) ; /* disable read cache */
1459
1460 data = XGINew_GetReg1( pVBInfo->P3c4 , 0x1 ) ;
1461 data |= 0x20 ;
1462 XGINew_SetReg1( pVBInfo->P3c4 , 0x01 , data ) ; /* Turn OFF Display */
1463
1464 data = XGINew_GetReg1( pVBInfo->P3c4 , 0x16 ) ;
1465
1466
1467 XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , ( USHORT )( data | 0x0F ) ) ; /* assume lowest speed DRAM */
1468
1469 XGINew_SetDRAMModeRegister( pVBInfo ) ;
1470 XGINew_DisableRefresh( HwDeviceExtension, pVBInfo ) ;
1471 XGINew_CheckBusWidth_310( pVBInfo) ;
1472 XGINew_VerifyMclk( HwDeviceExtension, pVBInfo ) ; /* alan 2000/7/3 */
1473
1474
1475
1476 if ( XGINew_Get310DRAMType( pVBInfo ) < 2 )
1477 {
1478 XGINew_SDRSizing( pVBInfo ) ;
1479 }
1480 else
1481 {
1482 XGINew_DDRSizing( pVBInfo) ;
1483 }
1484
1485
1486
1487
1488 XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , pVBInfo->SR15[ 1 ][ XGINew_RAMType ] ) ; /* restore SR16 */
1489
1490 XGINew_EnableRefresh( HwDeviceExtension, pVBInfo ) ;
1491 data=XGINew_GetReg1( pVBInfo->P3c4 ,0x21 ) ;
1492 XGINew_SetReg1( pVBInfo->P3c4 , 0x21 , ( USHORT )( data | 0x20 ) ) ; /* enable read cache */
1493}
1494
1495
1496
1497/* --------------------------------------------------------------------- */
1498/* Function : XGINew_SetDRAMModeRegister340 */
1499/* Input : */
1500/* Output : */
1501/* Description : */
1502/* --------------------------------------------------------------------- */
1503
1504void XGINew_SetDRAMModeRegister340( PXGI_HW_DEVICE_INFO HwDeviceExtension )
1505{
1506 UCHAR data ;
1507 VB_DEVICE_INFO VBINF;
1508 PVB_DEVICE_INFO pVBInfo = &VBINF;
1509 pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
1510 pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ;
1511 pVBInfo->BaseAddr = (ULONG)HwDeviceExtension->pjIOAddress ;
1512 pVBInfo->ISXPDOS = 0 ;
1513
1514 pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ;
1515 pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ;
1516 pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10 ;
1517 pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e ;
1518 pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ;
1519 pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a ;
1520 pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16 ;
1521 pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17 ;
1522 pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18 ;
1523 pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19 ;
1524 pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A ;
1525 pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00 ;
1526 pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04 ;
1527 pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ;
1528 pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12 ;
1529 pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ;
1530 pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2 ;
1531 if ( HwDeviceExtension->jChipType < XG20 ) /* kuku 2004/06/25 */
1532 XGI_GetVBType( pVBInfo ) ; /* Run XGI_GetVBType before InitTo330Pointer */
1533
1534 InitTo330Pointer(HwDeviceExtension->jChipType,pVBInfo);
1535
1536 ReadVBIOSTablData( HwDeviceExtension->jChipType , pVBInfo) ;
1537
1538 if ( XGINew_GetXG20DRAMType( HwDeviceExtension, pVBInfo) == 0 )
1539 {
1540 data = ( XGINew_GetReg1( pVBInfo->P3c4 , 0x39 ) & 0x02 ) >> 1 ;
1541 if ( data == 0x01 )
1542 XGINew_DDR2x_MRS_340( pVBInfo->P3c4, pVBInfo ) ;
1543 else
1544 XGINew_DDR1x_MRS_340( pVBInfo->P3c4, pVBInfo ) ;
1545 }
1546 else
1547 XGINew_DDR2_MRS_XG20( HwDeviceExtension, pVBInfo->P3c4, pVBInfo);
1548
1549 XGINew_SetReg1( pVBInfo->P3c4 , 0x1B , 0x03 ) ;
1550}
1551
1552/* --------------------------------------------------------------------- */
1553/* Function : XGINew_SetDRAMModeRegister */
1554/* Input : */
1555/* Output : */
1556/* Description : */
1557/* --------------------------------------------------------------------- */
1558void XGINew_SetDRAMModeRegister( PVB_DEVICE_INFO pVBInfo)
1559{
1560 if ( XGINew_Get310DRAMType( pVBInfo ) < 2 )
1561 {
1562 XGINew_SDR_MRS(pVBInfo ) ;
1563 }
1564 else
1565 {
1566 /* SR16 <- 0F,CF,0F,8F */
1567 XGINew_DDR_MRS( pVBInfo ) ;
1568 }
1569}
1570
1571
1572/* --------------------------------------------------------------------- */
1573/* Function : XGINew_DisableRefresh */
1574/* Input : */
1575/* Output : */
1576/* Description : */
1577/* --------------------------------------------------------------------- */
1578void XGINew_DisableRefresh( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
1579{
1580 USHORT data ;
1581
1582
1583 data = XGINew_GetReg1( pVBInfo->P3c4 , 0x1B ) ;
1584 data &= 0xF8 ;
1585 XGINew_SetReg1( pVBInfo->P3c4 , 0x1B , data ) ;
1586
1587}
1588
1589
1590/* --------------------------------------------------------------------- */
1591/* Function : XGINew_EnableRefresh */
1592/* Input : */
1593/* Output : */
1594/* Description : */
1595/* --------------------------------------------------------------------- */
1596void XGINew_EnableRefresh( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
1597{
1598
1599 XGINew_SetReg1( pVBInfo->P3c4 , 0x1B , pVBInfo->SR15[ 3 ][ XGINew_RAMType ] ) ; /* SR1B */
1600
1601
1602}
1603
1604
1605/* --------------------------------------------------------------------- */
1606/* Function : XGINew_DisableChannelInterleaving */
1607/* Input : */
1608/* Output : */
1609/* Description : */
1610/* --------------------------------------------------------------------- */
1611void XGINew_DisableChannelInterleaving( int index , USHORT XGINew_DDRDRAM_TYPE[][ 5 ] , PVB_DEVICE_INFO pVBInfo)
1612{
1613 USHORT data ;
1614
1615 data = XGINew_GetReg1( pVBInfo->P3c4 , 0x15 ) ;
1616 data &= 0x1F ;
1617
1618 switch( XGINew_DDRDRAM_TYPE[ index ][ 3 ] )
1619 {
1620 case 64:
1621 data |= 0 ;
1622 break ;
1623 case 32:
1624 data |= 0x20 ;
1625 break ;
1626 case 16:
1627 data |= 0x40 ;
1628 break ;
1629 case 4:
1630 data |= 0x60 ;
1631 break ;
1632 default:
1633 break ;
1634 }
1635 XGINew_SetReg1( pVBInfo->P3c4 , 0x15 , data ) ;
1636}
1637
1638
1639/* --------------------------------------------------------------------- */
1640/* Function : XGINew_SetDRAMSizingType */
1641/* Input : */
1642/* Output : */
1643/* Description : */
1644/* --------------------------------------------------------------------- */
1645void XGINew_SetDRAMSizingType( int index , USHORT DRAMTYPE_TABLE[][ 5 ] ,PVB_DEVICE_INFO pVBInfo)
1646{
1647 USHORT data ;
1648
1649 data = DRAMTYPE_TABLE[ index ][ 4 ] ;
1650 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x13 , 0x80 , data ) ;
1651 DelayUS( 15 ) ;
1652 /* should delay 50 ns */
1653}
1654
1655
1656/* --------------------------------------------------------------------- */
1657/* Function : XGINew_CheckBusWidth_310 */
1658/* Input : */
1659/* Output : */
1660/* Description : */
1661/* --------------------------------------------------------------------- */
1662void XGINew_CheckBusWidth_310( PVB_DEVICE_INFO pVBInfo)
1663{
1664 USHORT data ;
1665 PULONG volatile pVideoMemory ;
1666
1667 pVideoMemory = (PULONG) pVBInfo->FBAddr;
1668
1669 if ( XGINew_Get310DRAMType( pVBInfo ) < 2 )
1670 {
1671 XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x00 ) ;
1672 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x12 ) ;
1673 /* should delay */
1674 XGINew_SDR_MRS( pVBInfo ) ;
1675
1676 XGINew_ChannelAB = 0 ;
1677 XGINew_DataBusWidth = 128 ;
1678 pVideoMemory[ 0 ] = 0x01234567L ;
1679 pVideoMemory[ 1 ] = 0x456789ABL ;
1680 pVideoMemory[ 2 ] = 0x89ABCDEFL ;
1681 pVideoMemory[ 3 ] = 0xCDEF0123L ;
1682 pVideoMemory[ 4 ] = 0x55555555L ;
1683 pVideoMemory[ 5 ] = 0x55555555L ;
1684 pVideoMemory[ 6 ] = 0xFFFFFFFFL ;
1685 pVideoMemory[ 7 ] = 0xFFFFFFFFL ;
1686
1687 if ( ( pVideoMemory[ 3 ] != 0xCDEF0123L ) || ( pVideoMemory[ 2 ] != 0x89ABCDEFL ) )
1688 {
1689 /* ChannelA64Bit */
1690 XGINew_DataBusWidth = 64 ;
1691 XGINew_ChannelAB = 0 ;
1692 data=XGINew_GetReg1( pVBInfo->P3c4 , 0x14 ) ;
1693 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , ( USHORT )( data & 0xFD ) ) ;
1694 }
1695
1696 if ( ( pVideoMemory[ 1 ] != 0x456789ABL ) || ( pVideoMemory[ 0 ] != 0x01234567L ) )
1697 {
1698 /* ChannelB64Bit */
1699 XGINew_DataBusWidth = 64 ;
1700 XGINew_ChannelAB = 1 ;
1701 data=XGINew_GetReg1( pVBInfo->P3c4 , 0x14 ) ;
1702 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , ( USHORT )( ( data & 0xFD ) | 0x01 ) ) ;
1703 }
1704
1705 return ;
1706 }
1707 else
1708 {
1709 /* DDR Dual channel */
1710 XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x00 ) ;
1711 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x02 ) ; /* Channel A, 64bit */
1712 /* should delay */
1713 XGINew_DDR_MRS( pVBInfo ) ;
1714
1715 XGINew_ChannelAB = 0 ;
1716 XGINew_DataBusWidth = 64 ;
1717 pVideoMemory[ 0 ] = 0x01234567L ;
1718 pVideoMemory[ 1 ] = 0x456789ABL ;
1719 pVideoMemory[ 2 ] = 0x89ABCDEFL ;
1720 pVideoMemory[ 3 ] = 0xCDEF0123L ;
1721 pVideoMemory[ 4 ] = 0x55555555L ;
1722 pVideoMemory[ 5 ] = 0x55555555L ;
1723 pVideoMemory[ 6 ] = 0xAAAAAAAAL ;
1724 pVideoMemory[ 7 ] = 0xAAAAAAAAL ;
1725
1726 if ( pVideoMemory[ 1 ] == 0x456789ABL )
1727 {
1728 if ( pVideoMemory[ 0 ] == 0x01234567L )
1729 {
1730 /* Channel A 64bit */
1731 return ;
1732 }
1733 }
1734 else
1735 {
1736 if ( pVideoMemory[ 0 ] == 0x01234567L )
1737 {
1738 /* Channel A 32bit */
1739 XGINew_DataBusWidth = 32 ;
1740 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x00 ) ;
1741 return ;
1742 }
1743 }
1744
1745 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x03 ) ; /* Channel B, 64bit */
1746 XGINew_DDR_MRS( pVBInfo);
1747
1748 XGINew_ChannelAB = 1 ;
1749 XGINew_DataBusWidth = 64 ;
1750 pVideoMemory[ 0 ] = 0x01234567L ;
1751 pVideoMemory[ 1 ] = 0x456789ABL ;
1752 pVideoMemory[ 2 ] = 0x89ABCDEFL ;
1753 pVideoMemory[ 3 ] = 0xCDEF0123L ;
1754 pVideoMemory[ 4 ] = 0x55555555L ;
1755 pVideoMemory[ 5 ] = 0x55555555L ;
1756 pVideoMemory[ 6 ] = 0xAAAAAAAAL ;
1757 pVideoMemory[ 7 ] = 0xAAAAAAAAL ;
1758
1759 if ( pVideoMemory[ 1 ] == 0x456789ABL )
1760 {
1761 /* Channel B 64 */
1762 if ( pVideoMemory[ 0 ] == 0x01234567L )
1763 {
1764 /* Channel B 64bit */
1765 return ;
1766 }
1767 else
1768 {
1769 /* error */
1770 }
1771 }
1772 else
1773 {
1774 if ( pVideoMemory[ 0 ] == 0x01234567L )
1775 {
1776 /* Channel B 32 */
1777 XGINew_DataBusWidth = 32 ;
1778 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x01 ) ;
1779 }
1780 else
1781 {
1782 /* error */
1783 }
1784 }
1785 }
1786}
1787
1788
1789/* --------------------------------------------------------------------- */
1790/* Function : XGINew_SetRank */
1791/* Input : */
1792/* Output : */
1793/* Description : */
1794/* --------------------------------------------------------------------- */
1795int XGINew_SetRank( int index , UCHAR RankNo , UCHAR XGINew_ChannelAB , USHORT DRAMTYPE_TABLE[][ 5 ] , PVB_DEVICE_INFO pVBInfo)
1796{
1797 USHORT data ;
1798 int RankSize ;
1799
1800 if ( ( RankNo == 2 ) && ( DRAMTYPE_TABLE[ index ][ 0 ] == 2 ) )
1801 return 0 ;
1802
1803 RankSize = DRAMTYPE_TABLE[ index ][ 3 ] / 2 * XGINew_DataBusWidth / 32 ;
1804
1805 if ( ( RankNo * RankSize ) <= 128 )
1806 {
1807 data = 0 ;
1808
1809 while( ( RankSize >>= 1 ) > 0 )
1810 {
1811 data += 0x10 ;
1812 }
1813 data |= ( RankNo - 1 ) << 2 ;
1814 data |= ( XGINew_DataBusWidth / 64 ) & 2 ;
1815 data |= XGINew_ChannelAB ;
1816 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , data ) ;
1817 /* should delay */
1818 XGINew_SDR_MRS( pVBInfo ) ;
1819 return( 1 ) ;
1820 }
1821 else
1822 return( 0 ) ;
1823}
1824
1825
1826/* --------------------------------------------------------------------- */
1827/* Function : XGINew_SetDDRChannel */
1828/* Input : */
1829/* Output : */
1830/* Description : */
1831/* --------------------------------------------------------------------- */
1832int XGINew_SetDDRChannel( int index , UCHAR ChannelNo , UCHAR XGINew_ChannelAB , USHORT DRAMTYPE_TABLE[][ 5 ] , PVB_DEVICE_INFO pVBInfo)
1833{
1834 USHORT data ;
1835 int RankSize ;
1836
1837 RankSize = DRAMTYPE_TABLE[index][3]/2 * XGINew_DataBusWidth/32;
1838 /* RankSize = DRAMTYPE_TABLE[ index ][ 3 ] ; */
1839 if ( ChannelNo * RankSize <= 128 )
1840 {
1841 data = 0 ;
1842 while( ( RankSize >>= 1 ) > 0 )
1843 {
1844 data += 0x10 ;
1845 }
1846
1847 if ( ChannelNo == 2 )
1848 data |= 0x0C ;
1849
1850 data |= ( XGINew_DataBusWidth / 32 ) & 2 ;
1851 data |= XGINew_ChannelAB ;
1852 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , data ) ;
1853 /* should delay */
1854 XGINew_DDR_MRS( pVBInfo ) ;
1855 return( 1 ) ;
1856 }
1857 else
1858 return( 0 ) ;
1859}
1860
1861
1862/* --------------------------------------------------------------------- */
1863/* Function : XGINew_CheckColumn */
1864/* Input : */
1865/* Output : */
1866/* Description : */
1867/* --------------------------------------------------------------------- */
1868int XGINew_CheckColumn( int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo)
1869{
1870 int i ;
1871 ULONG Increment , Position ;
1872
1873 /* Increment = 1 << ( DRAMTYPE_TABLE[ index ][ 2 ] + XGINew_DataBusWidth / 64 + 1 ) ; */
1874 Increment = 1 << ( 10 + XGINew_DataBusWidth / 64 ) ;
1875
1876 for( i = 0 , Position = 0 ; i < 2 ; i++ )
1877 {
1878 *( ( PULONG )( pVBInfo->FBAddr + Position ) ) = Position ;
1879 Position += Increment ;
1880 }
1881
1882#ifdef WIN2000 /* chiawen for linux solution */
1883 DelayUS( 100 ) ;
1884#endif
1885
1886 for( i = 0 , Position = 0 ; i < 2 ; i++ )
1887 {
1888 /* if ( pVBInfo->FBAddr[ Position ] != Position ) */
1889 if ( ( *( PULONG )( pVBInfo->FBAddr + Position ) ) != Position )
1890 return( 0 ) ;
1891 Position += Increment ;
1892 }
1893 return( 1 ) ;
1894}
1895
1896
1897/* --------------------------------------------------------------------- */
1898/* Function : XGINew_CheckBanks */
1899/* Input : */
1900/* Output : */
1901/* Description : */
1902/* --------------------------------------------------------------------- */
1903int XGINew_CheckBanks( int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo)
1904{
1905 int i ;
1906 ULONG Increment , Position ;
1907
1908 Increment = 1 << ( DRAMTYPE_TABLE[ index ][ 2 ] + XGINew_DataBusWidth / 64 + 2 ) ;
1909
1910 for( i = 0 , Position = 0 ; i < 4 ; i++ )
1911 {
1912 /* pVBInfo->FBAddr[ Position ] = Position ; */
1913 *( ( PULONG )( pVBInfo->FBAddr + Position ) ) = Position ;
1914 Position += Increment ;
1915 }
1916
1917 for( i = 0 , Position = 0 ; i < 4 ; i++ )
1918 {
1919 /* if (pVBInfo->FBAddr[ Position ] != Position ) */
1920 if ( ( *( PULONG )( pVBInfo->FBAddr + Position ) ) != Position )
1921 return( 0 ) ;
1922 Position += Increment ;
1923 }
1924 return( 1 ) ;
1925}
1926
1927
1928/* --------------------------------------------------------------------- */
1929/* Function : XGINew_CheckRank */
1930/* Input : */
1931/* Output : */
1932/* Description : */
1933/* --------------------------------------------------------------------- */
1934int XGINew_CheckRank( int RankNo , int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo)
1935{
1936 int i ;
1937 ULONG Increment , Position ;
1938
1939 Increment = 1 << ( DRAMTYPE_TABLE[ index ][ 2 ] + DRAMTYPE_TABLE[ index ][ 1 ] +
1940 DRAMTYPE_TABLE[ index ][ 0 ] + XGINew_DataBusWidth / 64 + RankNo ) ;
1941
1942 for( i = 0 , Position = 0 ; i < 2 ; i++ )
1943 {
1944 /* pVBInfo->FBAddr[ Position ] = Position ; */
1945 /* *( ( PULONG )( pVBInfo->FBAddr ) ) = Position ; */
1946 *( ( PULONG )( pVBInfo->FBAddr + Position ) ) = Position ;
1947 Position += Increment ;
1948 }
1949
1950 for( i = 0 , Position = 0 ; i < 2 ; i++ )
1951 {
1952 /* if ( pVBInfo->FBAddr[ Position ] != Position ) */
1953 /* if ( ( *( PULONG )( pVBInfo->FBAddr ) ) != Position ) */
1954 if ( ( *( PULONG )( pVBInfo->FBAddr + Position ) ) != Position )
1955 return( 0 ) ;
1956 Position += Increment ;
1957 }
1958 return( 1 );
1959}
1960
1961
1962/* --------------------------------------------------------------------- */
1963/* Function : XGINew_CheckDDRRank */
1964/* Input : */
1965/* Output : */
1966/* Description : */
1967/* --------------------------------------------------------------------- */
1968int XGINew_CheckDDRRank( int RankNo , int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo)
1969{
1970 ULONG Increment , Position ;
1971 USHORT data ;
1972
1973 Increment = 1 << ( DRAMTYPE_TABLE[ index ][ 2 ] + DRAMTYPE_TABLE[ index ][ 1 ] +
1974 DRAMTYPE_TABLE[ index ][ 0 ] + XGINew_DataBusWidth / 64 + RankNo ) ;
1975
1976 Increment += Increment / 2 ;
1977
1978 Position = 0;
1979 *( ( PULONG )( pVBInfo->FBAddr + Position + 0 ) ) = 0x01234567 ;
1980 *( ( PULONG )( pVBInfo->FBAddr + Position + 1 ) ) = 0x456789AB ;
1981 *( ( PULONG )( pVBInfo->FBAddr + Position + 2 ) ) = 0x55555555 ;
1982 *( ( PULONG )( pVBInfo->FBAddr + Position + 3 ) ) = 0x55555555 ;
1983 *( ( PULONG )( pVBInfo->FBAddr + Position + 4 ) ) = 0xAAAAAAAA ;
1984 *( ( PULONG )( pVBInfo->FBAddr + Position + 5 ) ) = 0xAAAAAAAA ;
1985
1986 if ( ( *( PULONG )( pVBInfo->FBAddr + 1 ) ) == 0x456789AB )
1987 return( 1 ) ;
1988
1989 if ( ( *( PULONG )( pVBInfo->FBAddr + 0 ) ) == 0x01234567 )
1990 return( 0 ) ;
1991
1992 data = XGINew_GetReg1( pVBInfo->P3c4 , 0x14 ) ;
1993 data &= 0xF3 ;
1994 data |= 0x0E ;
1995 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , data ) ;
1996 data = XGINew_GetReg1( pVBInfo->P3c4 , 0x15 ) ;
1997 data += 0x20 ;
1998 XGINew_SetReg1( pVBInfo->P3c4 , 0x15 , data ) ;
1999
2000 return( 1 ) ;
2001}
2002
2003
2004/* --------------------------------------------------------------------- */
2005/* Function : XGINew_CheckRanks */
2006/* Input : */
2007/* Output : */
2008/* Description : */
2009/* --------------------------------------------------------------------- */
2010int XGINew_CheckRanks( int RankNo , int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo)
2011{
2012 int r ;
2013
2014 for( r = RankNo ; r >= 1 ; r-- )
2015 {
2016 if ( !XGINew_CheckRank( r , index , DRAMTYPE_TABLE, pVBInfo ) )
2017 return( 0 ) ;
2018 }
2019
2020 if ( !XGINew_CheckBanks( index , DRAMTYPE_TABLE, pVBInfo ) )
2021 return( 0 ) ;
2022
2023 if ( !XGINew_CheckColumn( index , DRAMTYPE_TABLE, pVBInfo ) )
2024 return( 0 ) ;
2025
2026 return( 1 ) ;
2027}
2028
2029
2030/* --------------------------------------------------------------------- */
2031/* Function : XGINew_CheckDDRRanks */
2032/* Input : */
2033/* Output : */
2034/* Description : */
2035/* --------------------------------------------------------------------- */
2036int XGINew_CheckDDRRanks( int RankNo , int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo)
2037{
2038 int r ;
2039
2040 for( r = RankNo ; r >= 1 ; r-- )
2041 {
2042 if ( !XGINew_CheckDDRRank( r , index , DRAMTYPE_TABLE, pVBInfo ) )
2043 return( 0 ) ;
2044 }
2045
2046 if ( !XGINew_CheckBanks( index , DRAMTYPE_TABLE, pVBInfo ) )
2047 return( 0 ) ;
2048
2049 if ( !XGINew_CheckColumn( index , DRAMTYPE_TABLE, pVBInfo ) )
2050 return( 0 ) ;
2051
2052 return( 1 ) ;
2053}
2054
2055
2056/* --------------------------------------------------------------------- */
2057/* Function : */
2058/* Input : */
2059/* Output : */
2060/* Description : */
2061/* --------------------------------------------------------------------- */
2062int XGINew_SDRSizing(PVB_DEVICE_INFO pVBInfo)
2063{
2064 int i ;
2065 UCHAR j ;
2066
2067 for( i = 0 ; i < 13 ; i++ )
2068 {
2069 XGINew_SetDRAMSizingType( i , XGINew_SDRDRAM_TYPE , pVBInfo) ;
2070
2071 for( j = 2 ; j > 0 ; j-- )
2072 {
2073 if ( !XGINew_SetRank( i , ( UCHAR )j , XGINew_ChannelAB , XGINew_SDRDRAM_TYPE , pVBInfo) )
2074 continue ;
2075 else
2076 {
2077 if ( XGINew_CheckRanks( j , i , XGINew_SDRDRAM_TYPE, pVBInfo) )
2078 return( 1 ) ;
2079 }
2080 }
2081 }
2082 return( 0 ) ;
2083}
2084
2085
2086/* --------------------------------------------------------------------- */
2087/* Function : XGINew_SetDRAMSizeReg */
2088/* Input : */
2089/* Output : */
2090/* Description : */
2091/* --------------------------------------------------------------------- */
2092USHORT XGINew_SetDRAMSizeReg( int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo)
2093{
2094 USHORT data = 0 , memsize = 0 ;
2095 int RankSize ;
2096 UCHAR ChannelNo ;
2097
2098 RankSize = DRAMTYPE_TABLE[ index ][ 3 ] * XGINew_DataBusWidth / 32 ;
2099 data = XGINew_GetReg1( pVBInfo->P3c4 , 0x13 ) ;
2100 data &= 0x80 ;
2101
2102 if ( data == 0x80 )
2103 RankSize *= 2 ;
2104
2105 data = 0 ;
2106
2107 if( XGINew_ChannelAB == 3 )
2108 ChannelNo = 4 ;
2109 else
2110 ChannelNo = XGINew_ChannelAB ;
2111
2112 if ( ChannelNo * RankSize <= 256 )
2113 {
2114 while( ( RankSize >>= 1 ) > 0 )
2115 {
2116 data += 0x10 ;
2117 }
2118
2119 memsize = data >> 4 ;
2120
2121 /* [2004/03/25] Vicent, Fix DRAM Sizing Error */
2122 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , ( XGINew_GetReg1( pVBInfo->P3c4 , 0x14 ) & 0x0F ) | ( data & 0xF0 ) ) ;
2123
2124 /* data |= XGINew_ChannelAB << 2 ; */
2125 /* data |= ( XGINew_DataBusWidth / 64 ) << 1 ; */
2126 /* XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , data ) ; */
2127
2128 /* should delay */
2129 /* XGINew_SetDRAMModeRegister340( pVBInfo ) ; */
2130 }
2131 return( memsize ) ;
2132}
2133
2134
2135/* --------------------------------------------------------------------- */
2136/* Function : XGINew_SetDRAMSize20Reg */
2137/* Input : */
2138/* Output : */
2139/* Description : */
2140/* --------------------------------------------------------------------- */
2141USHORT XGINew_SetDRAMSize20Reg( int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo)
2142{
2143 USHORT data = 0 , memsize = 0 ;
2144 int RankSize ;
2145 UCHAR ChannelNo ;
2146
2147 RankSize = DRAMTYPE_TABLE[ index ][ 3 ] * XGINew_DataBusWidth / 8 ;
2148 data = XGINew_GetReg1( pVBInfo->P3c4 , 0x13 ) ;
2149 data &= 0x80 ;
2150
2151 if ( data == 0x80 )
2152 RankSize *= 2 ;
2153
2154 data = 0 ;
2155
2156 if( XGINew_ChannelAB == 3 )
2157 ChannelNo = 4 ;
2158 else
2159 ChannelNo = XGINew_ChannelAB ;
2160
2161 if ( ChannelNo * RankSize <= 256 )
2162 {
2163 while( ( RankSize >>= 1 ) > 0 )
2164 {
2165 data += 0x10 ;
2166 }
2167
2168 memsize = data >> 4 ;
2169
2170 /* [2004/03/25] Vicent, Fix DRAM Sizing Error */
2171 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , ( XGINew_GetReg1( pVBInfo->P3c4 , 0x14 ) & 0x0F ) | ( data & 0xF0 ) ) ;
2172 DelayUS( 15 ) ;
2173
2174 /* data |= XGINew_ChannelAB << 2 ; */
2175 /* data |= ( XGINew_DataBusWidth / 64 ) << 1 ; */
2176 /* XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , data ) ; */
2177
2178 /* should delay */
2179 /* XGINew_SetDRAMModeRegister340( pVBInfo ) ; */
2180 }
2181 return( memsize ) ;
2182}
2183
2184
2185/* --------------------------------------------------------------------- */
2186/* Function : XGINew_ReadWriteRest */
2187/* Input : */
2188/* Output : */
2189/* Description : */
2190/* --------------------------------------------------------------------- */
2191int XGINew_ReadWriteRest( USHORT StopAddr , USHORT StartAddr, PVB_DEVICE_INFO pVBInfo)
2192{
2193 int i ;
2194 ULONG Position = 0 ;
2195
2196 *( ( PULONG )( pVBInfo->FBAddr + Position ) ) = Position ;
2197
2198 for( i = StartAddr ; i <= StopAddr ; i++ )
2199 {
2200 Position = 1 << i ;
2201 *( ( PULONG )( pVBInfo->FBAddr + Position ) ) = Position ;
2202 }
2203
2204 DelayUS( 500 ) ; /* [Vicent] 2004/04/16. Fix #1759 Memory Size error in Multi-Adapter. */
2205
2206 Position = 0 ;
2207
2208 if ( ( *( PULONG )( pVBInfo->FBAddr + Position ) ) != Position )
2209 return( 0 ) ;
2210
2211 for( i = StartAddr ; i <= StopAddr ; i++ )
2212 {
2213 Position = 1 << i ;
2214 if ( ( *( PULONG )( pVBInfo->FBAddr + Position ) ) != Position )
2215 return( 0 ) ;
2216 }
2217 return( 1 ) ;
2218}
2219
2220
2221/* --------------------------------------------------------------------- */
2222/* Function : XGINew_CheckFrequence */
2223/* Input : */
2224/* Output : */
2225/* Description : */
2226/* --------------------------------------------------------------------- */
2227UCHAR XGINew_CheckFrequence( PVB_DEVICE_INFO pVBInfo )
2228{
2229 UCHAR data ;
2230
2231 data = XGINew_GetReg1( pVBInfo->P3d4 , 0x97 ) ;
2232
2233 if ( ( data & 0x10 ) == 0 )
2234 {
2235 data = XGINew_GetReg1( pVBInfo->P3c4 , 0x39 ) ;
2236 data = ( data & 0x02 ) >> 1 ;
2237 return( data ) ;
2238 }
2239 else
2240 return( data & 0x01 ) ;
2241}
2242
2243
2244/* --------------------------------------------------------------------- */
2245/* Function : XGINew_CheckChannel */
2246/* Input : */
2247/* Output : */
2248/* Description : */
2249/* --------------------------------------------------------------------- */
2250void XGINew_CheckChannel( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
2251{
2252 UCHAR data;
2253
2254 switch( HwDeviceExtension->jChipType )
2255 {
2256 case XG20:
2257 case XG21:
2258 data = XGINew_GetReg1( pVBInfo->P3d4 , 0x97 ) ;
2259 data = data & 0x01;
2260 XGINew_ChannelAB = 1 ; /* XG20 "JUST" one channel */
2261
2262 if ( data == 0 ) /* Single_32_16 */
2263 {
2264
2265 if (( HwDeviceExtension->ulVideoMemorySize - 1 ) > 0x1000000)
2266 {
2267
2268 XGINew_DataBusWidth = 32 ; /* 32 bits */
2269 XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xB1 ) ; /* 22bit + 2 rank + 32bit */
2270 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x52 ) ;
2271 DelayUS( 15 ) ;
2272
2273 if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 )
2274 return ;
2275
2276 if (( HwDeviceExtension->ulVideoMemorySize - 1 ) > 0x800000)
2277 {
2278 XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x31 ) ; /* 22bit + 1 rank + 32bit */
2279 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x42 ) ;
2280 DelayUS( 15 ) ;
2281
2282 if ( XGINew_ReadWriteRest( 23 , 23 , pVBInfo ) == 1 )
2283 return ;
2284 }
2285 }
2286
2287 if (( HwDeviceExtension->ulVideoMemorySize - 1 ) > 0x800000)
2288 {
2289 XGINew_DataBusWidth = 16 ; /* 16 bits */
2290 XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xB1 ) ; /* 22bit + 2 rank + 16bit */
2291 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x41 ) ;
2292 DelayUS( 15 ) ;
2293
2294 if ( XGINew_ReadWriteRest( 23 , 22 , pVBInfo ) == 1 )
2295 return ;
2296 else
2297 XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x31 ) ;
2298 DelayUS( 15 ) ;
2299 }
2300
2301 }
2302 else /* Dual_16_8 */
2303 {
2304 if (( HwDeviceExtension->ulVideoMemorySize - 1 ) > 0x800000)
2305 {
2306
2307 XGINew_DataBusWidth = 16 ; /* 16 bits */
2308 XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xB1 ) ; /* (0x31:12x8x2) 22bit + 2 rank */
2309 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x41 ) ; /* 0x41:16Mx16 bit*/
2310 DelayUS( 15 ) ;
2311
2312 if ( XGINew_ReadWriteRest( 23 , 22 , pVBInfo ) == 1 )
2313 return ;
2314
2315 if (( HwDeviceExtension->ulVideoMemorySize - 1 ) > 0x400000)
2316 {
2317 XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x31 ) ; /* (0x31:12x8x2) 22bit + 1 rank */
2318 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x31 ) ; /* 0x31:8Mx16 bit*/
2319 DelayUS( 15 ) ;
2320
2321 if ( XGINew_ReadWriteRest( 22 , 22 , pVBInfo ) == 1 )
2322 return ;
2323 }
2324 }
2325
2326
2327 if (( HwDeviceExtension->ulVideoMemorySize - 1 ) > 0x400000)
2328 {
2329 XGINew_DataBusWidth = 8 ; /* 8 bits */
2330 XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xB1 ) ; /* (0x31:12x8x2) 22bit + 2 rank */
2331 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x30 ) ; /* 0x30:8Mx8 bit*/
2332 DelayUS( 15 ) ;
2333
2334 if ( XGINew_ReadWriteRest( 22 , 21 , pVBInfo ) == 1 )
2335 return ;
2336 else
2337 XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x31 ) ; /* (0x31:12x8x2) 22bit + 1 rank */
2338 DelayUS( 15 ) ;
2339 }
2340 }
2341 break ;
2342
2343 case XG27:
2344 XGINew_DataBusWidth = 16 ; /* 16 bits */
2345 XGINew_ChannelAB = 1 ; /* Single channel */
2346 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x51 ) ; /* 32Mx16 bit*/
2347 break ;
2348 case XG41:
2349 if ( XGINew_CheckFrequence(pVBInfo) == 1 )
2350 {
2351 XGINew_DataBusWidth = 32 ; /* 32 bits */
2352 XGINew_ChannelAB = 3 ; /* Quad Channel */
2353 XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xA1 ) ;
2354 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x4C ) ;
2355
2356 if ( XGINew_ReadWriteRest( 25 , 23 , pVBInfo ) == 1 )
2357 return ;
2358
2359 XGINew_ChannelAB = 2 ; /* Dual channels */
2360 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x48 ) ;
2361
2362 if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 )
2363 return ;
2364
2365 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x49 ) ;
2366
2367 if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 )
2368 return ;
2369
2370 XGINew_ChannelAB = 3 ;
2371 XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x21 ) ;
2372 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x3C ) ;
2373
2374 if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 )
2375 return ;
2376
2377 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x38 ) ;
2378
2379 if ( XGINew_ReadWriteRest( 8 , 4 , pVBInfo ) == 1 )
2380 return ;
2381 else
2382 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x39 ) ;
2383 }
2384 else
2385 { /* DDR */
2386 XGINew_DataBusWidth = 64 ; /* 64 bits */
2387 XGINew_ChannelAB = 2 ; /* Dual channels */
2388 XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xA1 ) ;
2389 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x5A ) ;
2390
2391 if ( XGINew_ReadWriteRest( 25 , 24 , pVBInfo ) == 1 )
2392 return ;
2393
2394 XGINew_ChannelAB = 1 ; /* Single channels */
2395 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x52 ) ;
2396
2397 if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 )
2398 return ;
2399
2400 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x53 ) ;
2401
2402 if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 )
2403 return ;
2404
2405 XGINew_ChannelAB = 2 ; /* Dual channels */
2406 XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x21 ) ;
2407 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x4A ) ;
2408
2409 if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 )
2410 return ;
2411
2412 XGINew_ChannelAB = 1 ; /* Single channels */
2413 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x42 ) ;
2414
2415 if ( XGINew_ReadWriteRest( 8 , 4 , pVBInfo ) == 1 )
2416 return ;
2417 else
2418 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x43 ) ;
2419 }
2420
2421 break ;
2422
2423 case XG42:
2424/*
2425 XG42 SR14 D[3] Reserve
2426 D[2] = 1, Dual Channel
2427 = 0, Single Channel
2428
2429 It's Different from Other XG40 Series.
2430*/
2431 if ( XGINew_CheckFrequence(pVBInfo) == 1 ) /* DDRII, DDR2x */
2432 {
2433 XGINew_DataBusWidth = 32 ; /* 32 bits */
2434 XGINew_ChannelAB = 2 ; /* 2 Channel */
2435 XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xA1 ) ;
2436 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x44 ) ;
2437
2438 if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 )
2439 return ;
2440
2441 XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x21 ) ;
2442 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x34 ) ;
2443 if ( XGINew_ReadWriteRest( 23 , 22 , pVBInfo ) == 1 )
2444 return ;
2445
2446 XGINew_ChannelAB = 1 ; /* Single Channel */
2447 XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xA1 ) ;
2448 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x40 ) ;
2449
2450 if ( XGINew_ReadWriteRest( 23 , 22 , pVBInfo ) == 1 )
2451 return ;
2452 else
2453 {
2454 XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x21 ) ;
2455 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x30 ) ;
2456 }
2457 }
2458 else
2459 { /* DDR */
2460 XGINew_DataBusWidth = 64 ; /* 64 bits */
2461 XGINew_ChannelAB = 1 ; /* 1 channels */
2462 XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xA1 ) ;
2463 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x52 ) ;
2464
2465 if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 )
2466 return ;
2467 else
2468 {
2469 XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x21 ) ;
2470 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x42 ) ;
2471 }
2472 }
2473
2474 break ;
2475
2476 default: /* XG40 */
2477
2478 if ( XGINew_CheckFrequence(pVBInfo) == 1 ) /* DDRII */
2479 {
2480 XGINew_DataBusWidth = 32 ; /* 32 bits */
2481 XGINew_ChannelAB = 3 ;
2482 XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xA1 ) ;
2483 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x4C ) ;
2484
2485 if ( XGINew_ReadWriteRest( 25 , 23 , pVBInfo ) == 1 )
2486 return ;
2487
2488 XGINew_ChannelAB = 2 ; /* 2 channels */
2489 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x48 ) ;
2490
2491 if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 )
2492 return ;
2493
2494 XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x21 ) ;
2495 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x3C ) ;
2496
2497 if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 )
2498 XGINew_ChannelAB = 3 ; /* 4 channels */
2499 else
2500 {
2501 XGINew_ChannelAB = 2 ; /* 2 channels */
2502 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x38 ) ;
2503 }
2504 }
2505 else
2506 { /* DDR */
2507 XGINew_DataBusWidth = 64 ; /* 64 bits */
2508 XGINew_ChannelAB = 2 ; /* 2 channels */
2509 XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xA1 ) ;
2510 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x5A ) ;
2511
2512 if ( XGINew_ReadWriteRest( 25 , 24 , pVBInfo ) == 1 )
2513 return ;
2514 else
2515 {
2516 XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x21 ) ;
2517 XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x4A ) ;
2518 }
2519 }
2520 break ;
2521 }
2522}
2523
2524
2525/* --------------------------------------------------------------------- */
2526/* Function : XGINew_DDRSizing340 */
2527/* Input : */
2528/* Output : */
2529/* Description : */
2530/* --------------------------------------------------------------------- */
2531int XGINew_DDRSizing340( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
2532{
2533 int i ;
2534 USHORT memsize , addr ;
2535
2536 XGINew_SetReg1( pVBInfo->P3c4 , 0x15 , 0x00 ) ; /* noninterleaving */
2537 XGINew_SetReg1( pVBInfo->P3c4 , 0x1C , 0x00 ) ; /* nontiling */
2538 XGINew_CheckChannel( HwDeviceExtension, pVBInfo ) ;
2539
2540
2541 if ( HwDeviceExtension->jChipType >= XG20 )
2542 {
2543 for( i = 0 ; i < 12 ; i++ )
2544 {
2545 XGINew_SetDRAMSizingType( i , XGINew_DDRDRAM_TYPE20, pVBInfo ) ;
2546 memsize = XGINew_SetDRAMSize20Reg( i , XGINew_DDRDRAM_TYPE20, pVBInfo ) ;
2547 if ( memsize == 0 )
2548 continue ;
2549
2550 addr = memsize + ( XGINew_ChannelAB - 2 ) + 20 ;
2551 if ( ( HwDeviceExtension->ulVideoMemorySize - 1 ) < ( ULONG )( 1 << addr ) )
2552 continue ;
2553
2554 if ( XGINew_ReadWriteRest( addr , 5, pVBInfo ) == 1 )
2555 return( 1 ) ;
2556 }
2557 }
2558 else
2559 {
2560 for( i = 0 ; i < 4 ; i++ )
2561 {
2562 XGINew_SetDRAMSizingType( i , XGINew_DDRDRAM_TYPE340, pVBInfo ) ;
2563 memsize = XGINew_SetDRAMSizeReg( i , XGINew_DDRDRAM_TYPE340, pVBInfo ) ;
2564
2565 if ( memsize == 0 )
2566 continue ;
2567
2568 addr = memsize + ( XGINew_ChannelAB - 2 ) + 20 ;
2569 if ( ( HwDeviceExtension->ulVideoMemorySize - 1 ) < ( ULONG )( 1 << addr ) )
2570 continue ;
2571
2572 if ( XGINew_ReadWriteRest( addr , 9, pVBInfo ) == 1 )
2573 return( 1 ) ;
2574 }
2575 }
2576 return( 0 ) ;
2577}
2578
2579
2580/* --------------------------------------------------------------------- */
2581/* Function : XGINew_DDRSizing */
2582/* Input : */
2583/* Output : */
2584/* Description : */
2585/* --------------------------------------------------------------------- */
2586int XGINew_DDRSizing(PVB_DEVICE_INFO pVBInfo)
2587{
2588 int i ;
2589 UCHAR j ;
2590
2591 for( i = 0 ; i < 4 ; i++ )
2592 {
2593 XGINew_SetDRAMSizingType( i , XGINew_DDRDRAM_TYPE, pVBInfo ) ;
2594 XGINew_DisableChannelInterleaving( i , XGINew_DDRDRAM_TYPE , pVBInfo) ;
2595 for( j = 2 ; j > 0 ; j-- )
2596 {
2597 XGINew_SetDDRChannel( i , j , XGINew_ChannelAB , XGINew_DDRDRAM_TYPE , pVBInfo ) ;
2598 if ( !XGINew_SetRank( i , ( UCHAR )j , XGINew_ChannelAB , XGINew_DDRDRAM_TYPE, pVBInfo ) )
2599 continue ;
2600 else
2601 {
2602 if ( XGINew_CheckDDRRanks( j , i , XGINew_DDRDRAM_TYPE, pVBInfo ) )
2603 return( 1 ) ;
2604 }
2605 }
2606 }
2607 return( 0 ) ;
2608}
2609
2610/* --------------------------------------------------------------------- */
2611/* Function : XGINew_SetMemoryClock */
2612/* Input : */
2613/* Output : */
2614/* Description : */
2615/* --------------------------------------------------------------------- */
2616void XGINew_SetMemoryClock( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
2617{
2618
2619
2620 XGINew_SetReg1( pVBInfo->P3c4 , 0x28 , pVBInfo->MCLKData[ XGINew_RAMType ].SR28 ) ;
2621 XGINew_SetReg1( pVBInfo->P3c4 , 0x29 , pVBInfo->MCLKData[ XGINew_RAMType ].SR29 ) ;
2622 XGINew_SetReg1( pVBInfo->P3c4 , 0x2A , pVBInfo->MCLKData[ XGINew_RAMType ].SR2A ) ;
2623
2624
2625
2626 XGINew_SetReg1( pVBInfo->P3c4 , 0x2E , pVBInfo->ECLKData[ XGINew_RAMType ].SR2E ) ;
2627 XGINew_SetReg1( pVBInfo->P3c4 , 0x2F , pVBInfo->ECLKData[ XGINew_RAMType ].SR2F ) ;
2628 XGINew_SetReg1( pVBInfo->P3c4 , 0x30 , pVBInfo->ECLKData[ XGINew_RAMType ].SR30 ) ;
2629
2630 /* [Vicent] 2004/07/07, When XG42 ECLK = MCLK = 207MHz, Set SR32 D[1:0] = 10b */
2631 /* [Hsuan] 2004/08/20, Modify SR32 value, when MCLK=207MHZ, ELCK=250MHz, Set SR32 D[1:0] = 10b */
2632 if ( HwDeviceExtension->jChipType == XG42 )
2633 {
2634 if ( ( pVBInfo->MCLKData[ XGINew_RAMType ].SR28 == 0x1C ) && ( pVBInfo->MCLKData[ XGINew_RAMType ].SR29 == 0x01 )
2635 && ( ( ( pVBInfo->ECLKData[ XGINew_RAMType ].SR2E == 0x1C ) && ( pVBInfo->ECLKData[ XGINew_RAMType ].SR2F == 0x01 ) )
2636 || ( ( pVBInfo->ECLKData[ XGINew_RAMType ].SR2E == 0x22 ) && ( pVBInfo->ECLKData[ XGINew_RAMType ].SR2F == 0x01 ) ) ) )
2637 {
2638 XGINew_SetReg1( pVBInfo->P3c4 , 0x32 , ( ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x32 ) & 0xFC ) | 0x02 ) ;
2639 }
2640 }
2641}
2642
2643
2644/* --------------------------------------------------------------------- */
2645/* Function : ChkLFB */
2646/* Input : */
2647/* Output : */
2648/* Description : */
2649/* --------------------------------------------------------------------- */
2650BOOLEAN ChkLFB( PVB_DEVICE_INFO pVBInfo )
2651{
2652 if ( LFBDRAMTrap & XGINew_GetReg1( pVBInfo->P3d4 , 0x78 ) )
2653 return( TRUE ) ;
2654 else
2655 return( FALSE );
2656}
2657
2658
2659/* --------------------------------------------------------------------- */
2660/* input : dx ,valid value : CR or second chip's CR */
2661/* */
2662/* SetPowerConsume : */
2663/* Description: reduce 40/43 power consumption in first chip or */
2664/* in second chip, assume CR A1 D[6]="1" in this case */
2665/* output : none */
2666/* --------------------------------------------------------------------- */
2667void SetPowerConsume ( PXGI_HW_DEVICE_INFO HwDeviceExtension , ULONG XGI_P3d4Port )
2668{
2669 ULONG lTemp ;
2670 UCHAR bTemp;
2671
2672 HwDeviceExtension->pQueryVGAConfigSpace( HwDeviceExtension , 0x08 , 0 , &lTemp ) ; /* Get */
2673 if ((lTemp&0xFF)==0)
2674 {
2675 /* set CR58 D[5]=0 D[3]=0 */
2676 XGINew_SetRegAND( XGI_P3d4Port , 0x58 , 0xD7 ) ;
2677 bTemp = (UCHAR) XGINew_GetReg1( XGI_P3d4Port , 0xCB ) ;
2678 if (bTemp&0x20)
2679 {
2680 if (!(bTemp&0x10))
2681 {
2682 XGINew_SetRegANDOR( XGI_P3d4Port , 0x58 , 0xD7 , 0x20 ) ; /* CR58 D[5]=1 D[3]=0 */
2683 }
2684 else
2685 {
2686 XGINew_SetRegANDOR( XGI_P3d4Port , 0x58 , 0xD7 , 0x08 ) ; /* CR58 D[5]=0 D[3]=1 */
2687 }
2688
2689 }
2690
2691 }
2692}
2693
2694
2695
2696#if defined(LINUX_XF86)||defined(LINUX_KERNEL)
2697void XGINew_InitVBIOSData(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
2698{
2699
2700 /* ULONG ROMAddr = (ULONG)HwDeviceExtension->pjVirtualRomBase; */
2701 pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
2702 pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ;
2703 pVBInfo->BaseAddr = (ULONG)HwDeviceExtension->pjIOAddress ;
2704 pVBInfo->ISXPDOS = 0 ;
2705
2706 pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ;
2707 pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ;
2708 pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10 ;
2709 pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e ;
2710 pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ;
2711 pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a ;
2712 pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16 ;
2713 pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17 ;
2714 pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18 ;
2715 pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19 ;
2716 pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A ;
2717 pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00 ;
2718 pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04 ;
2719 pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ;
2720 pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12 ;
2721 pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ;
2722 pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2 ;
2723 if ( HwDeviceExtension->jChipType < XG20 ) /* kuku 2004/06/25 */
2724 XGI_GetVBType( pVBInfo ) ; /* Run XGI_GetVBType before InitTo330Pointer */
2725
2726 switch(HwDeviceExtension->jChipType)
2727 {
2728 case XG40:
2729 case XG41:
2730 case XG42:
2731 case XG20:
2732 case XG21:
2733 default:
2734 InitTo330Pointer(HwDeviceExtension->jChipType,pVBInfo);
2735 return ;
2736 }
2737
2738}
2739#endif /* For Linux */
2740
2741/* --------------------------------------------------------------------- */
2742/* Function : ReadVBIOSTablData */
2743/* Input : */
2744/* Output : */
2745/* Description : */
2746/* --------------------------------------------------------------------- */
2747void ReadVBIOSTablData( UCHAR ChipType , PVB_DEVICE_INFO pVBInfo)
2748{
2749 PUCHAR volatile pVideoMemory = ( PUCHAR )pVBInfo->ROMAddr ;
2750 ULONG i ;
2751 UCHAR j , k ;
2752#if 0
2753 ULONG ii , jj ;
2754 i = pVideoMemory[ 0x1CF ] | ( pVideoMemory[ 0x1D0 ] << 8 ) ; /* UniROM */
2755 if ( i != 0 )
2756 UNIROM = 1 ;
2757
2758 ii = 0x90 ;
2759 for( jj = 0x00 ; jj < 0x08 ; jj++ )
2760 {
2761 pVBInfo->MCLKData[ jj ].SR28 = pVideoMemory[ ii ] ;
2762 pVBInfo->MCLKData[ jj ].SR29 = pVideoMemory[ ii + 1] ;
2763 pVBInfo->MCLKData[ jj ].SR2A = pVideoMemory[ ii + 2] ;
2764 pVBInfo->MCLKData[ jj ].CLOCK = pVideoMemory[ ii + 3 ] | ( pVideoMemory[ ii + 4 ] << 8 ) ;
2765 ii += 0x05 ;
2766 }
2767
2768 ii = 0xB8 ;
2769 for( jj = 0x00 ; jj < 0x08 ; jj++ )
2770 {
2771 pVBInfo->ECLKData[ jj ].SR2E = pVideoMemory[ ii ] ;
2772 pVBInfo->ECLKData[ jj ].SR2F=pVideoMemory[ ii + 1 ] ;
2773 pVBInfo->ECLKData[ jj ].SR30= pVideoMemory[ ii + 2 ] ;
2774 pVBInfo->ECLKData[ jj ].CLOCK= pVideoMemory[ ii + 3 ] | ( pVideoMemory[ ii + 4 ] << 8 ) ;
2775 ii += 0x05 ;
2776 }
2777
2778 /* Volari customize data area start */
2779 /* if ( ChipType == XG40 ) */
2780 if ( ChipType >= XG40 )
2781 {
2782 ii = 0xE0 ;
2783 for( jj = 0x00 ; jj < 0x03 ; jj++ )
2784 {
2785 pVBInfo->SR15[ jj ][ 0 ] = pVideoMemory[ ii ] ; /* SR13, SR14, and SR18 */
2786 pVBInfo->SR15[ jj ][ 1 ] = pVideoMemory[ ii + 1 ] ;
2787 pVBInfo->SR15[ jj ][ 2 ] = pVideoMemory[ ii + 2 ] ;
2788 pVBInfo->SR15[ jj ][ 3 ] = pVideoMemory[ ii + 3 ] ;
2789 pVBInfo->SR15[ jj ][ 4 ] = pVideoMemory[ ii + 4 ] ;
2790 pVBInfo->SR15[ jj ][ 5 ] = pVideoMemory[ ii + 5 ] ;
2791 pVBInfo->SR15[ jj ][ 6 ] = pVideoMemory[ ii + 6 ] ;
2792 pVBInfo->SR15[ jj ][ 7 ] = pVideoMemory[ ii + 7 ] ;
2793 ii += 0x08 ;
2794 }
2795 ii = 0x110 ;
2796 jj = 0x03 ;
2797 pVBInfo->SR15[ jj ][ 0 ] = pVideoMemory[ ii ] ; /* SR1B */
2798 pVBInfo->SR15[ jj ][ 1 ] = pVideoMemory[ ii + 1 ] ;
2799 pVBInfo->SR15[ jj ][ 2 ] = pVideoMemory[ ii + 2 ] ;
2800 pVBInfo->SR15[ jj ][ 3 ] = pVideoMemory[ ii + 3 ] ;
2801 pVBInfo->SR15[ jj ][ 4 ] = pVideoMemory[ ii + 4 ] ;
2802 pVBInfo->SR15[ jj ][ 5 ] = pVideoMemory[ ii + 5 ] ;
2803 pVBInfo->SR15[ jj ][ 6 ] = pVideoMemory[ ii + 6 ] ;
2804 pVBInfo->SR15[ jj ][ 7 ] = pVideoMemory[ ii + 7 ] ;
2805
2806 *pVBInfo->pSR07 = pVideoMemory[ 0x74 ] ;
2807 *pVBInfo->pSR1F = pVideoMemory[ 0x75 ] ;
2808 *pVBInfo->pSR21 = pVideoMemory[ 0x76 ] ;
2809 *pVBInfo->pSR22 = pVideoMemory[ 0x77 ] ;
2810 *pVBInfo->pSR23 = pVideoMemory[ 0x78 ] ;
2811 *pVBInfo->pSR24 = pVideoMemory[ 0x79 ] ;
2812 pVBInfo->SR25[ 0 ] = pVideoMemory[ 0x7A ] ;
2813 *pVBInfo->pSR31 = pVideoMemory[ 0x7B ] ;
2814 *pVBInfo->pSR32 = pVideoMemory[ 0x7C ] ;
2815 *pVBInfo->pSR33 = pVideoMemory[ 0x7D ] ;
2816 ii = 0xF8 ;
2817
2818 for( jj = 0 ; jj < 3 ; jj++ )
2819 {
2820 pVBInfo->CR40[ jj ][ 0 ] = pVideoMemory[ ii ] ;
2821 pVBInfo->CR40[ jj ][ 1 ] = pVideoMemory[ ii + 1 ] ;
2822 pVBInfo->CR40[ jj ][ 2 ] = pVideoMemory[ ii + 2 ] ;
2823 pVBInfo->CR40[ jj ][ 3 ] = pVideoMemory[ ii + 3 ] ;
2824 pVBInfo->CR40[ jj ][ 4 ] = pVideoMemory[ ii + 4 ] ;
2825 pVBInfo->CR40[ jj ][ 5 ] = pVideoMemory[ ii + 5 ] ;
2826 pVBInfo->CR40[ jj ][ 6 ] = pVideoMemory[ ii + 6 ] ;
2827 pVBInfo->CR40[ jj ][ 7 ] = pVideoMemory[ ii + 7 ] ;
2828 ii += 0x08 ;
2829 }
2830
2831 ii = 0x118 ;
2832 for( j = 3 ; j < 24 ; j++ )
2833 {
2834 pVBInfo->CR40[ j ][ 0 ] = pVideoMemory[ ii ] ;
2835 pVBInfo->CR40[ j ][ 1 ] = pVideoMemory[ ii + 1 ] ;
2836 pVBInfo->CR40[ j ][ 2 ] = pVideoMemory[ ii + 2 ] ;
2837 pVBInfo->CR40[ j ][ 3 ] = pVideoMemory[ ii + 3 ] ;
2838 pVBInfo->CR40[ j ][ 4 ] = pVideoMemory[ ii + 4 ] ;
2839 pVBInfo->CR40[ j ][ 5 ] = pVideoMemory[ ii + 5 ] ;
2840 pVBInfo->CR40[ j ][ 6 ] = pVideoMemory[ ii + 6 ] ;
2841 pVBInfo->CR40[ j ][ 7 ] = pVideoMemory[ ii + 7 ] ;
2842 ii += 0x08 ;
2843 }
2844
2845 i = pVideoMemory[ 0x1C0 ] | ( pVideoMemory[ 0x1C1 ] << 8 ) ;
2846
2847 for( j = 0 ; j < 8 ; j++ )
2848 {
2849 for( k = 0 ; k < 4 ; k++ )
2850 pVBInfo->CR6B[ j ][ k ] = pVideoMemory[ i + 4 * j + k ] ;
2851 }
2852
2853 i = pVideoMemory[ 0x1C2 ] | ( pVideoMemory[ 0x1C3 ] << 8 ) ;
2854
2855 for( j = 0 ; j < 8 ; j++ )
2856 {
2857 for( k = 0 ; k < 4 ; k++ )
2858 pVBInfo->CR6E[ j ][ k ] = pVideoMemory[ i + 4 * j + k ] ;
2859 }
2860
2861 i = pVideoMemory[ 0x1C4 ] | ( pVideoMemory[ 0x1C5 ] << 8 ) ;
2862 for( j = 0 ; j < 8 ; j++ )
2863 {
2864 for( k = 0 ; k < 32 ; k++ )
2865 pVBInfo->CR6F[ j ][ k ] = pVideoMemory[ i + 32 * j + k ] ;
2866 }
2867
2868 i = pVideoMemory[ 0x1C6 ] | ( pVideoMemory[ 0x1C7 ] << 8 ) ;
2869
2870 for( j = 0 ; j < 8 ; j++ )
2871 {
2872 for( k = 0 ; k < 2 ; k++ )
2873 pVBInfo->CR89[ j ][ k ] = pVideoMemory[ i + 2 * j + k ] ;
2874 }
2875
2876 i = pVideoMemory[ 0x1C8 ] | ( pVideoMemory[ 0x1C9 ] << 8 ) ;
2877 for( j = 0 ; j < 12 ; j++ )
2878 pVBInfo->AGPReg[ j ] = pVideoMemory[ i + j ] ;
2879
2880 i = pVideoMemory[ 0x1CF ] | ( pVideoMemory[ 0x1D0 ] << 8 ) ;
2881 for( j = 0 ; j < 4 ; j++ )
2882 pVBInfo->SR16[ j ] = pVideoMemory[ i + j ] ;
2883
2884 if ( ChipType == XG21 )
2885 {
2886 if (pVideoMemory[ 0x67 ] & 0x80)
2887 {
2888 *pVBInfo->pDVOSetting = pVideoMemory[ 0x67 ];
2889 }
2890 if ( (pVideoMemory[ 0x67 ] & 0xC0) == 0xC0 )
2891 {
2892 *pVBInfo->pCR2E = pVideoMemory[ i + 4 ] ;
2893 *pVBInfo->pCR2F = pVideoMemory[ i + 5 ] ;
2894 *pVBInfo->pCR46 = pVideoMemory[ i + 6 ] ;
2895 *pVBInfo->pCR47 = pVideoMemory[ i + 7 ] ;
2896 }
2897 }
2898
2899 if ( ChipType == XG27 )
2900 {
2901 jj = i+j;
2902 for( i = 0 ; i <= 0xB ; i++,jj++ )
2903 pVBInfo->pCRD0[i] = pVideoMemory[ jj ] ;
2904 for( i = 0x0 ; i <= 0x1 ; i++,jj++ )
2905 pVBInfo->pCRDE[i] = pVideoMemory[ jj ] ;
2906
2907 *pVBInfo->pSR40 = pVideoMemory[ jj ] ;
2908 jj++;
2909 *pVBInfo->pSR41 = pVideoMemory[ jj ] ;
2910
2911 if (pVideoMemory[ 0x67 ] & 0x80)
2912 {
2913 *pVBInfo->pDVOSetting = pVideoMemory[ 0x67 ];
2914 }
2915 if ( (pVideoMemory[ 0x67 ] & 0xC0) == 0xC0 )
2916 {
2917 jj++;
2918 *pVBInfo->pCR2E = pVideoMemory[ jj ] ;
2919 *pVBInfo->pCR2F = pVideoMemory[ jj + 1 ] ;
2920 *pVBInfo->pCR46 = pVideoMemory[ jj + 2 ] ;
2921 *pVBInfo->pCR47 = pVideoMemory[ jj + 3 ] ;
2922 }
2923
2924 }
2925
2926 *pVBInfo->pCRCF = pVideoMemory[ 0x1CA ] ;
2927 *pVBInfo->pXGINew_DRAMTypeDefinition = pVideoMemory[ 0x1CB ] ;
2928 *pVBInfo->pXGINew_I2CDefinition = pVideoMemory[ 0x1D1 ] ;
2929 if ( ChipType >= XG20 )
2930 {
2931 *pVBInfo->pXGINew_CR97 = pVideoMemory[ 0x1D2 ] ;
2932 if ( ChipType == XG27 )
2933 {
2934 *pVBInfo->pSR36 = pVideoMemory[ 0x1D3 ] ;
2935 *pVBInfo->pCR8F = pVideoMemory[ 0x1D5 ] ;
2936 }
2937 }
2938
2939 }
2940#endif
2941 /* Volari customize data area end */
2942
2943 if ( ChipType == XG21 )
2944 {
2945 pVBInfo->IF_DEF_LVDS = 0 ;
2946 if (pVideoMemory[ 0x65 ] & 0x1)
2947 {
2948 pVBInfo->IF_DEF_LVDS = 1 ;
2949 i = pVideoMemory[ 0x316 ] | ( pVideoMemory[ 0x317 ] << 8 );
2950 j = pVideoMemory[ i-1 ] ;
2951 if ( j != 0xff )
2952 {
2953 k = 0;
2954 do
2955 {
2956 pVBInfo->XG21_LVDSCapList[k].LVDS_Capability = pVideoMemory[ i ] | ( pVideoMemory[ i + 1 ] << 8 );
2957 pVBInfo->XG21_LVDSCapList[k].LVDSHT = pVideoMemory[ i + 2 ] | ( pVideoMemory[ i + 3 ] << 8 ) ;
2958 pVBInfo->XG21_LVDSCapList[k].LVDSVT = pVideoMemory[ i + 4 ] | ( pVideoMemory[ i + 5 ] << 8 );
2959 pVBInfo->XG21_LVDSCapList[k].LVDSHDE = pVideoMemory[ i + 6 ] | ( pVideoMemory[ i + 7 ] << 8 );
2960 pVBInfo->XG21_LVDSCapList[k].LVDSVDE = pVideoMemory[ i + 8 ] | ( pVideoMemory[ i + 9 ] << 8 );
2961 pVBInfo->XG21_LVDSCapList[k].LVDSHFP = pVideoMemory[ i + 10 ] | ( pVideoMemory[ i + 11 ] << 8 );
2962 pVBInfo->XG21_LVDSCapList[k].LVDSVFP = pVideoMemory[ i + 12 ] | ( pVideoMemory[ i + 13 ] << 8 );
2963 pVBInfo->XG21_LVDSCapList[k].LVDSHSYNC = pVideoMemory[ i + 14 ] | ( pVideoMemory[ i + 15 ] << 8 );
2964 pVBInfo->XG21_LVDSCapList[k].LVDSVSYNC = pVideoMemory[ i + 16 ] | ( pVideoMemory[ i + 17 ] << 8 );
2965 pVBInfo->XG21_LVDSCapList[k].VCLKData1 = pVideoMemory[ i + 18 ] ;
2966 pVBInfo->XG21_LVDSCapList[k].VCLKData2 = pVideoMemory[ i + 19 ] ;
2967 pVBInfo->XG21_LVDSCapList[k].PSC_S1 = pVideoMemory[ i + 20 ] ;
2968 pVBInfo->XG21_LVDSCapList[k].PSC_S2 = pVideoMemory[ i + 21 ] ;
2969 pVBInfo->XG21_LVDSCapList[k].PSC_S3 = pVideoMemory[ i + 22 ] ;
2970 pVBInfo->XG21_LVDSCapList[k].PSC_S4 = pVideoMemory[ i + 23 ] ;
2971 pVBInfo->XG21_LVDSCapList[k].PSC_S5 = pVideoMemory[ i + 24 ] ;
2972 i += 25;
2973 j--;
2974 k++;
2975 } while ( (j>0) && ( k < (sizeof(XGI21_LCDCapList)/sizeof(XGI21_LVDSCapStruct)) ) );
2976 }
2977 else
2978 {
2979 pVBInfo->XG21_LVDSCapList[0].LVDS_Capability = pVideoMemory[ i ] | ( pVideoMemory[ i + 1 ] << 8 );
2980 pVBInfo->XG21_LVDSCapList[0].LVDSHT = pVideoMemory[ i + 2 ] | ( pVideoMemory[ i + 3 ] << 8 ) ;
2981 pVBInfo->XG21_LVDSCapList[0].LVDSVT = pVideoMemory[ i + 4 ] | ( pVideoMemory[ i + 5 ] << 8 );
2982 pVBInfo->XG21_LVDSCapList[0].LVDSHDE = pVideoMemory[ i + 6 ] | ( pVideoMemory[ i + 7 ] << 8 );
2983 pVBInfo->XG21_LVDSCapList[0].LVDSVDE = pVideoMemory[ i + 8 ] | ( pVideoMemory[ i + 9 ] << 8 );
2984 pVBInfo->XG21_LVDSCapList[0].LVDSHFP = pVideoMemory[ i + 10 ] | ( pVideoMemory[ i + 11 ] << 8 );
2985 pVBInfo->XG21_LVDSCapList[0].LVDSVFP = pVideoMemory[ i + 12 ] | ( pVideoMemory[ i + 13 ] << 8 );
2986 pVBInfo->XG21_LVDSCapList[0].LVDSHSYNC = pVideoMemory[ i + 14 ] | ( pVideoMemory[ i + 15 ] << 8 );
2987 pVBInfo->XG21_LVDSCapList[0].LVDSVSYNC = pVideoMemory[ i + 16 ] | ( pVideoMemory[ i + 17 ] << 8 );
2988 pVBInfo->XG21_LVDSCapList[0].VCLKData1 = pVideoMemory[ i + 18 ] ;
2989 pVBInfo->XG21_LVDSCapList[0].VCLKData2 = pVideoMemory[ i + 19 ] ;
2990 pVBInfo->XG21_LVDSCapList[0].PSC_S1 = pVideoMemory[ i + 20 ] ;
2991 pVBInfo->XG21_LVDSCapList[0].PSC_S2 = pVideoMemory[ i + 21 ] ;
2992 pVBInfo->XG21_LVDSCapList[0].PSC_S3 = pVideoMemory[ i + 22 ] ;
2993 pVBInfo->XG21_LVDSCapList[0].PSC_S4 = pVideoMemory[ i + 23 ] ;
2994 pVBInfo->XG21_LVDSCapList[0].PSC_S5 = pVideoMemory[ i + 24 ] ;
2995 }
2996 }
2997 }
2998}
2999
3000/* --------------------------------------------------------------------- */
3001/* Function : XGINew_DDR1x_MRS_XG20 */
3002/* Input : */
3003/* Output : */
3004/* Description : */
3005/* --------------------------------------------------------------------- */
3006void XGINew_DDR1x_MRS_XG20( ULONG P3c4 , PVB_DEVICE_INFO pVBInfo)
3007{
3008
3009 XGINew_SetReg1( P3c4 , 0x18 , 0x01 ) ;
3010 XGINew_SetReg1( P3c4 , 0x19 , 0x40 ) ;
3011 XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ;
3012 XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ;
3013 DelayUS( 60 ) ;
3014
3015 XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ;
3016 XGINew_SetReg1( P3c4 , 0x19 , 0x40 ) ;
3017 XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ;
3018 XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ;
3019 DelayUS( 60 ) ;
3020 XGINew_SetReg1( P3c4 , 0x18 , pVBInfo->SR15[ 2 ][ XGINew_RAMType ] ) ; /* SR18 */
3021 /* XGINew_SetReg1( P3c4 , 0x18 , 0x31 ) ; */
3022 XGINew_SetReg1( P3c4 , 0x19 , 0x01 ) ;
3023 XGINew_SetReg1( P3c4 , 0x16 , 0x03 ) ;
3024 XGINew_SetReg1( P3c4 , 0x16 , 0x83 ) ;
3025 DelayUS( 1000 ) ;
3026 XGINew_SetReg1( P3c4 , 0x1B , 0x03 ) ;
3027 DelayUS( 500 ) ;
3028 /* XGINew_SetReg1( P3c4 , 0x18 , 0x31 ) ; */
3029 XGINew_SetReg1( P3c4 , 0x18 , pVBInfo->SR15[ 2 ][ XGINew_RAMType ] ) ; /* SR18 */
3030 XGINew_SetReg1( P3c4 , 0x19 , 0x00 ) ;
3031 XGINew_SetReg1( P3c4 , 0x16 , 0x03 ) ;
3032 XGINew_SetReg1( P3c4 , 0x16 , 0x83 ) ;
3033 XGINew_SetReg1( P3c4 , 0x1B , 0x00 ) ;
3034}
3035
3036/* --------------------------------------------------------------------- */
3037/* Function : XGINew_SetDRAMModeRegister_XG20 */
3038/* Input : */
3039/* Output : */
3040/* Description : */
3041/* --------------------------------------------------------------------- */
3042void XGINew_SetDRAMModeRegister_XG20( PXGI_HW_DEVICE_INFO HwDeviceExtension )
3043{
3044 VB_DEVICE_INFO VBINF;
3045 PVB_DEVICE_INFO pVBInfo = &VBINF;
3046 pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
3047 pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ;
3048 pVBInfo->BaseAddr = (ULONG)HwDeviceExtension->pjIOAddress ;
3049 pVBInfo->ISXPDOS = 0 ;
3050
3051 pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ;
3052 pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ;
3053 pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10 ;
3054 pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e ;
3055 pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ;
3056 pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a ;
3057 pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16 ;
3058 pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17 ;
3059 pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18 ;
3060 pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19 ;
3061 pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A ;
3062 pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00 ;
3063 pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04 ;
3064 pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ;
3065 pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12 ;
3066 pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ;
3067 pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2 ;
3068
3069 InitTo330Pointer(HwDeviceExtension->jChipType,pVBInfo);
3070
3071 ReadVBIOSTablData( HwDeviceExtension->jChipType , pVBInfo) ;
3072
3073 if ( XGINew_GetXG20DRAMType( HwDeviceExtension, pVBInfo) == 0 )
3074 XGINew_DDR1x_MRS_XG20( pVBInfo->P3c4, pVBInfo ) ;
3075 else
3076 XGINew_DDR2_MRS_XG20( HwDeviceExtension , pVBInfo->P3c4 , pVBInfo ) ;
3077
3078 XGINew_SetReg1( pVBInfo->P3c4 , 0x1B , 0x03 ) ;
3079}
3080
3081void XGINew_SetDRAMModeRegister_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension )
3082{
3083 VB_DEVICE_INFO VBINF;
3084 PVB_DEVICE_INFO pVBInfo = &VBINF;
3085 pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
3086 pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ;
3087 pVBInfo->BaseAddr = (ULONG)HwDeviceExtension->pjIOAddress ;
3088 pVBInfo->ISXPDOS = 0 ;
3089
3090 pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ;
3091 pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ;
3092 pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10 ;
3093 pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e ;
3094 pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ;
3095 pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a ;
3096 pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16 ;
3097 pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17 ;
3098 pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18 ;
3099 pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19 ;
3100 pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A ;
3101 pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00 ;
3102 pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04 ;
3103 pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ;
3104 pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12 ;
3105 pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ;
3106 pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2 ;
3107
3108 InitTo330Pointer(HwDeviceExtension->jChipType,pVBInfo);
3109
3110 ReadVBIOSTablData( HwDeviceExtension->jChipType , pVBInfo) ;
3111
3112 if ( XGINew_GetXG20DRAMType( HwDeviceExtension, pVBInfo) == 0 )
3113 XGINew_DDR1x_MRS_XG20( pVBInfo->P3c4, pVBInfo ) ;
3114 else
3115 //XGINew_DDR2_MRS_XG27( HwDeviceExtension , pVBInfo->P3c4 , pVBInfo ) ;
3116 XGINew_DDRII_Bootup_XG27( HwDeviceExtension , pVBInfo->P3c4 , pVBInfo) ;
3117
3118 //XGINew_SetReg1( pVBInfo->P3c4 , 0x1B , 0x03 ) ;
3119 XGINew_SetReg1( pVBInfo->P3c4 , 0x1B , pVBInfo->SR15[ 3 ][ XGINew_RAMType ] ) ; /* SR1B */
3120
3121}
3122/*
3123void XGINew_SetDRAMModeRegister_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension )
3124{
3125#ifndef LINUX_XF86
3126 UCHAR data ;
3127#endif
3128 VB_DEVICE_INFO VBINF;
3129 PVB_DEVICE_INFO pVBInfo = &VBINF;
3130 pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
3131 pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ;
3132 pVBInfo->BaseAddr = HwDeviceExtension->pjIOAddress ;
3133 pVBInfo->ISXPDOS = 0 ;
3134
3135 pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ;
3136 pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ;
3137 pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10 ;
3138 pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e ;
3139 pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ;
3140 pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a ;
3141 pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16 ;
3142 pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17 ;
3143 pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18 ;
3144 pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19 ;
3145 pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A ;
3146 pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00 ;
3147 pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04 ;
3148 pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ;
3149 pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12 ;
3150 pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ;
3151 pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2 ;
3152
3153 InitTo330Pointer(HwDeviceExtension->jChipType,pVBInfo);
3154
3155 ReadVBIOSTablData( HwDeviceExtension->jChipType , pVBInfo) ;
3156
3157 if ( XGINew_GetXG20DRAMType( HwDeviceExtension, pVBInfo) == 0 )
3158 XGINew_DDR1x_MRS_XG20( pVBInfo->P3c4, pVBInfo ) ;
3159 else
3160 XGINew_DDR2_MRS_XG27( HwDeviceExtension , pVBInfo->P3c4 , pVBInfo ) ;
3161
3162 XGINew_SetReg1( pVBInfo->P3c4 , 0x1B , 0x03 ) ;
3163}
3164*/
3165/* -------------------------------------------------------- */
3166/* Function : XGINew_ChkSenseStatus */
3167/* Input : */
3168/* Output : */
3169/* Description : */
3170/* -------------------------------------------------------- */
3171void XGINew_ChkSenseStatus ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
3172{
3173 USHORT tempbx=0 , temp , tempcx , CR3CData;
3174
3175 temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x32 ) ;
3176
3177 if ( temp & Monitor1Sense )
3178 tempbx |= ActiveCRT1 ;
3179 if ( temp & LCDSense )
3180 tempbx |= ActiveLCD ;
3181 if ( temp & Monitor2Sense )
3182 tempbx |= ActiveCRT2 ;
3183 if ( temp & TVSense )
3184 {
3185 tempbx |= ActiveTV ;
3186 if ( temp & AVIDEOSense )
3187 tempbx |= ( ActiveAVideo << 8 );
3188 if ( temp & SVIDEOSense )
3189 tempbx |= ( ActiveSVideo << 8 );
3190 if ( temp & SCARTSense )
3191 tempbx |= ( ActiveSCART << 8 );
3192 if ( temp & HiTVSense )
3193 tempbx |= ( ActiveHiTV << 8 );
3194 if ( temp & YPbPrSense )
3195 tempbx |= ( ActiveYPbPr << 8 );
3196 }
3197
3198 tempcx = XGINew_GetReg1( pVBInfo->P3d4 , 0x3d ) ;
3199 tempcx |= ( XGINew_GetReg1( pVBInfo->P3d4 , 0x3e ) << 8 ) ;
3200
3201 if ( tempbx & tempcx )
3202 {
3203 CR3CData = XGINew_GetReg1( pVBInfo->P3d4 , 0x3c ) ;
3204 if ( !( CR3CData & DisplayDeviceFromCMOS ) )
3205 {
3206 tempcx = 0x1FF0 ;
3207 if ( *pVBInfo->pSoftSetting & ModeSoftSetting )
3208 {
3209 tempbx = 0x1FF0 ;
3210 }
3211 }
3212 }
3213 else
3214 {
3215 tempcx = 0x1FF0 ;
3216 if ( *pVBInfo->pSoftSetting & ModeSoftSetting )
3217 {
3218 tempbx = 0x1FF0 ;
3219 }
3220 }
3221
3222 tempbx &= tempcx ;
3223 XGINew_SetReg1( pVBInfo->P3d4, 0x3d , ( tempbx & 0x00FF ) ) ;
3224 XGINew_SetReg1( pVBInfo->P3d4, 0x3e , ( ( tempbx & 0xFF00 ) >> 8 )) ;
3225}
3226/* -------------------------------------------------------- */
3227/* Function : XGINew_SetModeScratch */
3228/* Input : */
3229/* Output : */
3230/* Description : */
3231/* -------------------------------------------------------- */
3232void XGINew_SetModeScratch ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo )
3233{
3234 USHORT temp , tempcl = 0 , tempch = 0 , CR31Data , CR38Data;
3235
3236 temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x3d ) ;
3237 temp |= XGINew_GetReg1( pVBInfo->P3d4 , 0x3e ) << 8 ;
3238 temp |= ( XGINew_GetReg1( pVBInfo->P3d4 , 0x31 ) & ( DriverMode >> 8) ) << 8 ;
3239
3240 if ( pVBInfo->IF_DEF_CRT2Monitor == 1)
3241 {
3242 if ( temp & ActiveCRT2 )
3243 tempcl = SetCRT2ToRAMDAC ;
3244 }
3245
3246 if ( temp & ActiveLCD )
3247 {
3248 tempcl |= SetCRT2ToLCD ;
3249 if ( temp & DriverMode )
3250 {
3251 if ( temp & ActiveTV )
3252 {
3253 tempch = SetToLCDA | EnableDualEdge ;
3254 temp ^= SetCRT2ToLCD ;
3255
3256 if ( ( temp >> 8 ) & ActiveAVideo )
3257 tempcl |= SetCRT2ToAVIDEO ;
3258 if ( ( temp >> 8 ) & ActiveSVideo )
3259 tempcl |= SetCRT2ToSVIDEO ;
3260 if ( ( temp >> 8 ) & ActiveSCART )
3261 tempcl |= SetCRT2ToSCART ;
3262
3263 if ( pVBInfo->IF_DEF_HiVision == 1 )
3264 {
3265 if ( ( temp >> 8 ) & ActiveHiTV )
3266 tempcl |= SetCRT2ToHiVisionTV ;
3267 }
3268
3269 if ( pVBInfo->IF_DEF_YPbPr == 1 )
3270 {
3271 if ( ( temp >> 8 ) & ActiveYPbPr )
3272 tempch |= SetYPbPr ;
3273 }
3274 }
3275 }
3276 }
3277 else
3278 {
3279 if ( ( temp >> 8 ) & ActiveAVideo )
3280 tempcl |= SetCRT2ToAVIDEO ;
3281 if ( ( temp >> 8 ) & ActiveSVideo )
3282 tempcl |= SetCRT2ToSVIDEO ;
3283 if ( ( temp >> 8 ) & ActiveSCART )
3284 tempcl |= SetCRT2ToSCART ;
3285
3286 if ( pVBInfo->IF_DEF_HiVision == 1 )
3287 {
3288 if ( ( temp >> 8 ) & ActiveHiTV )
3289 tempcl |= SetCRT2ToHiVisionTV ;
3290 }
3291
3292 if ( pVBInfo->IF_DEF_YPbPr == 1 )
3293 {
3294 if ( ( temp >> 8 ) & ActiveYPbPr )
3295 tempch |= SetYPbPr ;
3296 }
3297 }
3298
3299
3300 tempcl |= SetSimuScanMode ;
3301 if ( (!( temp & ActiveCRT1 )) && ( ( temp & ActiveLCD ) || ( temp & ActiveTV ) || ( temp & ActiveCRT2 ) ) )
3302 tempcl ^= ( SetSimuScanMode | SwitchToCRT2 ) ;
3303 if ( ( temp & ActiveLCD ) && ( temp & ActiveTV ) )
3304 tempcl ^= ( SetSimuScanMode | SwitchToCRT2 ) ;
3305 XGINew_SetReg1( pVBInfo->P3d4, 0x30 , tempcl ) ;
3306
3307 CR31Data = XGINew_GetReg1( pVBInfo->P3d4 , 0x31 ) ;
3308 CR31Data &= ~( SetNotSimuMode >> 8 ) ;
3309 if ( !( temp & ActiveCRT1 ) )
3310 CR31Data |= ( SetNotSimuMode >> 8 ) ;
3311 CR31Data &= ~( DisableCRT2Display >> 8 ) ;
3312 if (!( ( temp & ActiveLCD ) || ( temp & ActiveTV ) || ( temp & ActiveCRT2 ) ) )
3313 CR31Data |= ( DisableCRT2Display >> 8 ) ;
3314 XGINew_SetReg1( pVBInfo->P3d4, 0x31 , CR31Data ) ;
3315
3316 CR38Data = XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) ;
3317 CR38Data &= ~SetYPbPr ;
3318 CR38Data |= tempch ;
3319 XGINew_SetReg1( pVBInfo->P3d4, 0x38 , CR38Data ) ;
3320
3321}
3322
3323/* -------------------------------------------------------- */
3324/* Function : XGINew_GetXG21Sense */
3325/* Input : */
3326/* Output : */
3327/* Description : */
3328/* -------------------------------------------------------- */
3329void XGINew_GetXG21Sense(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
3330{
3331 UCHAR Temp;
3332 PUCHAR volatile pVideoMemory = ( PUCHAR )pVBInfo->ROMAddr ;
3333
3334 pVBInfo->IF_DEF_LVDS = 0 ;
3335
3336#ifdef WIN2000
3337 pVBInfo->IF_DEF_CH7007 = 0 ;
3338 if ( ( pVideoMemory[ 0x65 ] & 0x02 ) ) /* For XG21 CH7007 */
3339 {
3340 /* VideoDebugPrint((0, "ReadVBIOSTablData: pVideoMemory[ 0x65 ] =%x\n",pVideoMemory[ 0x65 ])); */
3341 pVBInfo->IF_DEF_CH7007 = 1 ; /* [Billy] 07/05/03 */
3342 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x38 , ~0xE0 , 0x60 ) ; /* CH7007 on chip */
3343 }
3344 else
3345#endif
3346#if 1
3347 if (( pVideoMemory[ 0x65 ] & 0x01 ) ) /* For XG21 LVDS */
3348 {
3349 pVBInfo->IF_DEF_LVDS = 1 ;
3350 XGINew_SetRegOR( pVBInfo->P3d4 , 0x32 , LCDSense ) ;
3351 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x38 , ~0xE0 , 0xC0 ) ; /* LVDS on chip */
3352 }
3353 else
3354 {
3355#endif
3356 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x4A , ~0x03 , 0x03 ) ; /* Enable GPIOA/B read */
3357 Temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x48 ) & 0xC0;
3358 if ( Temp == 0xC0 )
3359 { /* DVI & DVO GPIOA/B pull high */
3360 XGINew_SenseLCD( HwDeviceExtension, pVBInfo ) ;
3361 XGINew_SetRegOR( pVBInfo->P3d4 , 0x32 , LCDSense ) ;
3362 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x4A , ~0x20 , 0x20 ) ; /* Enable read GPIOF */
3363 Temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x48 ) & 0x04 ;
3364 if ( !Temp )
3365 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x38 , ~0xE0 , 0x80 ) ; /* TMDS on chip */
3366 else
3367 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x38 , ~0xE0 , 0xA0 ) ; /* Only DVO on chip */
3368 XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~0x20 ) ; /* Disable read GPIOF */
3369 }
3370#if 1
3371 }
3372#endif
3373}
3374
3375/* -------------------------------------------------------- */
3376/* Function : XGINew_GetXG27Sense */
3377/* Input : */
3378/* Output : */
3379/* Description : */
3380/* -------------------------------------------------------- */
3381void XGINew_GetXG27Sense(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
3382{
3383 UCHAR Temp,bCR4A;
3384
3385 pVBInfo->IF_DEF_LVDS = 0 ;
3386 bCR4A = XGINew_GetReg1( pVBInfo->P3d4 , 0x4A ) ;
3387 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x4A , ~0x07 , 0x07 ) ; /* Enable GPIOA/B/C read */
3388 Temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x48 ) & 0x07;
3389 XGINew_SetReg1( pVBInfo->P3d4, 0x4A , bCR4A ) ;
3390
3391 if ( Temp <= 0x02 )
3392 {
3393 pVBInfo->IF_DEF_LVDS = 1 ;
3394 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x38 , ~0xE0 , 0xC0 ) ; /* LVDS setting */
3395 XGINew_SetReg1( pVBInfo->P3d4, 0x30 , 0x21 ) ;
3396 }
3397 else
3398 {
3399 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x38 , ~0xE0 , 0xA0 ) ; /* TMDS/DVO setting */
3400 }
3401 XGINew_SetRegOR( pVBInfo->P3d4 , 0x32 , LCDSense ) ;
3402
3403}
3404
3405UCHAR GetXG21FPBits(PVB_DEVICE_INFO pVBInfo)
3406{
3407 UCHAR CR38,CR4A,temp;
3408
3409 CR4A = XGINew_GetReg1( pVBInfo->P3d4 , 0x4A ) ;
3410 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x4A , ~0x10 , 0x10 ) ; /* enable GPIOE read */
3411 CR38 = XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) ;
3412 temp =0;
3413 if ( ( CR38 & 0xE0 ) > 0x80 )
3414 {
3415 temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x48 ) ;
3416 temp &= 0x08;
3417 temp >>= 3;
3418 }
3419
3420 XGINew_SetReg1( pVBInfo->P3d4, 0x4A , CR4A ) ;
3421
3422 return temp;
3423}
3424
3425UCHAR GetXG27FPBits(PVB_DEVICE_INFO pVBInfo)
3426{
3427 UCHAR CR4A,temp;
3428
3429 CR4A = XGINew_GetReg1( pVBInfo->P3d4 , 0x4A ) ;
3430 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x4A , ~0x03 , 0x03 ) ; /* enable GPIOA/B/C read */
3431 temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x48 ) ;
3432 if ( temp <= 2 )
3433 {
3434 temp &= 0x03;
3435 }
3436 else
3437 {
3438 temp = ((temp&0x04)>>1) || ((~temp)&0x01);
3439 }
3440 XGINew_SetReg1( pVBInfo->P3d4, 0x4A , CR4A ) ;
3441
3442 return temp;
3443}
3444
diff --git a/drivers/staging/xgifb/vb_init.h b/drivers/staging/xgifb/vb_init.h
new file mode 100644
index 000000000000..1f39d9c74cdd
--- /dev/null
+++ b/drivers/staging/xgifb/vb_init.h
@@ -0,0 +1,7 @@
1#ifndef _VBINIT_
2#define _VBINIT_
3extern BOOLEAN XGIInitNew( PXGI_HW_DEVICE_INFO HwDeviceExtension ) ;
4extern XGI21_LVDSCapStruct XGI21_LCDCapList[13];
5
6#endif
7
diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c
new file mode 100644
index 000000000000..bd7f73898644
--- /dev/null
+++ b/drivers/staging/xgifb/vb_setmode.c
@@ -0,0 +1,10736 @@
1#include "osdef.h"
2
3#ifdef TC
4#include <stdio.h>
5#include <string.h>
6#include <conio.h>
7#include <dos.h>
8#endif
9
10
11#ifdef LINUX_XF86
12#include "xf86.h"
13#include "xf86PciInfo.h"
14#include "xgi.h"
15#include "xgi_regs.h"
16#endif
17
18#ifdef LINUX_KERNEL
19#include <asm/io.h>
20#include <linux/types.h>
21#include <linux/version.h>
22#include "XGIfb.h"
23/*#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
24#include <video/XGIfb.h>
25#else
26#include <linux/XGIfb.h>
27#endif*/
28#endif
29
30#ifdef WIN2000
31#include <dderror.h>
32#include <devioctl.h>
33#include <miniport.h>
34#include <ntddvdeo.h>
35#include <video.h>
36
37#include "xgiv.h"
38#include "dd_i2c.h"
39#include "tools.h"
40#endif
41
42#include "vb_def.h"
43#include "vgatypes.h"
44#include "vb_struct.h"
45#include "vb_util.h"
46#include "vb_table.h"
47
48
49
50#define IndexMask 0xff
51#ifndef XGI_MASK_DUAL_CHIP
52#define XGI_MASK_DUAL_CHIP 0x04 /* SR3A */
53#endif
54
55
56
57BOOLEAN XGI_IsLCDDualLink(PVB_DEVICE_INFO pVBInfo);
58BOOLEAN XGI_SetCRT2Group301(USHORT ModeNo, PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo);
59BOOLEAN XGI_BacklightByDrv(PVB_DEVICE_INFO pVBInfo);
60
61BOOLEAN XGI_IsLCDON(PVB_DEVICE_INFO pVBInfo);
62BOOLEAN XGI_DisableChISLCD(PVB_DEVICE_INFO pVBInfo);
63BOOLEAN XGI_EnableChISLCD(PVB_DEVICE_INFO pVBInfo);
64BOOLEAN XGI_AjustCRT2Rate(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,USHORT *i, PVB_DEVICE_INFO pVBInfo);
65BOOLEAN XGI_SearchModeID( USHORT ModeNo,USHORT *ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
66BOOLEAN XGI_GetLCDInfo(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
67BOOLEAN XGISetModeNew( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo ) ;
68BOOLEAN XGI_BridgeIsOn(PVB_DEVICE_INFO pVBInfo);
69UCHAR XGI_GetModePtr( USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo);
70USHORT XGI_GetOffset(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo);
71USHORT XGI_GetRatePtrCRT2( PXGI_HW_DEVICE_INFO pXGIHWDE, USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo );
72USHORT XGI_GetResInfo(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
73USHORT XGI_GetColorDepth(USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo);
74USHORT XGI_GetVGAHT2(PVB_DEVICE_INFO pVBInfo);
75USHORT XGI_GetVCLK2Ptr(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo);
76void XGI_VBLongWait(PVB_DEVICE_INFO pVBInfo);
77void XGI_SaveCRT2Info(USHORT ModeNo, PVB_DEVICE_INFO pVBInfo);
78void XGI_GetCRT2Data(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
79void XGI_GetCRT2ResInfo(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
80void XGI_PreSetGroup1(USHORT ModeNo,USHORT ModeIdIndex, PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
81void XGI_SetGroup1(USHORT ModeNo,USHORT ModeIdIndex, PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
82void XGI_SetLockRegs(USHORT ModeNo,USHORT ModeIdIndex, PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
83void XGI_SetLCDRegs(USHORT ModeNo,USHORT ModeIdIndex, PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
84void XGI_SetGroup2(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
85void XGI_SetGroup3(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
86void XGI_SetGroup4(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
87void XGI_SetGroup5(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
88void* XGI_GetLcdPtr(USHORT BX, USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
89void* XGI_GetTVPtr(USHORT BX, USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
90void XGI_FirePWDEnable(PVB_DEVICE_INFO pVBInfo);
91void XGI_EnableGatingCRT(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
92void XGI_DisableGatingCRT(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
93void XGI_SetPanelDelay(USHORT tempbl, PVB_DEVICE_INFO pVBInfo);
94void XGI_SetPanelPower(USHORT tempah,USHORT tempbl, PVB_DEVICE_INFO pVBInfo);
95void XGI_EnablePWD( PVB_DEVICE_INFO pVBInfo);
96void XGI_DisablePWD( PVB_DEVICE_INFO pVBInfo);
97void XGI_AutoThreshold( PVB_DEVICE_INFO pVBInfo);
98void XGI_SetTap4Regs( PVB_DEVICE_INFO pVBInfo);
99
100void XGI_DisplayOn(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo);
101void XGI_DisplayOff( PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo );
102void XGI_SetCRT1Group(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo);
103void XGI_SetXG21CRTC(USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
104void XGI_SetXG21LCD(PVB_DEVICE_INFO pVBInfo,USHORT RefreshRateTableIndex,USHORT ModeNo);
105void XGI_SetXG27CRTC(USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
106void XGI_SetXG27LCD(PVB_DEVICE_INFO pVBInfo,USHORT RefreshRateTableIndex,USHORT ModeNo);
107void XGI_UpdateXG21CRTC(USHORT ModeNo, PVB_DEVICE_INFO pVBInfo, USHORT RefreshRateTableIndex);
108void XGI_WaitDisply(PVB_DEVICE_INFO pVBInfo);
109void XGI_SenseCRT1(PVB_DEVICE_INFO pVBInfo);
110void XGI_SetSeqRegs(USHORT ModeNo,USHORT StandTableIndex,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo);
111void XGI_SetMiscRegs(USHORT StandTableIndex, PVB_DEVICE_INFO pVBInfo);
112void XGI_SetCRTCRegs(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT StandTableIndex, PVB_DEVICE_INFO pVBInfo);
113void XGI_SetATTRegs(USHORT ModeNo,USHORT StandTableIndex,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo );
114void XGI_SetGRCRegs(USHORT StandTableIndex, PVB_DEVICE_INFO pVBInfo);
115void XGI_ClearExt1Regs(PVB_DEVICE_INFO pVBInfo);
116
117void XGI_SetSync(USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo);
118void XGI_SetCRT1CRTC(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo,PXGI_HW_DEVICE_INFO HwDeviceExtension);
119void XGI_SetCRT1Timing_H(PVB_DEVICE_INFO pVBInfo,PXGI_HW_DEVICE_INFO HwDeviceExtension);
120void XGI_SetCRT1Timing_V(USHORT ModeIdIndex,USHORT ModeNo,PVB_DEVICE_INFO pVBInfo);
121void XGI_SetCRT1DE(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo);
122void XGI_SetCRT1VCLK(USHORT ModeNo,USHORT ModeIdIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
123void XGI_SetCRT1FIFO(USHORT ModeNo,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
124void XGI_SetCRT1ModeRegs(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo);
125void XGI_SetVCLKState(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo,USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo);
126
127void XGI_LoadDAC(USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo);
128void XGI_WriteDAC(USHORT dl, USHORT ah, USHORT al, USHORT dh, PVB_DEVICE_INFO pVBInfo);
129/*void XGI_ClearBuffer(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo,PVB_DEVICE_INFO pVBInfo);*/
130void XGI_SetLCDAGroup(USHORT ModeNo,USHORT ModeIdIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo);
131void XGI_GetLVDSResInfo( USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo);
132void XGI_GetLVDSData(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo);
133void XGI_ModCRT1Regs(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo);
134void XGI_SetLVDSRegs(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo);
135void XGI_UpdateModeInfo(PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo);
136void XGI_GetVGAType(PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo);
137void XGI_GetVBType(PVB_DEVICE_INFO pVBInfo);
138void XGI_GetVBInfo(USHORT ModeNo,USHORT ModeIdIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo);
139void XGI_GetTVInfo(USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo);
140void XGI_SetCRT2ECLK( USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo);
141void InitTo330Pointer(UCHAR,PVB_DEVICE_INFO pVBInfo);
142void XGI_GetLCDSync(USHORT* HSyncWidth, USHORT* VSyncWidth, PVB_DEVICE_INFO pVBInfo);
143void XGI_DisableBridge(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
144void XGI_EnableBridge(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo);
145void XGI_SetCRT2VCLK(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
146void XGI_OEM310Setting(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
147void XGI_SetDelayComp(PVB_DEVICE_INFO pVBInfo);
148void XGI_SetLCDCap(PVB_DEVICE_INFO pVBInfo);
149void XGI_SetLCDCap_A(USHORT tempcx,PVB_DEVICE_INFO pVBInfo);
150void XGI_SetLCDCap_B(USHORT tempcx,PVB_DEVICE_INFO pVBInfo);
151void SetSpectrum(PVB_DEVICE_INFO pVBInfo);
152void XGI_SetAntiFlicker(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
153void XGI_SetEdgeEnhance(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
154void XGI_SetPhaseIncr(PVB_DEVICE_INFO pVBInfo);
155void XGI_SetYFilter(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
156void XGI_GetTVPtrIndex2(USHORT* tempbx,UCHAR* tempcl,UCHAR* tempch, PVB_DEVICE_INFO pVBInfo);
157USHORT XGI_GetTVPtrIndex( PVB_DEVICE_INFO pVBInfo );
158void XGI_SetCRT2ModeRegs(USHORT ModeNo,PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo );
159void XGI_CloseCRTC(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo);
160void XGI_OpenCRTC(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo);
161void XGI_GetRAMDAC2DATA(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo);
162void XGI_UnLockCRT2(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo);
163void XGI_LockCRT2(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo);
164void XGINew_EnableCRT2(PVB_DEVICE_INFO pVBInfo);
165void XGINew_LCD_Wait_Time(UCHAR DelayTime, PVB_DEVICE_INFO pVBInfo);
166void XGI_LongWait(PVB_DEVICE_INFO pVBInfo);
167void XGI_SetCRT1Offset( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo );
168void XGI_GetLCDVCLKPtr(UCHAR* di_0,UCHAR *di_1, PVB_DEVICE_INFO pVBInfo);
169UCHAR XGI_GetVCLKPtr(USHORT RefreshRateTableIndex,USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
170void XGI_GetVCLKLen(UCHAR tempal,UCHAR* di_0,UCHAR* di_1, PVB_DEVICE_INFO pVBInfo);
171USHORT XGI_GetLCDCapPtr(PVB_DEVICE_INFO pVBInfo);
172USHORT XGI_GetLCDCapPtr1(PVB_DEVICE_INFO pVBInfo);
173XGI301C_Tap4TimingStruct* XGI_GetTap4Ptr(USHORT tempcx, PVB_DEVICE_INFO pVBInfo);
174void XGI_SetXG21FPBits(PVB_DEVICE_INFO pVBInfo);
175void XGI_SetXG27FPBits(PVB_DEVICE_INFO pVBInfo);
176UCHAR XGI_XG21GetPSCValue(PVB_DEVICE_INFO pVBInfo);
177UCHAR XGI_XG27GetPSCValue(PVB_DEVICE_INFO pVBInfo);
178void XGI_XG21BLSignalVDD(USHORT tempbh,USHORT tempbl, PVB_DEVICE_INFO pVBInfo);
179void XGI_XG27BLSignalVDD(USHORT tempbh,USHORT tempbl, PVB_DEVICE_INFO pVBInfo);
180void XGI_XG21SetPanelDelay(USHORT tempbl, PVB_DEVICE_INFO pVBInfo);
181BOOLEAN XGI_XG21CheckLVDSMode(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo );
182void XGI_SetXG21LVDSPara(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo );
183void XGI_SetXG27LVDSPara(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo );
184UCHAR XGI_SetDefaultVCLK( PVB_DEVICE_INFO pVBInfo );
185
186extern void ReadVBIOSTablData( UCHAR ChipType , PVB_DEVICE_INFO pVBInfo);
187#ifdef WIN2000
188/* [Billy] 2007/05/17 For CH7007 */
189extern UCHAR CH7007TVReg_UNTSC[][8],CH7007TVReg_ONTSC[][8],CH7007TVReg_UPAL[][8],CH7007TVReg_OPAL[][8];
190extern UCHAR CH7007TVCRT1UNTSC_H[][10],CH7007TVCRT1ONTSC_H[][10],CH7007TVCRT1UPAL_H[][10],CH7007TVCRT1OPAL_H[][10] ;
191extern UCHAR CH7007TVCRT1UNTSC_V[][10],CH7007TVCRT1ONTSC_V[][10],CH7007TVCRT1UPAL_V[][10],CH7007TVCRT1OPAL_V[][10] ;
192extern UCHAR XGI7007_CHTVVCLKUNTSC[],XGI7007_CHTVVCLKONTSC[],XGI7007_CHTVVCLKUPAL[],XGI7007_CHTVVCLKOPAL[];
193
194extern BOOLEAN XGI_XG21CheckCH7007TVMode(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo ) ;
195extern void SetCH7007Regs(PXGI_HW_DEVICE_INFO HwDeviceExtension, USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo ) ;
196extern VP_STATUS TurnOnCH7007(PHW_DEVICE_EXTENSION pHWDE) ;
197extern VP_STATUS TurnOffCH7007(PHW_DEVICE_EXTENSION pHWDE) ;
198extern BOOLEAN IsCH7007TVMode(PVB_DEVICE_INFO pVBInfo) ;
199#endif
200
201/* USHORT XGINew_flag_clearbuffer; 0: no clear frame buffer 1:clear frame buffer */
202
203
204
205
206
207USHORT XGINew_MDA_DAC[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
208 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
209 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
210 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
211 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
212 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
213 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
214 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F};
215
216USHORT XGINew_CGA_DAC[]={0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
217 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
218 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
219 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
220 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
221 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
222 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
223 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F};
224
225USHORT XGINew_EGA_DAC[]={0x00,0x10,0x04,0x14,0x01,0x11,0x05,0x15,
226 0x20,0x30,0x24,0x34,0x21,0x31,0x25,0x35,
227 0x08,0x18,0x0C,0x1C,0x09,0x19,0x0D,0x1D,
228 0x28,0x38,0x2C,0x3C,0x29,0x39,0x2D,0x3D,
229 0x02,0x12,0x06,0x16,0x03,0x13,0x07,0x17,
230 0x22,0x32,0x26,0x36,0x23,0x33,0x27,0x37,
231 0x0A,0x1A,0x0E,0x1E,0x0B,0x1B,0x0F,0x1F,
232 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F};
233
234USHORT XGINew_VGA_DAC[]={0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
235 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
236 0x00,0x05,0x08,0x0B,0x0E,0x11,0x14,0x18,
237 0x1C,0x20,0x24,0x28,0x2D,0x32,0x38,0x3F,
238
239 0x00,0x10,0x1F,0x2F,0x3F,0x1F,0x27,0x2F,
240 0x37,0x3F,0x2D,0x31,0x36,0x3A,0x3F,0x00,
241 0x07,0x0E,0x15,0x1C,0x0E,0x11,0x15,0x18,
242 0x1C,0x14,0x16,0x18,0x1A,0x1C,0x00,0x04,
243 0x08,0x0C,0x10,0x08,0x0A,0x0C,0x0E,0x10,
244 0x0B,0x0C,0x0D,0x0F,0x10};
245
246
247/* --------------------------------------------------------------------- */
248/* Function : InitTo330Pointer */
249/* Input : */
250/* Output : */
251/* Description : */
252/* --------------------------------------------------------------------- */
253void InitTo330Pointer( UCHAR ChipType ,PVB_DEVICE_INFO pVBInfo)
254{
255 pVBInfo->SModeIDTable = (XGI_StStruct *) XGI330_SModeIDTable ;
256 pVBInfo->StandTable = (XGI_StandTableStruct *) XGI330_StandTable ;
257 pVBInfo->EModeIDTable = (XGI_ExtStruct *) XGI330_EModeIDTable ;
258 pVBInfo->RefIndex = (XGI_Ext2Struct *) XGI330_RefIndex ;
259 pVBInfo->XGINEWUB_CRT1Table = (XGI_CRT1TableStruct *) XGI_CRT1Table ;
260
261 /* add for new UNIVGABIOS */
262 /* XGINew_UBLCDDataTable = (XGI_LCDDataTablStruct *) XGI_LCDDataTable ; */
263 /* XGINew_UBTVDataTable = (XGI_TVDataTablStruct *) XGI_TVDataTable ; */
264
265
266 if ( ChipType >= XG40 )
267 {
268 pVBInfo->MCLKData = (XGI_MCLKDataStruct *) XGI340New_MCLKData ;
269 pVBInfo->ECLKData = (XGI_ECLKDataStruct *) XGI340_ECLKData ;
270 }
271 else
272 {
273 pVBInfo->MCLKData = (XGI_MCLKDataStruct *) XGI330New_MCLKData ;
274 pVBInfo->ECLKData = (XGI_ECLKDataStruct *) XGI330_ECLKData ;
275 }
276
277 pVBInfo->VCLKData = (XGI_VCLKDataStruct *) XGI_VCLKData ;
278 pVBInfo->VBVCLKData = (XGI_VBVCLKDataStruct *) XGI_VBVCLKData ;
279 pVBInfo->ScreenOffset = XGI330_ScreenOffset ;
280 pVBInfo->StResInfo = (XGI_StResInfoStruct *) XGI330_StResInfo ;
281 pVBInfo->ModeResInfo = (XGI_ModeResInfoStruct *) XGI330_ModeResInfo ;
282
283 pVBInfo->pOutputSelect = &XGI330_OutputSelect ;
284 pVBInfo->pSoftSetting = &XGI330_SoftSetting ;
285 pVBInfo->pSR07 = &XGI330_SR07 ;
286 pVBInfo->LCDResInfo = 0 ;
287 pVBInfo->LCDTypeInfo = 0 ;
288 pVBInfo->LCDInfo = 0 ;
289 pVBInfo->VBInfo = 0 ;
290 pVBInfo->TVInfo = 0;
291
292
293 pVBInfo->SR15 = XGI340_SR13 ;
294 pVBInfo->CR40 = XGI340_cr41 ;
295 pVBInfo->SR25 = XGI330_sr25 ;
296 pVBInfo->pSR31 = &XGI330_sr31 ;
297 pVBInfo->pSR32 = &XGI330_sr32 ;
298 pVBInfo->CR6B = XGI340_CR6B ;
299 pVBInfo->CR6E = XGI340_CR6E ;
300 pVBInfo->CR6F = XGI340_CR6F ;
301 pVBInfo->CR89 = XGI340_CR89 ;
302 pVBInfo->AGPReg = XGI340_AGPReg ;
303 pVBInfo->SR16 = XGI340_SR16 ;
304 pVBInfo->pCRCF = &XG40_CRCF ;
305 pVBInfo->pXGINew_DRAMTypeDefinition = &XG40_DRAMTypeDefinition ;
306
307
308 pVBInfo->CR49 = XGI330_CR49 ;
309 pVBInfo->pSR1F = &XGI330_SR1F ;
310 pVBInfo->pSR21 = &XGI330_SR21 ;
311 pVBInfo->pSR22 = &XGI330_SR22 ;
312 pVBInfo->pSR23 = &XGI330_SR23 ;
313 pVBInfo->pSR24 = &XGI330_SR24 ;
314 pVBInfo->pSR33 = &XGI330_SR33 ;
315
316
317
318 pVBInfo->pCRT2Data_1_2 = &XGI330_CRT2Data_1_2 ;
319 pVBInfo->pCRT2Data_4_D = &XGI330_CRT2Data_4_D ;
320 pVBInfo->pCRT2Data_4_E = &XGI330_CRT2Data_4_E ;
321 pVBInfo->pCRT2Data_4_10 = &XGI330_CRT2Data_4_10 ;
322 pVBInfo->pRGBSenseData = &XGI330_RGBSenseData ;
323 pVBInfo->pVideoSenseData = &XGI330_VideoSenseData ;
324 pVBInfo->pYCSenseData = &XGI330_YCSenseData ;
325 pVBInfo->pRGBSenseData2 = &XGI330_RGBSenseData2 ;
326 pVBInfo->pVideoSenseData2 = &XGI330_VideoSenseData2 ;
327 pVBInfo->pYCSenseData2 = &XGI330_YCSenseData2 ;
328
329 pVBInfo->NTSCTiming = XGI330_NTSCTiming ;
330 pVBInfo->PALTiming = XGI330_PALTiming ;
331 pVBInfo->HiTVExtTiming = XGI330_HiTVExtTiming ;
332 pVBInfo->HiTVSt1Timing = XGI330_HiTVSt1Timing ;
333 pVBInfo->HiTVSt2Timing = XGI330_HiTVSt2Timing ;
334 pVBInfo->HiTVTextTiming = XGI330_HiTVTextTiming ;
335 pVBInfo->YPbPr750pTiming = XGI330_YPbPr750pTiming ;
336 pVBInfo->YPbPr525pTiming = XGI330_YPbPr525pTiming ;
337 pVBInfo->YPbPr525iTiming = XGI330_YPbPr525iTiming ;
338 pVBInfo->HiTVGroup3Data = XGI330_HiTVGroup3Data ;
339 pVBInfo->HiTVGroup3Simu = XGI330_HiTVGroup3Simu ;
340 pVBInfo->HiTVGroup3Text = XGI330_HiTVGroup3Text ;
341 pVBInfo->Ren525pGroup3 = XGI330_Ren525pGroup3 ;
342 pVBInfo->Ren750pGroup3 = XGI330_Ren750pGroup3 ;
343
344
345 pVBInfo->TimingH = (XGI_TimingHStruct *) XGI_TimingH ;
346 pVBInfo->TimingV = (XGI_TimingVStruct *) XGI_TimingV ;
347 pVBInfo->UpdateCRT1 = (XGI_XG21CRT1Struct *) XGI_UpdateCRT1Table ;
348
349 pVBInfo->CHTVVCLKUNTSC = XGI330_CHTVVCLKUNTSC ;
350 pVBInfo->CHTVVCLKONTSC = XGI330_CHTVVCLKONTSC ;
351 pVBInfo->CHTVVCLKUPAL = XGI330_CHTVVCLKUPAL ;
352 pVBInfo->CHTVVCLKOPAL = XGI330_CHTVVCLKOPAL ;
353
354 /* 310 customization related */
355 if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) )
356 pVBInfo->LCDCapList = XGI_LCDDLCapList ;
357 else
358 pVBInfo->LCDCapList = XGI_LCDCapList ;
359
360 if ( ( ChipType == XG21 ) || ( ChipType == XG27 ) )
361 pVBInfo->XG21_LVDSCapList = XGI21_LCDCapList ;
362
363 pVBInfo->XGI_TVDelayList = XGI301TVDelayList ;
364 pVBInfo->XGI_TVDelayList2 = XGI301TVDelayList2 ;
365
366
367 pVBInfo->pXGINew_I2CDefinition = &XG40_I2CDefinition ;
368
369 if ( ChipType >= XG20 )
370 pVBInfo->pXGINew_CR97 = &XG20_CR97 ;
371
372 if ( ChipType == XG27 )
373 {
374 pVBInfo->MCLKData = (XGI_MCLKDataStruct *) XGI27New_MCLKData ;
375 pVBInfo->CR40 = XGI27_cr41 ;
376 pVBInfo->pXGINew_CR97 = &XG27_CR97 ;
377 pVBInfo->pSR36 = &XG27_SR36 ;
378 pVBInfo->pCR8F = &XG27_CR8F ;
379 pVBInfo->pCRD0 = XG27_CRD0 ;
380 pVBInfo->pCRDE = XG27_CRDE ;
381 pVBInfo->pSR40 = &XG27_SR40 ;
382 pVBInfo->pSR41 = &XG27_SR41 ;
383
384 }
385
386 if ( ChipType >= XG20 )
387 {
388 pVBInfo->pDVOSetting = &XG21_DVOSetting ;
389 pVBInfo->pCR2E = &XG21_CR2E ;
390 pVBInfo->pCR2F = &XG21_CR2F ;
391 pVBInfo->pCR46 = &XG21_CR46 ;
392 pVBInfo->pCR47 = &XG21_CR47 ;
393 }
394
395}
396
397
398
399
400
401
402/* --------------------------------------------------------------------- */
403/* Function : XGISetModeNew */
404/* Input : */
405/* Output : */
406/* Description : */
407/* --------------------------------------------------------------------- */
408BOOLEAN XGISetModeNew( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo )
409{
410 USHORT ModeIdIndex ;
411 /* PUCHAR pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ; */
412 VB_DEVICE_INFO VBINF;
413 PVB_DEVICE_INFO pVBInfo = &VBINF;
414 pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ;
415 pVBInfo->BaseAddr = (ULONG)HwDeviceExtension->pjIOAddress ;
416 pVBInfo->IF_DEF_LVDS = 0 ;
417 pVBInfo->IF_DEF_CH7005 = 0 ;
418 pVBInfo->IF_DEF_LCDA = 1 ;
419 pVBInfo->IF_DEF_CH7017 = 0 ;
420 pVBInfo->IF_DEF_CH7007 = 0 ; /* [Billy] 2007/05/14 */
421 pVBInfo->IF_DEF_VideoCapture = 0 ;
422 pVBInfo->IF_DEF_ScaleLCD = 0 ;
423 pVBInfo->IF_DEF_OEMUtil = 0 ;
424 pVBInfo->IF_DEF_PWD = 0 ;
425
426
427 if ( HwDeviceExtension->jChipType >= XG20 ) /* kuku 2004/06/25 */
428 {
429 pVBInfo->IF_DEF_YPbPr = 0 ;
430 pVBInfo->IF_DEF_HiVision = 0 ;
431 pVBInfo->IF_DEF_CRT2Monitor = 0 ;
432 pVBInfo->VBType = 0 ; /*set VBType default 0*/
433 }
434 else if ( HwDeviceExtension->jChipType >= XG40 )
435 {
436 pVBInfo->IF_DEF_YPbPr = 1 ;
437 pVBInfo->IF_DEF_HiVision = 1 ;
438 pVBInfo->IF_DEF_CRT2Monitor = 1 ;
439 }
440 else
441 {
442 pVBInfo->IF_DEF_YPbPr = 1 ;
443 pVBInfo->IF_DEF_HiVision = 1 ;
444 pVBInfo->IF_DEF_CRT2Monitor = 0 ;
445 }
446
447 pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ;
448 pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ;
449 pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10 ;
450 pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e ;
451 pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ;
452 pVBInfo->P3cc = pVBInfo->BaseAddr + 0x1C ;
453 pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a ;
454 pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16 ;
455 pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17 ;
456 pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18 ;
457 pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19 ;
458 pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A ;
459 pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00 ;
460 pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04 ;
461 pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ;
462 pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12 ;
463 pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ;
464 pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2 ;
465
466 if ( HwDeviceExtension->jChipType == XG21 ) /* for x86 Linux, XG21 LVDS */
467 {
468 if ( ( XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) & 0xE0 ) == 0xC0 )
469 {
470 pVBInfo->IF_DEF_LVDS = 1 ;
471 }
472 }
473 if ( HwDeviceExtension->jChipType == XG27 )
474 {
475 if ( ( XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) & 0xE0 ) == 0xC0 )
476 {
477 if ( XGINew_GetReg1( pVBInfo->P3d4 , 0x30 ) & 0x20 )
478 {
479 pVBInfo->IF_DEF_LVDS = 1 ;
480 }
481 }
482 }
483
484 if ( HwDeviceExtension->jChipType < XG20 ) /* kuku 2004/06/25 */
485 XGI_GetVBType( pVBInfo ) ;
486
487 InitTo330Pointer( HwDeviceExtension->jChipType, pVBInfo ) ;
488#ifdef WIN2000
489 ReadVBIOSTablData( HwDeviceExtension->jChipType , pVBInfo) ;
490#endif
491 if ( ModeNo & 0x80 )
492 {
493 ModeNo = ModeNo & 0x7F ;
494/* XGINew_flag_clearbuffer = 0 ; */
495 }
496/* else
497 {
498 XGINew_flag_clearbuffer = 1 ;
499 }
500*/
501 XGINew_SetReg1( pVBInfo->P3c4 , 0x05 , 0x86 ) ;
502
503 if ( HwDeviceExtension->jChipType < XG20 ) /* kuku 2004/06/25 1.Openkey */
504 XGI_UnLockCRT2( HwDeviceExtension , pVBInfo ) ;
505
506 XGI_SearchModeID( ModeNo , &ModeIdIndex, pVBInfo ) ;
507
508 XGI_GetVGAType(HwDeviceExtension, pVBInfo) ;
509
510 if ( HwDeviceExtension->jChipType < XG20 ) /* kuku 2004/06/25 */
511 {
512 XGI_GetVBInfo(ModeNo , ModeIdIndex , HwDeviceExtension, pVBInfo ) ;
513 XGI_GetTVInfo(ModeNo , ModeIdIndex, pVBInfo ) ;
514 XGI_GetLCDInfo(ModeNo , ModeIdIndex, pVBInfo ) ;
515 XGI_DisableBridge( HwDeviceExtension,pVBInfo ) ;
516/* XGI_OpenCRTC( HwDeviceExtension, pVBInfo ) ; */
517
518 if ( pVBInfo->VBInfo & ( SetSimuScanMode | SetCRT2ToLCDA ) )
519 {
520 XGI_SetCRT1Group(HwDeviceExtension , ModeNo , ModeIdIndex, pVBInfo ) ;
521
522 if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
523 {
524 XGI_SetLCDAGroup(ModeNo , ModeIdIndex , HwDeviceExtension, pVBInfo ) ;
525 }
526 }
527 else
528 {
529 if ( !( pVBInfo->VBInfo & SwitchToCRT2) )
530 {
531 XGI_SetCRT1Group( HwDeviceExtension , ModeNo , ModeIdIndex, pVBInfo ) ;
532 if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
533 {
534 XGI_SetLCDAGroup( ModeNo , ModeIdIndex , HwDeviceExtension, pVBInfo ) ;
535 }
536 }
537 }
538
539 if ( pVBInfo->VBInfo & ( SetSimuScanMode | SwitchToCRT2 ) )
540 {
541 switch( HwDeviceExtension->ujVBChipID )
542 {
543 case VB_CHIP_301:
544 XGI_SetCRT2Group301( ModeNo , HwDeviceExtension, pVBInfo ) ; /*add for CRT2 */
545 break ;
546
547 case VB_CHIP_302:
548 XGI_SetCRT2Group301(ModeNo , HwDeviceExtension, pVBInfo ) ; /*add for CRT2 */
549 break ;
550
551 default:
552 break ;
553 }
554 }
555
556 XGI_SetCRT2ModeRegs( ModeNo, HwDeviceExtension,pVBInfo ) ;
557 XGI_OEM310Setting( ModeNo, ModeIdIndex,pVBInfo ) ; /*0212*/
558 XGI_CloseCRTC( HwDeviceExtension, pVBInfo ) ;
559 XGI_EnableBridge( HwDeviceExtension ,pVBInfo) ;
560 } /* !XG20 */
561 else
562 {
563#ifdef WIN2000
564 if ( pVBInfo->IF_DEF_CH7007 == 1 )
565 {
566
567 VideoDebugPrint((0, "XGISetModeNew: pVBIfo->IF_DEF_CH7007==1\n"));
568 pVBInfo->VBType = VB_CH7007 ;
569 XGI_GetVBInfo(ModeNo , ModeIdIndex , HwDeviceExtension, pVBInfo ) ;
570 XGI_GetTVInfo(ModeNo , ModeIdIndex, pVBInfo ) ;
571 XGI_GetLCDInfo(ModeNo , ModeIdIndex, pVBInfo ) ;
572 if( !(XGI_XG21CheckCH7007TVMode(ModeNo, ModeIdIndex, pVBInfo )) )
573 {
574 return FALSE;
575 }
576 }
577#endif
578
579
580 if ( pVBInfo->IF_DEF_LVDS == 1 )
581 {
582 if ( !XGI_XG21CheckLVDSMode(ModeNo , ModeIdIndex, pVBInfo) )
583 {
584 return FALSE;
585 }
586 }
587
588 if ( ModeNo <= 0x13 )
589 {
590 pVBInfo->ModeType = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag & ModeInfoFlag;
591 }
592 else
593 {
594 pVBInfo->ModeType = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag & ModeInfoFlag;
595 }
596
597 pVBInfo->SetFlag = 0 ;
598 if ( pVBInfo->IF_DEF_CH7007 != 1 )
599 {
600 pVBInfo->VBInfo = DisableCRT2Display ;
601 }
602
603
604 XGI_DisplayOff(HwDeviceExtension, pVBInfo) ;
605
606 XGI_SetCRT1Group(HwDeviceExtension , ModeNo , ModeIdIndex, pVBInfo ) ;
607
608 XGI_DisplayOn( HwDeviceExtension, pVBInfo ) ;
609 /*
610 if( HwDeviceExtension->jChipType == XG21 )
611 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x09 , ~0x80 , 0x80 ) ;
612 */
613 }
614
615
616/*
617 if ( ModeNo <= 0x13 )
618 {
619 modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
620 }
621 else
622 {
623 modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
624 }
625 pVBInfo->ModeType = modeflag&ModeInfoFlag ;
626 pVBInfo->SetFlag = 0x00 ;
627 pVBInfo->VBInfo = DisableCRT2Display ;
628 temp = XGINew_CheckMemorySize( HwDeviceExtension , ModeNo , ModeIdIndex, pVBInfo ) ;
629
630 if ( temp == 0 )
631 return( 0 ) ;
632
633 XGI_DisplayOff( HwDeviceExtension, pVBInfo) ;
634 XGI_SetCRT1Group( HwDeviceExtension , ModeNo , ModeIdIndex, pVBInfo ) ;
635 XGI_DisplayOn( HwDeviceExtension, pVBInfo) ;
636*/
637
638 XGI_UpdateModeInfo( HwDeviceExtension, pVBInfo ) ;
639
640 if ( HwDeviceExtension->jChipType < XG20 ) /* kuku 2004/06/25 */
641{
642 XGI_LockCRT2( HwDeviceExtension, pVBInfo ) ;
643}
644
645 return( TRUE ) ;
646}
647
648
649/* --------------------------------------------------------------------- */
650/* Function : XGI_SetCRT1Group */
651/* Input : */
652/* Output : */
653/* Description : */
654/* --------------------------------------------------------------------- */
655void XGI_SetCRT1Group( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
656{
657 USHORT StandTableIndex ,
658 RefreshRateTableIndex ,
659 b3CC ,
660 temp ;
661
662 USHORT XGINew_P3cc = pVBInfo->P3cc;
663
664 /* XGINew_CRT1Mode = ModeNo ; // SaveModeID */
665 StandTableIndex = XGI_GetModePtr( ModeNo , ModeIdIndex, pVBInfo ) ;
666 /* XGI_SetBIOSData(ModeNo , ModeIdIndex ) ; */
667 /* XGI_ClearBankRegs( ModeNo , ModeIdIndex ) ; */
668 XGI_SetSeqRegs( ModeNo , StandTableIndex , ModeIdIndex, pVBInfo ) ;
669 XGI_SetMiscRegs( StandTableIndex, pVBInfo ) ;
670 XGI_SetCRTCRegs( HwDeviceExtension , StandTableIndex, pVBInfo) ;
671 XGI_SetATTRegs( ModeNo , StandTableIndex , ModeIdIndex, pVBInfo ) ;
672 XGI_SetGRCRegs( StandTableIndex, pVBInfo ) ;
673 XGI_ClearExt1Regs(pVBInfo) ;
674
675/* if ( pVBInfo->IF_DEF_ExpLink ) */
676 if ( HwDeviceExtension->jChipType == XG27 )
677 {
678 if ( pVBInfo->IF_DEF_LVDS == 0 )
679 {
680 XGI_SetDefaultVCLK( pVBInfo ) ;
681 }
682 }
683
684 temp = ~ProgrammingCRT2 ;
685 pVBInfo->SetFlag &= temp ;
686 pVBInfo->SelectCRT2Rate = 0 ;
687
688 if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
689 {
690 if ( pVBInfo->VBInfo & ( SetSimuScanMode | SetCRT2ToLCDA | SetInSlaveMode ) )
691 {
692 pVBInfo->SetFlag |= ProgrammingCRT2 ;
693 }
694 }
695
696 RefreshRateTableIndex = XGI_GetRatePtrCRT2( HwDeviceExtension, ModeNo , ModeIdIndex, pVBInfo ) ;
697 if ( RefreshRateTableIndex != 0xFFFF )
698 {
699 XGI_SetSync( RefreshRateTableIndex, pVBInfo ) ;
700 XGI_SetCRT1CRTC( ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo, HwDeviceExtension ) ;
701 XGI_SetCRT1DE( HwDeviceExtension , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
702 XGI_SetCRT1Offset( ModeNo , ModeIdIndex , RefreshRateTableIndex , HwDeviceExtension, pVBInfo ) ;
703 XGI_SetCRT1VCLK( ModeNo , ModeIdIndex , HwDeviceExtension , RefreshRateTableIndex, pVBInfo ) ;
704 }
705
706 if ( ( HwDeviceExtension->jChipType >= XG20 )&&
707 ( HwDeviceExtension->jChipType < XG27 ) ) /* fix H/W DCLK/2 bug */
708 {
709 if ( ( ModeNo == 0x00 ) | (ModeNo == 0x01) )
710 {
711 XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , 0x4E) ;
712 XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , 0xE9) ;
713 b3CC =(UCHAR) XGINew_GetReg2(XGINew_P3cc) ;
714 XGINew_SetReg3(XGINew_P3cc , (b3CC |= 0x0C) ) ;
715 }
716 else if ( ( ModeNo == 0x04) | ( ModeNo == 0x05) | ( ModeNo == 0x0D) )
717 {
718 XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , 0x1B) ;
719 XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , 0xE3) ;
720 b3CC = (UCHAR)XGINew_GetReg2(XGINew_P3cc) ;
721 XGINew_SetReg3(XGINew_P3cc , (b3CC |= 0x0C) ) ;
722 }
723 }
724
725 if ( HwDeviceExtension->jChipType >= XG21 )
726 {
727 temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) ;
728 if ( temp & 0xA0 )
729 {
730
731 /*XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~0x20 ) ;*/ /* Enable write GPIOF */
732 /*XGINew_SetRegAND( pVBInfo->P3d4 , 0x48 , ~0x20 ) ;*/ /* P. DWN */
733 /* XG21 CRT1 Timing */
734 if ( HwDeviceExtension->jChipType == XG27 )
735 XGI_SetXG27CRTC( ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo );
736 else
737 XGI_SetXG21CRTC( ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo );
738
739 XGI_UpdateXG21CRTC( ModeNo , pVBInfo , RefreshRateTableIndex) ;
740
741 if ( HwDeviceExtension->jChipType == XG27 )
742 XGI_SetXG27LCD( pVBInfo , RefreshRateTableIndex , ModeNo );
743 else
744 XGI_SetXG21LCD( pVBInfo , RefreshRateTableIndex , ModeNo );
745
746 if ( pVBInfo->IF_DEF_LVDS == 1 )
747 {
748 if ( HwDeviceExtension->jChipType == XG27 )
749 XGI_SetXG27LVDSPara(ModeNo,ModeIdIndex, pVBInfo );
750 else
751 XGI_SetXG21LVDSPara(ModeNo,ModeIdIndex, pVBInfo );
752 }
753 /*XGINew_SetRegOR( pVBInfo->P3d4 , 0x48 , 0x20 ) ;*/ /* P. ON */
754 }
755 }
756
757 pVBInfo->SetFlag &= ( ~ProgrammingCRT2 ) ;
758 XGI_SetCRT1FIFO( ModeNo , HwDeviceExtension, pVBInfo ) ;
759 XGI_SetCRT1ModeRegs( HwDeviceExtension , ModeNo , ModeIdIndex , RefreshRateTableIndex , pVBInfo) ;
760
761
762 /* XGI_LoadCharacter(); //dif ifdef TVFont */
763
764 XGI_LoadDAC( ModeNo , ModeIdIndex, pVBInfo ) ;
765 /* XGI_ClearBuffer( HwDeviceExtension , ModeNo, pVBInfo ) ; */
766#ifdef WIN2000
767 if ( pVBInfo->IF_DEF_CH7007 == 1 ) /* [Billy] 2007/05/14 */
768 {
769 VideoDebugPrint((0, "XGI_SetCRT1Group: VBInfo->IF_DEF_CH7007==1\n"));
770 SetCH7007Regs(HwDeviceExtension, ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo ) ; /* 07/05/28 */
771 }
772#endif
773}
774
775
776/* --------------------------------------------------------------------- */
777/* Function : XGI_GetModePtr */
778/* Input : */
779/* Output : */
780/* Description : */
781/* --------------------------------------------------------------------- */
782UCHAR XGI_GetModePtr( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
783{
784 UCHAR index ;
785
786 if ( ModeNo <= 0x13 )
787 index = pVBInfo->SModeIDTable[ ModeIdIndex ].St_StTableIndex ;
788 else
789 {
790 if ( pVBInfo->ModeType <= 0x02 )
791 index = 0x1B ; /* 02 -> ModeEGA */
792 else
793 index = 0x0F ;
794 }
795 return( index ) ; /* Get pVBInfo->StandTable index */
796}
797
798
799/* --------------------------------------------------------------------- */
800/* Function : XGI_SetBIOSData */
801/* Input : */
802/* Output : */
803/* Description : */
804/* --------------------------------------------------------------------- */
805/*UCHAR XGI_SetBIOSData( USHORT ModeNo , USHORT ModeIdIndex )
806{
807 return( 0 ) ;
808}
809*/
810
811/* --------------------------------------------------------------------- */
812/* Function : XGI_ClearBankRegs */
813/* Input : */
814/* Output : */
815/* Description : */
816/* --------------------------------------------------------------------- */
817/*UCHAR XGI_ClearBankRegs( USHORT ModeNo , USHORT ModeIdIndex )
818{
819 return( 0 ) ;
820}
821*/
822
823/* --------------------------------------------------------------------- */
824/* Function : XGI_SetSeqRegs */
825/* Input : */
826/* Output : */
827/* Description : */
828/* --------------------------------------------------------------------- */
829void XGI_SetSeqRegs( USHORT ModeNo , USHORT StandTableIndex , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
830{
831 UCHAR tempah ,
832 SRdata ;
833
834 USHORT i ,
835 modeflag ;
836
837 if ( ModeNo <= 0x13 )
838 modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
839 else
840 modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
841
842 XGINew_SetReg1( pVBInfo->P3c4 , 0x00 , 0x03 ) ; /* Set SR0 */
843 tempah=pVBInfo->StandTable[ StandTableIndex ].SR[ 0 ] ;
844
845 i = SetCRT2ToLCDA ;
846 if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
847 {
848 tempah |= 0x01 ;
849 }
850 else
851 {
852 if ( pVBInfo->VBInfo & ( SetCRT2ToTV | SetCRT2ToLCD ) )
853 {
854 if ( pVBInfo->VBInfo & SetInSlaveMode )
855 tempah |= 0x01 ;
856 }
857 }
858
859 tempah |= 0x20 ; /* screen off */
860 XGINew_SetReg1( pVBInfo->P3c4 , 0x01 , tempah ) ; /* Set SR1 */
861
862 for( i = 02 ; i <= 04 ; i++ )
863 {
864 SRdata = pVBInfo->StandTable[ StandTableIndex ].SR[ i - 1 ] ; /* Get SR2,3,4 from file */
865 XGINew_SetReg1( pVBInfo->P3c4 , i , SRdata ) ; /* Set SR2 3 4 */
866 }
867}
868
869
870/* --------------------------------------------------------------------- */
871/* Function : XGI_SetMiscRegs */
872/* Input : */
873/* Output : */
874/* Description : */
875/* --------------------------------------------------------------------- */
876void XGI_SetMiscRegs( USHORT StandTableIndex, PVB_DEVICE_INFO pVBInfo )
877{
878 UCHAR Miscdata ;
879
880 Miscdata = pVBInfo->StandTable[ StandTableIndex ].MISC ; /* Get Misc from file */
881/*
882 if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
883 {
884 if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
885 {
886 Miscdata |= 0x0C ;
887 }
888 }
889*/
890
891 XGINew_SetReg3( pVBInfo->P3c2 , Miscdata ) ; /* Set Misc(3c2) */
892}
893
894
895/* --------------------------------------------------------------------- */
896/* Function : XGI_SetCRTCRegs */
897/* Input : */
898/* Output : */
899/* Description : */
900/* --------------------------------------------------------------------- */
901void XGI_SetCRTCRegs( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT StandTableIndex, PVB_DEVICE_INFO pVBInfo )
902{
903 UCHAR CRTCdata ;
904 USHORT i ;
905
906 CRTCdata = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ;
907 CRTCdata &= 0x7f ;
908 XGINew_SetReg1( pVBInfo->P3d4 , 0x11 , CRTCdata ) ; /* Unlock CRTC */
909
910 for( i = 0 ; i <= 0x18 ; i++ )
911 {
912 CRTCdata = pVBInfo->StandTable[ StandTableIndex ].CRTC[ i ] ; /* Get CRTC from file */
913 XGINew_SetReg1( pVBInfo->P3d4 , i , CRTCdata ) ; /* Set CRTC( 3d4 ) */
914 }
915/*
916 if ( ( HwDeviceExtension->jChipType == XGI_630 )&& ( HwDeviceExtension->jChipRevision == 0x30 ) )
917 {
918 if ( pVBInfo->VBInfo & SetInSlaveMode )
919 {
920 if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToTV ) )
921 {
922 XGINew_SetReg1( pVBInfo->P3d4 , 0x18 , 0xFE ) ;
923 }
924 }
925 }
926*/
927}
928
929
930/* --------------------------------------------------------------------- */
931/* Function : */
932/* Input : */
933/* Output : */
934/* Description : */
935/* --------------------------------------------------------------------- */
936void XGI_SetATTRegs( USHORT ModeNo , USHORT StandTableIndex , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
937{
938 UCHAR ARdata ;
939 USHORT i ,
940 modeflag ;
941
942 if ( ModeNo <= 0x13 )
943 modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
944 else
945 modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
946
947 for( i = 0 ; i <= 0x13 ; i++ )
948 {
949 ARdata = pVBInfo->StandTable[ StandTableIndex ].ATTR[ i ] ;
950 if ( modeflag & Charx8Dot ) /* ifndef Dot9 */
951 {
952 if ( i == 0x13 )
953 {
954 if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
955 ARdata = 0 ;
956 else
957 {
958 if ( pVBInfo->VBInfo & ( SetCRT2ToTV | SetCRT2ToLCD ) )
959 {
960 if ( pVBInfo->VBInfo & SetInSlaveMode )
961 ARdata = 0 ;
962 }
963 }
964 }
965 }
966
967 XGINew_GetReg2( pVBInfo->P3da ) ; /* reset 3da */
968 XGINew_SetReg3( pVBInfo->P3c0 , i ) ; /* set index */
969 XGINew_SetReg3( pVBInfo->P3c0 , ARdata ) ; /* set data */
970 }
971
972 XGINew_GetReg2( pVBInfo->P3da ) ; /* reset 3da */
973 XGINew_SetReg3( pVBInfo->P3c0 , 0x14 ) ; /* set index */
974 XGINew_SetReg3( pVBInfo->P3c0 , 0x00 ) ; /* set data */
975 XGINew_GetReg2( pVBInfo->P3da ) ; /* Enable Attribute */
976 XGINew_SetReg3( pVBInfo->P3c0 , 0x20 ) ;
977}
978
979
980/* --------------------------------------------------------------------- */
981/* Function : XGI_SetGRCRegs */
982/* Input : */
983/* Output : */
984/* Description : */
985/* --------------------------------------------------------------------- */
986void XGI_SetGRCRegs( USHORT StandTableIndex, PVB_DEVICE_INFO pVBInfo )
987{
988 UCHAR GRdata ;
989 USHORT i ;
990
991 for( i = 0 ; i <= 0x08 ; i++ )
992 {
993 GRdata = pVBInfo->StandTable[ StandTableIndex ].GRC[ i ] ; /* Get GR from file */
994 XGINew_SetReg1( pVBInfo->P3ce , i , GRdata ) ; /* Set GR(3ce) */
995 }
996
997 if ( pVBInfo->ModeType > ModeVGA )
998 {
999 GRdata = ( UCHAR )XGINew_GetReg1( pVBInfo->P3ce , 0x05 ) ;
1000 GRdata &= 0xBF ; /* 256 color disable */
1001 XGINew_SetReg1( pVBInfo->P3ce , 0x05 , GRdata ) ;
1002 }
1003}
1004
1005
1006/* --------------------------------------------------------------------- */
1007/* Function : XGI_ClearExt1Regs */
1008/* Input : */
1009/* Output : */
1010/* Description : */
1011/* --------------------------------------------------------------------- */
1012void XGI_ClearExt1Regs(PVB_DEVICE_INFO pVBInfo)
1013{
1014 USHORT i ;
1015
1016 for( i = 0x0A ; i <= 0x0E ; i++ )
1017 XGINew_SetReg1( pVBInfo->P3c4 , i , 0x00 ) ; /* Clear SR0A-SR0E */
1018}
1019
1020
1021/* --------------------------------------------------------------------- */
1022/* Function : XGI_SetDefaultVCLK */
1023/* Input : */
1024/* Output : */
1025/* Description : */
1026/* --------------------------------------------------------------------- */
1027UCHAR XGI_SetDefaultVCLK( PVB_DEVICE_INFO pVBInfo )
1028{
1029
1030 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x31 , ~0x30 , 0x20 ) ;
1031 XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , pVBInfo->VCLKData[ 0 ].SR2B ) ;
1032 XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , pVBInfo->VCLKData[ 0 ].SR2C ) ;
1033
1034 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x31 , ~0x30 , 0x10 ) ;
1035 XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , pVBInfo->VCLKData[ 1 ].SR2B ) ;
1036 XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , pVBInfo->VCLKData[ 1 ].SR2C ) ;
1037
1038 XGINew_SetRegAND( pVBInfo->P3c4 , 0x31 , ~0x30 ) ;
1039 return( 0 ) ;
1040}
1041
1042
1043/* --------------------------------------------------------------------- */
1044/* Function : XGI_GetRatePtrCRT2 */
1045/* Input : */
1046/* Output : */
1047/* Description : */
1048/* --------------------------------------------------------------------- */
1049USHORT XGI_GetRatePtrCRT2( PXGI_HW_DEVICE_INFO pXGIHWDE, USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
1050{
1051 SHORT LCDRefreshIndex[] = { 0x00 , 0x00 , 0x03 , 0x01 } ,
1052 LCDARefreshIndex[] = { 0x00 , 0x00 , 0x03 , 0x01 , 0x01 , 0x01 , 0x01 } ;
1053
1054 USHORT RefreshRateTableIndex , i ,
1055 modeflag , index , temp ;
1056
1057 if ( ModeNo <= 0x13 )
1058 {
1059 modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
1060 }
1061 else
1062 {
1063 modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
1064 }
1065
1066 if ( pVBInfo->IF_DEF_CH7005 == 1 )
1067 {
1068 if ( pVBInfo->VBInfo & SetCRT2ToTV )
1069 {
1070 if ( modeflag & HalfDCLK )
1071 return( 0 ) ;
1072 }
1073 }
1074
1075 if ( ModeNo < 0x14 )
1076 return( 0xFFFF ) ;
1077
1078 index = XGINew_GetReg1( pVBInfo->P3d4 , 0x33 ) ;
1079 index = index >> pVBInfo->SelectCRT2Rate ;
1080 index &= 0x0F ;
1081
1082 if ( pVBInfo->LCDInfo & LCDNonExpanding )
1083 index = 0 ;
1084
1085 if ( index > 0 )
1086 index-- ;
1087
1088 if ( pVBInfo->SetFlag & ProgrammingCRT2 )
1089 {
1090 if ( pVBInfo->IF_DEF_CH7005 == 1 )
1091 {
1092 if ( pVBInfo->VBInfo & SetCRT2ToTV )
1093 {
1094 index = 0 ;
1095 }
1096 }
1097
1098 if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
1099 {
1100 if( pVBInfo->IF_DEF_LVDS == 0 )
1101 {
1102 if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
1103 temp = LCDARefreshIndex[ pVBInfo->LCDResInfo & 0x0F ] ; /* 301b */
1104 else
1105 temp = LCDRefreshIndex[ pVBInfo->LCDResInfo & 0x0F ] ;
1106
1107 if ( index > temp )
1108 {
1109 index = temp ;
1110 }
1111 }
1112 else
1113 {
1114 index = 0 ;
1115 }
1116 }
1117 }
1118
1119 RefreshRateTableIndex = pVBInfo->EModeIDTable[ ModeIdIndex ].REFindex ;
1120 ModeNo = pVBInfo->RefIndex[ RefreshRateTableIndex ].ModeID ;
1121 if ( pXGIHWDE->jChipType >= XG20 ) /* for XG20, XG21, XG27 */
1122 {
1123 /*
1124 if ( pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag & XG2xNotSupport )
1125 {
1126 index++;
1127 }
1128 */
1129 if ( ( pVBInfo->RefIndex[ RefreshRateTableIndex ].XRes == 800 ) &&
1130 ( pVBInfo->RefIndex[ RefreshRateTableIndex ].YRes == 600 ) )
1131 {
1132 index++;
1133 }
1134/* Alan 10/19/2007; do the similiar adjustment like XGISearchCRT1Rate() */
1135 if ( ( pVBInfo->RefIndex[ RefreshRateTableIndex ].XRes == 1024 ) &&
1136 ( pVBInfo->RefIndex[ RefreshRateTableIndex ].YRes == 768 ) )
1137 {
1138 index++;
1139 }
1140 if ( ( pVBInfo->RefIndex[ RefreshRateTableIndex ].XRes == 1280 ) &&
1141 ( pVBInfo->RefIndex[ RefreshRateTableIndex ].YRes == 1024 ) )
1142 {
1143 index++;
1144 }
1145 }
1146
1147 i = 0 ;
1148 do
1149 {
1150 if ( pVBInfo->RefIndex[ RefreshRateTableIndex + i ].ModeID != ModeNo )
1151 break ;
1152 temp = pVBInfo->RefIndex[ RefreshRateTableIndex + i ].Ext_InfoFlag ;
1153 temp &= ModeInfoFlag ;
1154 if ( temp < pVBInfo->ModeType )
1155 break ;
1156 i++ ;
1157 index-- ;
1158
1159 } while( index != 0xFFFF ) ;
1160 if ( !( pVBInfo->VBInfo & SetCRT2ToRAMDAC ) )
1161 {
1162 if ( pVBInfo->VBInfo & SetInSlaveMode )
1163 {
1164 temp = pVBInfo->RefIndex[ RefreshRateTableIndex + i - 1 ].Ext_InfoFlag ;
1165 if ( temp & InterlaceMode )
1166 {
1167 i++ ;
1168 }
1169 }
1170 }
1171 i-- ;
1172 if ( ( pVBInfo->SetFlag & ProgrammingCRT2 ) )
1173 {
1174 temp = XGI_AjustCRT2Rate( ModeNo , ModeIdIndex , RefreshRateTableIndex , &i, pVBInfo) ;
1175 }
1176 return( RefreshRateTableIndex + i ) ; /*return(0x01|(temp1<<1)); */
1177}
1178
1179
1180/* --------------------------------------------------------------------- */
1181/* Function : XGI_AjustCRT2Rate */
1182/* Input : */
1183/* Output : */
1184/* Description : */
1185/* --------------------------------------------------------------------- */
1186BOOLEAN XGI_AjustCRT2Rate( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex , USHORT *i, PVB_DEVICE_INFO pVBInfo )
1187{
1188 USHORT tempax ,
1189 tempbx ,
1190 resinfo ,
1191 modeflag ,
1192 infoflag ;
1193
1194 if ( ModeNo <= 0x13 )
1195 {
1196 modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; /* si+St_ModeFlag */
1197 }
1198 else
1199 {
1200 modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
1201 }
1202
1203 resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ;
1204 tempbx = pVBInfo->RefIndex[ RefreshRateTableIndex + ( *i ) ].ModeID ;
1205 tempax = 0 ;
1206
1207 if ( pVBInfo->IF_DEF_LVDS == 0 )
1208 {
1209 if ( pVBInfo->VBInfo & SetCRT2ToRAMDAC )
1210 {
1211 tempax |= SupportRAMDAC2 ;
1212
1213 if ( pVBInfo->VBType & VB_XGI301C )
1214 tempax |= SupportCRT2in301C ;
1215 }
1216
1217 if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) /* 301b */
1218 {
1219 tempax |= SupportLCD ;
1220
1221 if ( pVBInfo->LCDResInfo != Panel1280x1024 )
1222 {
1223 if ( pVBInfo->LCDResInfo != Panel1280x960 )
1224 {
1225 if ( pVBInfo->LCDInfo & LCDNonExpanding )
1226 {
1227 if ( resinfo >= 9 )
1228 {
1229 tempax = 0 ;
1230 return( 0 ) ;
1231 }
1232 }
1233 }
1234 }
1235 }
1236
1237 if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) /* for HiTV */
1238 {
1239 if ( ( pVBInfo->VBType & VB_XGI301LV ) && ( pVBInfo->VBExtInfo == VB_YPbPr1080i ) )
1240 {
1241 tempax |= SupportYPbPr ;
1242 if ( pVBInfo->VBInfo & SetInSlaveMode )
1243 {
1244 if ( resinfo == 4 )
1245 return( 0 ) ;
1246
1247 if ( resinfo == 3 )
1248 return( 0 ) ;
1249
1250 if ( resinfo > 7 )
1251 return( 0 ) ;
1252 }
1253 }
1254 else
1255 {
1256 tempax |= SupportHiVisionTV ;
1257 if ( pVBInfo->VBInfo & SetInSlaveMode )
1258 {
1259 if ( resinfo == 4 )
1260 return( 0 ) ;
1261
1262 if ( resinfo == 3 )
1263 {
1264 if ( pVBInfo->SetFlag & TVSimuMode )
1265 return( 0 ) ;
1266 }
1267
1268 if ( resinfo > 7 )
1269 return( 0 ) ;
1270 }
1271 }
1272 }
1273 else
1274 {
1275 if ( pVBInfo->VBInfo & ( SetCRT2ToAVIDEO | SetCRT2ToSVIDEO | SetCRT2ToSCART | SetCRT2ToYPbPr | SetCRT2ToHiVisionTV ) )
1276 {
1277 tempax |= SupportTV ;
1278
1279 if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
1280 {
1281 tempax |= SupportTV1024 ;
1282 }
1283
1284 if ( !( pVBInfo->VBInfo & SetPALTV ) )
1285 {
1286 if ( modeflag & NoSupportSimuTV )
1287 {
1288 if ( pVBInfo->VBInfo & SetInSlaveMode )
1289 {
1290 if ( !( pVBInfo->VBInfo & SetNotSimuMode ) )
1291 {
1292 return( 0 ) ;
1293 }
1294 }
1295 }
1296 }
1297 }
1298 }
1299 }
1300 else /* for LVDS */
1301 {
1302 if ( pVBInfo->IF_DEF_CH7005 == 1 )
1303 {
1304 if ( pVBInfo->VBInfo & SetCRT2ToTV )
1305 {
1306 tempax |= SupportCHTV ;
1307 }
1308 }
1309
1310 if ( pVBInfo->VBInfo & SetCRT2ToLCD )
1311 {
1312 tempax |= SupportLCD ;
1313
1314 if ( resinfo > 0x08 )
1315 return( 0 ) ; /* 1024x768 */
1316
1317 if ( pVBInfo->LCDResInfo < Panel1024x768 )
1318 {
1319 if ( resinfo > 0x07 )
1320 return( 0 ) ; /* 800x600 */
1321
1322 if ( resinfo == 0x04 )
1323 return( 0 ) ; /* 512x384 */
1324 }
1325 }
1326 }
1327
1328 for( ; pVBInfo->RefIndex[ RefreshRateTableIndex + ( *i ) ].ModeID == tempbx ; ( *i )-- )
1329 {
1330 infoflag = pVBInfo->RefIndex[ RefreshRateTableIndex + ( *i ) ].Ext_InfoFlag ;
1331 if ( infoflag & tempax )
1332 {
1333 return( 1 ) ;
1334 }
1335 if ( ( *i ) == 0 )
1336 break ;
1337 }
1338
1339 for( ( *i ) = 0 ; ; ( *i )++ )
1340 {
1341 infoflag = pVBInfo->RefIndex[ RefreshRateTableIndex + ( *i ) ].Ext_InfoFlag ;
1342 if ( pVBInfo->RefIndex[ RefreshRateTableIndex + ( *i ) ].ModeID != tempbx )
1343 {
1344 return( 0 ) ;
1345 }
1346
1347 if ( infoflag & tempax )
1348 {
1349 return( 1 ) ;
1350 }
1351 }
1352 return( 1 ) ;
1353}
1354
1355
1356/* --------------------------------------------------------------------- */
1357/* Function : XGI_SetSync */
1358/* Input : */
1359/* Output : */
1360/* Description : */
1361/* --------------------------------------------------------------------- */
1362void XGI_SetSync(USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
1363{
1364 USHORT sync ,
1365 temp ;
1366
1367 sync = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag >> 8 ; /* di+0x00 */
1368 sync &= 0xC0 ;
1369 temp = 0x2F ;
1370 temp |= sync ;
1371 XGINew_SetReg3( pVBInfo->P3c2 , temp ) ; /* Set Misc(3c2) */
1372}
1373
1374
1375/* --------------------------------------------------------------------- */
1376/* Function : XGI_SetCRT1CRTC */
1377/* Input : */
1378/* Output : */
1379/* Description : */
1380/* --------------------------------------------------------------------- */
1381void XGI_SetCRT1CRTC( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo, PXGI_HW_DEVICE_INFO HwDeviceExtension )
1382{
1383 UCHAR index ,
1384 data ;
1385
1386 USHORT i ;
1387
1388 index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC ; /* Get index */
1389 index = index&IndexMask ;
1390
1391 data =( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ;
1392 data &= 0x7F ;
1393 XGINew_SetReg1(pVBInfo->P3d4,0x11,data); /* Unlock CRTC */
1394
1395 for( i = 0 ; i < 8 ; i++ )
1396 pVBInfo->TimingH[ 0 ].data[ i ] = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ i ] ;
1397
1398 for( i = 0 ; i < 7 ; i++ )
1399 pVBInfo->TimingV[ 0 ].data[ i ] = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ i + 8 ] ;
1400
1401 XGI_SetCRT1Timing_H( pVBInfo, HwDeviceExtension ) ;
1402
1403
1404
1405 XGI_SetCRT1Timing_V( ModeIdIndex , ModeNo, pVBInfo ) ;
1406
1407
1408 if( pVBInfo->ModeType > 0x03 )
1409 XGINew_SetReg1( pVBInfo->P3d4 , 0x14 , 0x4F ) ;
1410}
1411
1412
1413/* --------------------------------------------------------------------- */
1414/* Function : XGI_SetCRT1Timing_H */
1415/* Input : */
1416/* Output : */
1417/* Description : */
1418/* --------------------------------------------------------------------- */
1419void XGI_SetCRT1Timing_H( PVB_DEVICE_INFO pVBInfo, PXGI_HW_DEVICE_INFO HwDeviceExtension )
1420{
1421 UCHAR data , data1, pushax;
1422 USHORT i , j ;
1423
1424 /* XGINew_SetReg1( pVBInfo->P3d4 , 0x51 , 0 ) ; */
1425 /* XGINew_SetReg1( pVBInfo->P3d4 , 0x56 , 0 ) ; */
1426 /* XGINew_SetRegANDOR( pVBInfo->P3d4 ,0x11 , 0x7f , 0x00 ) ; */
1427
1428 data = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ; /* unlock cr0-7 */
1429 data &= 0x7F ;
1430 XGINew_SetReg1( pVBInfo->P3d4 , 0x11 , data ) ;
1431
1432 data = pVBInfo->TimingH[ 0 ].data[ 0 ] ;
1433 XGINew_SetReg1( pVBInfo->P3d4 , 0 , data ) ;
1434
1435 for( i = 0x01 ; i <= 0x04 ; i++ )
1436 {
1437 data = pVBInfo->TimingH[ 0 ].data[ i ] ;
1438 XGINew_SetReg1( pVBInfo->P3d4 , ( USHORT )( i + 1 ) , data ) ;
1439 }
1440
1441 for( i = 0x05 ; i <= 0x06 ; i++ )
1442 {
1443 data = pVBInfo->TimingH[ 0 ].data[ i ];
1444 XGINew_SetReg1( pVBInfo->P3c4 ,( USHORT )( i + 6 ) , data ) ;
1445 }
1446
1447 j = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x0e ) ;
1448 j &= 0x1F ;
1449 data = pVBInfo->TimingH[ 0 ].data[ 7 ] ;
1450 data &= 0xE0 ;
1451 data |= j ;
1452 XGINew_SetReg1( pVBInfo->P3c4 , 0x0e , data ) ;
1453
1454 if ( HwDeviceExtension->jChipType >= XG20 )
1455 {
1456 data = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x04 ) ;
1457 data = data - 1 ;
1458 XGINew_SetReg1( pVBInfo->P3d4 , 0x04 , data ) ;
1459 data = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x05 ) ;
1460 data1 = data ;
1461 data1 &= 0xE0 ;
1462 data &= 0x1F ;
1463 if ( data == 0 )
1464 {
1465 pushax = data ;
1466 data = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x0c ) ;
1467 data &= 0xFB ;
1468 XGINew_SetReg1( pVBInfo->P3c4 , 0x0c , data ) ;
1469 data = pushax ;
1470 }
1471 data = data - 1 ;
1472 data |= data1 ;
1473 XGINew_SetReg1( pVBInfo->P3d4 , 0x05 , data ) ;
1474 data = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x0e ) ;
1475 data = data >> 5 ;
1476 data = data + 3 ;
1477 if ( data > 7 )
1478 data = data - 7 ;
1479 data = data << 5 ;
1480 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0e , ~0xE0 , data ) ;
1481 }
1482}
1483
1484
1485/* --------------------------------------------------------------------- */
1486/* Function : XGI_SetCRT1Timing_V */
1487/* Input : */
1488/* Output : */
1489/* Description : */
1490/* --------------------------------------------------------------------- */
1491void XGI_SetCRT1Timing_V( USHORT ModeIdIndex , USHORT ModeNo,PVB_DEVICE_INFO pVBInfo )
1492{
1493 UCHAR data ;
1494 USHORT i , j ;
1495
1496 /* XGINew_SetReg1( pVBInfo->P3d4 , 0x51 , 0 ) ; */
1497 /* XGINew_SetReg1( pVBInfo->P3d4 , 0x56 , 0 ) ; */
1498 /* XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x11 , 0x7f , 0x00 ) ; */
1499
1500 for( i = 0x00 ; i <= 0x01 ; i++ )
1501 {
1502 data = pVBInfo->TimingV[ 0 ].data[ i ] ;
1503 XGINew_SetReg1( pVBInfo->P3d4 , ( USHORT )( i + 6 ) , data ) ;
1504 }
1505
1506 for( i = 0x02 ; i <= 0x03 ; i++ )
1507 {
1508 data = pVBInfo->TimingV[ 0 ].data[ i ] ;
1509 XGINew_SetReg1( pVBInfo->P3d4 , ( USHORT )( i + 0x0e ) , data ) ;
1510 }
1511
1512 for( i = 0x04 ; i <= 0x05 ; i++ )
1513 {
1514 data = pVBInfo->TimingV[ 0 ].data[ i ] ;
1515 XGINew_SetReg1( pVBInfo->P3d4 , ( USHORT )( i + 0x11 ) , data ) ;
1516 }
1517
1518 j = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x0a ) ;
1519 j &= 0xC0 ;
1520 data = pVBInfo->TimingV[ 0 ].data[ 6 ] ;
1521 data &= 0x3F ;
1522 data |= j ;
1523 XGINew_SetReg1( pVBInfo->P3c4 , 0x0a , data ) ;
1524
1525 data = pVBInfo->TimingV[ 0 ].data[ 6 ] ;
1526 data &= 0x80 ;
1527 data = data >> 2 ;
1528
1529 if ( ModeNo <= 0x13 )
1530 i = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
1531 else
1532 i = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
1533
1534 i &= DoubleScanMode ;
1535 if ( i )
1536 data |= 0x80 ;
1537
1538 j = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x09 ) ;
1539 j &= 0x5F ;
1540 data |= j ;
1541 XGINew_SetReg1( pVBInfo->P3d4 , 0x09 , data ) ;
1542}
1543
1544
1545/* --------------------------------------------------------------------- */
1546/* Function : XGI_SetXG21CRTC */
1547/* Input : Stand or enhance CRTC table */
1548/* Output : Fill CRT Hsync/Vsync to SR2E/SR2F/SR30/SR33/SR34/SR3F */
1549/* Description : Set LCD timing */
1550/* --------------------------------------------------------------------- */
1551void XGI_SetXG21CRTC(USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo)
1552{
1553 UCHAR StandTableIndex, index, Tempax, Tempbx, Tempcx, Tempdx ;
1554 USHORT Temp1, Temp2, Temp3 ;
1555
1556 if ( ModeNo <= 0x13 )
1557 {
1558 StandTableIndex = XGI_GetModePtr( ModeNo , ModeIdIndex, pVBInfo ) ;
1559 Tempax = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 4 ] ; /* CR04 HRS */
1560 XGINew_SetReg1( pVBInfo->P3c4 , 0x2E , Tempax ) ; /* SR2E [7:0]->HRS */
1561 Tempbx = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 5 ] ; /* Tempbx: CR05 HRE */
1562 Tempbx &= 0x1F ; /* Tempbx: HRE[4:0] */
1563 Tempcx = Tempax ;
1564 Tempcx &= 0xE0 ; /* Tempcx: HRS[7:5] */
1565 Tempdx = Tempcx | Tempbx ; /* Tempdx(HRE): HRS[7:5]HRE[4:0] */
1566 if ( Tempbx < ( Tempax & 0x1F ) ) /* IF HRE < HRS */
1567 Tempdx |= 0x20 ; /* Tempdx: HRE = HRE + 0x20 */
1568 Tempdx <<= 2 ; /* Tempdx << 2 */
1569 XGINew_SetReg1( pVBInfo->P3c4 , 0x2F , Tempdx ) ; /* SR2F [7:2]->HRE */
1570 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x30 , 0xE3 , 00 ) ;
1571
1572 Tempax = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 16 ] ; /* Tempax: CR16 VRS */
1573 Tempbx = Tempax ; /* Tempbx=Tempax */
1574 Tempax &= 0x01 ; /* Tempax: VRS[0] */
1575 XGINew_SetRegOR( pVBInfo->P3c4 , 0x33 , Tempax ) ; /* SR33[0]->VRS */
1576 Tempax = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 7 ] ; /* Tempax: CR7 VRS */
1577 Tempdx = Tempbx >> 1 ; /* Tempdx: VRS[7:1] */
1578 Tempcx = Tempax & 0x04 ; /* Tempcx: CR7[2] */
1579 Tempcx <<= 5 ; /* Tempcx[7]: VRS[8] */
1580 Tempdx |= Tempcx ; /* Tempdx: VRS[8:1] */
1581 XGINew_SetReg1( pVBInfo->P3c4 , 0x34 , Tempdx ) ; /* SR34[7:0]: VRS[8:1] */
1582
1583 Temp1 = Tempcx << 1 ; /* Temp1[8]: VRS[8] UCHAR -> USHORT */
1584 Temp1 |= Tempbx ; /* Temp1[8:0]: VRS[8:0] */
1585 Tempax &= 0x80 ; /* Tempax[7]: CR7[7] */
1586 Temp2 = Tempax << 2 ; /* Temp2[9]: VRS[9] */
1587 Temp1 |= Temp2 ; /* Temp1[9:0]: VRS[9:0] */
1588
1589 Tempax = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 17 ] ; /* CR16 VRE */
1590 Tempax &= 0x0F ; /* Tempax[3:0]: VRE[3:0] */
1591 Temp2 = Temp1 & 0x3F0 ; /* Temp2[9:4]: VRS[9:4] */
1592 Temp2 |= Tempax ; /* Temp2[9:0]: VRE[9:0] */
1593 Temp3 = Temp1 & 0x0F ; /* Temp3[3:0]: VRS[3:0] */
1594 if ( Tempax < Temp3 ) /* VRE[3:0]<VRS[3:0] */
1595 Temp2 |= 0x10 ; /* Temp2: VRE + 0x10 */
1596 Temp2 &= 0xFF ; /* Temp2[7:0]: VRE[7:0] */
1597 Tempax = (UCHAR)Temp2 ; /* Tempax[7:0]: VRE[7:0] */
1598 Tempax <<= 2 ; /* Tempax << 2: VRE[5:0] */
1599 Temp1 &= 0x600 ; /* Temp1[10:9]: VRS[10:9] */
1600 Temp1 >>= 9 ; /* [10:9]->[1:0] */
1601 Tempbx = (UCHAR)Temp1 ; /* Tempbx[1:0]: VRS[10:9] */
1602 Tempax |= Tempbx ; /* VRE[5:0]VRS[10:9] */
1603 Tempax &= 0x7F ;
1604 XGINew_SetReg1( pVBInfo->P3c4 , 0x3F , Tempax ) ; /* SR3F D[7:2]->VRE D[1:0]->VRS */
1605 }
1606 else
1607 {
1608 index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC ;
1609 Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 3 ] ; /* Tempax: CR4 HRS */
1610 Tempcx = Tempax ; /* Tempcx: HRS */
1611 XGINew_SetReg1( pVBInfo->P3c4 , 0x2E , Tempax ) ; /* SR2E[7:0]->HRS */
1612
1613 Tempdx = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 5 ] ; /* SRB */
1614 Tempdx &= 0xC0 ; /* Tempdx[7:6]: SRB[7:6] */
1615 Temp1 = Tempdx ; /* Temp1[7:6]: HRS[9:8] */
1616 Temp1 <<= 2 ; /* Temp1[9:8]: HRS[9:8] */
1617 Temp1 |= Tempax ; /* Temp1[9:0]: HRS[9:0] */
1618
1619 Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 4 ] ; /* CR5 HRE */
1620 Tempax &= 0x1F ; /* Tempax[4:0]: HRE[4:0] */
1621
1622 Tempbx = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 6 ] ; /* SRC */
1623 Tempbx &= 0x04 ; /* Tempbx[2]: HRE[5] */
1624 Tempbx <<= 3 ; /* Tempbx[5]: HRE[5] */
1625 Tempax |= Tempbx ; /* Tempax[5:0]: HRE[5:0] */
1626
1627 Temp2 = Temp1 & 0x3C0 ; /* Temp2[9:6]: HRS[9:6] */
1628 Temp2 |= Tempax ; /* Temp2[9:0]: HRE[9:0] */
1629
1630 Tempcx &= 0x3F ; /* Tempcx[5:0]: HRS[5:0] */
1631 if( Tempax < Tempcx ) /* HRE < HRS */
1632 Temp2 |= 0x40 ; /* Temp2 + 0x40 */
1633
1634 Temp2 &= 0xFF ;
1635 Tempax = (UCHAR)Temp2 ; /* Tempax: HRE[7:0] */
1636 Tempax <<= 2 ; /* Tempax[7:2]: HRE[5:0] */
1637 Tempdx >>= 6 ; /* Tempdx[7:6]->[1:0] HRS[9:8] */
1638 Tempax |= Tempdx ; /* HRE[5:0]HRS[9:8] */
1639 XGINew_SetReg1( pVBInfo->P3c4 , 0x2F , Tempax ) ; /* SR2F D[7:2]->HRE, D[1:0]->HRS */
1640 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x30 , 0xE3 , 00 ) ;
1641
1642 Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 10 ] ; /* CR10 VRS */
1643 Tempbx = Tempax ; /* Tempbx: VRS */
1644 Tempax &= 0x01 ; /* Tempax[0]: VRS[0] */
1645 XGINew_SetRegOR( pVBInfo->P3c4 , 0x33 , Tempax ) ; /* SR33[0]->VRS[0] */
1646 Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 9 ] ; /* CR7[2][7] VRE */
1647 Tempcx = Tempbx >> 1 ; /* Tempcx[6:0]: VRS[7:1] */
1648 Tempdx = Tempax & 0x04 ; /* Tempdx[2]: CR7[2] */
1649 Tempdx <<= 5 ; /* Tempdx[7]: VRS[8] */
1650 Tempcx |= Tempdx ; /* Tempcx[7:0]: VRS[8:1] */
1651 XGINew_SetReg1( pVBInfo->P3c4 , 0x34 , Tempcx ) ; /* SR34[8:1]->VRS */
1652
1653 Temp1 = Tempdx ; /* Temp1[7]: Tempdx[7] */
1654 Temp1 <<= 1 ; /* Temp1[8]: VRS[8] */
1655 Temp1 |= Tempbx ; /* Temp1[8:0]: VRS[8:0] */
1656 Tempax &= 0x80 ;
1657 Temp2 = Tempax << 2 ; /* Temp2[9]: VRS[9] */
1658 Temp1 |= Temp2 ; /* Temp1[9:0]: VRS[9:0] */
1659 Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 14 ] ; /* Tempax: SRA */
1660 Tempax &= 0x08 ; /* Tempax[3]: VRS[3] */
1661 Temp2 = Tempax ;
1662 Temp2 <<= 7 ; /* Temp2[10]: VRS[10] */
1663 Temp1 |= Temp2 ; /* Temp1[10:0]: VRS[10:0] */
1664
1665 Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 11 ] ; /* Tempax: CR11 VRE */
1666 Tempax &= 0x0F ; /* Tempax[3:0]: VRE[3:0] */
1667 Tempbx = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 14 ] ; /* Tempbx: SRA */
1668 Tempbx &= 0x20 ; /* Tempbx[5]: VRE[5] */
1669 Tempbx >>= 1 ; /* Tempbx[4]: VRE[4] */
1670 Tempax |= Tempbx ; /* Tempax[4:0]: VRE[4:0] */
1671 Temp2 = Temp1 & 0x7E0 ; /* Temp2[10:5]: VRS[10:5] */
1672 Temp2 |= Tempax ; /* Temp2[10:5]: VRE[10:5] */
1673
1674 Temp3 = Temp1 & 0x1F ; /* Temp3[4:0]: VRS[4:0] */
1675 if ( Tempax < Temp3 ) /* VRE < VRS */
1676 Temp2 |= 0x20 ; /* VRE + 0x20 */
1677
1678 Temp2 &= 0xFF ;
1679 Tempax = (UCHAR)Temp2 ; /* Tempax: VRE[7:0] */
1680 Tempax <<= 2 ; /* Tempax[7:0]; VRE[5:0]00 */
1681 Temp1 &= 0x600 ; /* Temp1[10:9]: VRS[10:9] */
1682 Temp1 >>= 9 ; /* Temp1[1:0]: VRS[10:9] */
1683 Tempbx = (UCHAR)Temp1 ;
1684 Tempax |= Tempbx ; /* Tempax[7:0]: VRE[5:0]VRS[10:9] */
1685 Tempax &= 0x7F ;
1686 XGINew_SetReg1( pVBInfo->P3c4 , 0x3F , Tempax ) ; /* SR3F D[7:2]->VRE D[1:0]->VRS */
1687 }
1688}
1689
1690void XGI_SetXG27CRTC(USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo)
1691{
1692 USHORT StandTableIndex, index, Tempax, Tempbx, Tempcx, Tempdx ;
1693
1694 if ( ModeNo <= 0x13 )
1695 {
1696 StandTableIndex = XGI_GetModePtr( ModeNo , ModeIdIndex, pVBInfo ) ;
1697 Tempax = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 4 ] ; /* CR04 HRS */
1698 XGINew_SetReg1( pVBInfo->P3c4 , 0x2E , Tempax ) ; /* SR2E [7:0]->HRS */
1699 Tempbx = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 5 ] ; /* Tempbx: CR05 HRE */
1700 Tempbx &= 0x1F ; /* Tempbx: HRE[4:0] */
1701 Tempcx = Tempax ;
1702 Tempcx &= 0xE0 ; /* Tempcx: HRS[7:5] */
1703 Tempdx = Tempcx | Tempbx ; /* Tempdx(HRE): HRS[7:5]HRE[4:0] */
1704 if ( Tempbx < ( Tempax & 0x1F ) ) /* IF HRE < HRS */
1705 Tempdx |= 0x20 ; /* Tempdx: HRE = HRE + 0x20 */
1706 Tempdx <<= 2 ; /* Tempdx << 2 */
1707 XGINew_SetReg1( pVBInfo->P3c4 , 0x2F , Tempdx ) ; /* SR2F [7:2]->HRE */
1708 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x30 , 0xE3 , 00 ) ;
1709
1710 Tempax = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 16 ] ; /* Tempax: CR10 VRS */
1711 XGINew_SetReg1( pVBInfo->P3c4 , 0x34 , Tempax ) ; /* SR34[7:0]->VRS */
1712 Tempcx = Tempax ; /* Tempcx=Tempax=VRS[7:0] */
1713 Tempax = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 7 ] ; /* Tempax[7][2]: CR7[7][2] VRS[9][8] */
1714 Tempbx = Tempax ; /* Tempbx=CR07 */
1715 Tempax &= 0x04 ; /* Tempax[2]: CR07[2] VRS[8] */
1716 Tempax >>= 2;
1717 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x35 , ~0x01, Tempax ) ; /* SR35 D[0]->VRS D[8] */
1718 Tempcx |= (Tempax << 8) ; /* Tempcx[8] |= VRS[8] */
1719 Tempcx |= (Tempbx & 0x80)<<2; /* Tempcx[9] |= VRS[9] */
1720
1721
1722 Tempax = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 17 ] ; /* CR11 VRE */
1723 Tempax &= 0x0F ; /* Tempax: VRE[3:0] */
1724 Tempbx = Tempcx ; /* Tempbx=Tempcx=VRS[9:0] */
1725 Tempbx &= 0x3F0 ; /* Tempbx[9:4]: VRS[9:4] */
1726 Tempbx |= Tempax ; /* Tempbx[9:0]: VRE[9:0] */
1727 if ( Tempax <= (Tempcx & 0x0F) ) /* VRE[3:0]<=VRS[3:0] */
1728 Tempbx |= 0x10 ; /* Tempbx: VRE + 0x10 */
1729 Tempax = (UCHAR)Tempbx & 0xFF; /* Tempax[7:0]: VRE[7:0] */
1730 Tempax <<= 2 ; /* Tempax << 2: VRE[5:0] */
1731 Tempcx = (Tempcx&0x600)>>8; /* Tempcx VRS[10:9] */
1732 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x3F , ~0xFC, Tempax ) ; /* SR3F D[7:2]->VRE D[5:0] */
1733 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x35 , ~0x06, Tempcx ) ; /* SR35 D[2:1]->VRS[10:9] */
1734 }
1735 else
1736 {
1737 index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC ;
1738 Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 3 ] ; /* Tempax: CR4 HRS */
1739 Tempbx = Tempax ; /* Tempbx: HRS[7:0] */
1740 XGINew_SetReg1( pVBInfo->P3c4 , 0x2E , Tempax ) ; /* SR2E[7:0]->HRS */
1741
1742 Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 5 ] ; /* SR0B */
1743 Tempax &= 0xC0 ; /* Tempax[7:6]: SR0B[7:6]: HRS[9:8]*/
1744 Tempbx |= (Tempax << 2); /* Tempbx: HRS[9:0] */
1745
1746 Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 4 ] ; /* CR5 HRE */
1747 Tempax &= 0x1F ; /* Tempax[4:0]: HRE[4:0] */
1748 Tempcx = Tempax ; /* Tempcx: HRE[4:0] */
1749
1750 Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 6 ] ; /* SRC */
1751 Tempax &= 0x04 ; /* Tempax[2]: HRE[5] */
1752 Tempax <<= 3 ; /* Tempax[5]: HRE[5] */
1753 Tempcx |= Tempax ; /* Tempcx[5:0]: HRE[5:0] */
1754
1755 Tempbx = Tempbx & 0x3C0 ; /* Tempbx[9:6]: HRS[9:6] */
1756 Tempbx |= Tempcx ; /* Tempbx: HRS[9:6]HRE[5:0] */
1757
1758 Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 3 ] ; /* Tempax: CR4 HRS */
1759 Tempax &= 0x3F ; /* Tempax: HRS[5:0] */
1760 if( Tempcx <= Tempax ) /* HRE[5:0] < HRS[5:0] */
1761 Tempbx += 0x40 ; /* Tempbx= Tempbx + 0x40 : HRE[9:0]*/
1762
1763 Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 5 ] ; /* SR0B */
1764 Tempax &= 0xC0 ; /* Tempax[7:6]: SR0B[7:6]: HRS[9:8]*/
1765 Tempax >>= 6; /* Tempax[1:0]: HRS[9:8]*/
1766 Tempax |= ((Tempbx << 2) & 0xFF); /* Tempax[7:2]: HRE[5:0] */
1767 XGINew_SetReg1( pVBInfo->P3c4 , 0x2F , Tempax ) ; /* SR2F [7:2][1:0]: HRE[5:0]HRS[9:8] */
1768 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x30 , 0xE3 , 00 ) ;
1769
1770 Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 10 ] ; /* CR10 VRS */
1771 XGINew_SetReg1( pVBInfo->P3c4 , 0x34 , Tempax ) ; /* SR34[7:0]->VRS[7:0] */
1772
1773 Tempcx = Tempax ; /* Tempcx <= VRS[7:0] */
1774 Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 9 ] ; /* CR7[7][2] VRS[9][8] */
1775 Tempbx = Tempax ; /* Tempbx <= CR07[7:0] */
1776 Tempax = Tempax & 0x04 ; /* Tempax[2]: CR7[2]: VRS[8] */
1777 Tempax >>= 2 ; /* Tempax[0]: VRS[8] */
1778 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x35 , ~0x01 , Tempax ) ; /* SR35[0]: VRS[8] */
1779 Tempcx |= (Tempax<<8) ; /* Tempcx <= VRS[8:0] */
1780 Tempcx |= ((Tempbx&0x80)<<2) ; /* Tempcx <= VRS[9:0] */
1781 Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 14 ] ; /* Tempax: SR0A */
1782 Tempax &= 0x08; /* SR0A[3] VRS[10] */
1783 Tempcx |= (Tempax<<7) ; /* Tempcx <= VRS[10:0] */
1784
1785
1786 Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 11 ] ; /* Tempax: CR11 VRE */
1787 Tempax &= 0x0F ; /* Tempax[3:0]: VRE[3:0] */
1788 Tempbx = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 14 ] ; /* Tempbx: SR0A */
1789 Tempbx &= 0x20 ; /* Tempbx[5]: SR0A[5]: VRE[4] */
1790 Tempbx >>= 1 ; /* Tempbx[4]: VRE[4] */
1791 Tempax |= Tempbx ; /* Tempax[4:0]: VRE[4:0] */
1792 Tempbx = Tempcx ; /* Tempbx: VRS[10:0] */
1793 Tempbx &= 0x7E0 ; /* Tempbx[10:5]: VRS[10:5] */
1794 Tempbx |= Tempax ; /* Tempbx: VRS[10:5]VRE[4:0] */
1795
1796 if ( Tempbx <= Tempcx ) /* VRE <= VRS */
1797 Tempbx |= 0x20 ; /* VRE + 0x20 */
1798
1799 Tempax = (Tempbx<<2) & 0xFF ; /* Tempax: Tempax[7:0]; VRE[5:0]00 */
1800 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x3F , ~0xFC , Tempax ) ; /* SR3F[7:2]:VRE[5:0] */
1801 Tempax = Tempcx >> 8;
1802 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x35 , ~0x07 , Tempax ) ; /* SR35[2:0]:VRS[10:8] */
1803 }
1804}
1805
1806
1807/* --------------------------------------------------------------------- */
1808/* Function : XGI_SetXG21LCD */
1809/* Input : */
1810/* Output : FCLK duty cycle, FCLK delay compensation */
1811/* Description : All values set zero */
1812/* --------------------------------------------------------------------- */
1813void XGI_SetXG21LCD(PVB_DEVICE_INFO pVBInfo,USHORT RefreshRateTableIndex,USHORT ModeNo)
1814{
1815 USHORT Data , Temp , b3CC ;
1816 USHORT XGI_P3cc ;
1817
1818 XGI_P3cc = pVBInfo->P3cc ;
1819
1820 XGINew_SetReg1( pVBInfo->P3d4 , 0x2E , 0x00 ) ;
1821 XGINew_SetReg1( pVBInfo->P3d4 , 0x2F , 0x00 ) ;
1822 XGINew_SetReg1( pVBInfo->P3d4 , 0x46 , 0x00 ) ;
1823 XGINew_SetReg1( pVBInfo->P3d4 , 0x47 , 0x00 ) ;
1824 if ( ((*pVBInfo->pDVOSetting)&0xC0) == 0xC0 )
1825 {
1826 XGINew_SetReg1( pVBInfo->P3d4 , 0x2E , *pVBInfo->pCR2E ) ;
1827 XGINew_SetReg1( pVBInfo->P3d4 , 0x2F , *pVBInfo->pCR2F ) ;
1828 XGINew_SetReg1( pVBInfo->P3d4 , 0x46 , *pVBInfo->pCR46 ) ;
1829 XGINew_SetReg1( pVBInfo->P3d4 , 0x47 , *pVBInfo->pCR47 ) ;
1830 }
1831
1832 Temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x37 ) ;
1833
1834 if ( Temp & 0x01 )
1835 {
1836 XGINew_SetRegOR( pVBInfo->P3c4 , 0x06 , 0x40 ) ; /* 18 bits FP */
1837 XGINew_SetRegOR( pVBInfo->P3c4 , 0x09 , 0x40 ) ;
1838 }
1839
1840 XGINew_SetRegOR( pVBInfo->P3c4 , 0x1E , 0x01 ) ; /* Negative blank polarity */
1841
1842 XGINew_SetRegAND( pVBInfo->P3c4 , 0x30 , ~0x20 ) ;
1843 XGINew_SetRegAND( pVBInfo->P3c4 , 0x35 , ~0x80 ) ;
1844
1845 if ( ModeNo <= 0x13 )
1846 {
1847 b3CC = (UCHAR) XGINew_GetReg2( XGI_P3cc ) ;
1848 if ( b3CC & 0x40 )
1849 XGINew_SetRegOR( pVBInfo->P3c4 , 0x30 , 0x20 ) ; /* Hsync polarity */
1850 if ( b3CC & 0x80 )
1851 XGINew_SetRegOR( pVBInfo->P3c4 , 0x35 , 0x80 ) ; /* Vsync polarity */
1852 }
1853 else
1854 {
1855 Data = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag ;
1856 if ( Data & 0x4000 )
1857 XGINew_SetRegOR( pVBInfo->P3c4 , 0x30 , 0x20 ) ; /* Hsync polarity */
1858 if ( Data & 0x8000 )
1859 XGINew_SetRegOR( pVBInfo->P3c4 , 0x35 , 0x80 ) ; /* Vsync polarity */
1860 }
1861}
1862
1863void XGI_SetXG27LCD(PVB_DEVICE_INFO pVBInfo,USHORT RefreshRateTableIndex,USHORT ModeNo)
1864{
1865 USHORT Data , Temp , b3CC ;
1866 USHORT XGI_P3cc ;
1867
1868 XGI_P3cc = pVBInfo->P3cc ;
1869
1870 XGINew_SetReg1( pVBInfo->P3d4 , 0x2E , 0x00 ) ;
1871 XGINew_SetReg1( pVBInfo->P3d4 , 0x2F , 0x00 ) ;
1872 XGINew_SetReg1( pVBInfo->P3d4 , 0x46 , 0x00 ) ;
1873 XGINew_SetReg1( pVBInfo->P3d4 , 0x47 , 0x00 ) ;
1874
1875 Temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x37 ) ;
1876 if ( ( Temp & 0x03 ) == 0 ) /* dual 12 */
1877 {
1878 XGINew_SetReg1( pVBInfo->P3d4 , 0x46 , 0x13 ) ;
1879 XGINew_SetReg1( pVBInfo->P3d4 , 0x47 , 0x13 ) ;
1880 }
1881
1882 if ( ((*pVBInfo->pDVOSetting)&0xC0) == 0xC0 )
1883 {
1884 XGINew_SetReg1( pVBInfo->P3d4 , 0x2E , *pVBInfo->pCR2E ) ;
1885 XGINew_SetReg1( pVBInfo->P3d4 , 0x2F , *pVBInfo->pCR2F ) ;
1886 XGINew_SetReg1( pVBInfo->P3d4 , 0x46 , *pVBInfo->pCR46 ) ;
1887 XGINew_SetReg1( pVBInfo->P3d4 , 0x47 , *pVBInfo->pCR47 ) ;
1888 }
1889
1890 XGI_SetXG27FPBits(pVBInfo);
1891
1892 XGINew_SetRegOR( pVBInfo->P3c4 , 0x1E , 0x01 ) ; /* Negative blank polarity */
1893
1894 XGINew_SetRegAND( pVBInfo->P3c4 , 0x30 , ~0x20 ) ; /* Hsync polarity */
1895 XGINew_SetRegAND( pVBInfo->P3c4 , 0x35 , ~0x80 ) ; /* Vsync polarity */
1896
1897 if ( ModeNo <= 0x13 )
1898 {
1899 b3CC = (UCHAR) XGINew_GetReg2( XGI_P3cc ) ;
1900 if ( b3CC & 0x40 )
1901 XGINew_SetRegOR( pVBInfo->P3c4 , 0x30 , 0x20 ) ; /* Hsync polarity */
1902 if ( b3CC & 0x80 )
1903 XGINew_SetRegOR( pVBInfo->P3c4 , 0x35 , 0x80 ) ; /* Vsync polarity */
1904 }
1905 else
1906 {
1907 Data = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag ;
1908 if ( Data & 0x4000 )
1909 XGINew_SetRegOR( pVBInfo->P3c4 , 0x30 , 0x20 ) ; /* Hsync polarity */
1910 if ( Data & 0x8000 )
1911 XGINew_SetRegOR( pVBInfo->P3c4 , 0x35 , 0x80 ) ; /* Vsync polarity */
1912 }
1913}
1914
1915/* --------------------------------------------------------------------- */
1916/* Function : XGI_UpdateXG21CRTC */
1917/* Input : */
1918/* Output : CRT1 CRTC */
1919/* Description : Modify CRT1 Hsync/Vsync to fix LCD mode timing */
1920/* --------------------------------------------------------------------- */
1921void XGI_UpdateXG21CRTC( USHORT ModeNo , PVB_DEVICE_INFO pVBInfo , USHORT RefreshRateTableIndex )
1922{
1923 int i , index = -1;
1924
1925 XGINew_SetRegAND( pVBInfo->P3d4 , 0x11 , 0x7F ) ; /* Unlock CR0~7 */
1926 if ( ModeNo <= 0x13 )
1927 {
1928 for( i = 0 ; i < 12 ; i++ )
1929 {
1930 if ( ModeNo == pVBInfo->UpdateCRT1[ i ].ModeID )
1931 index = i ;
1932 }
1933 }
1934 else
1935 {
1936 if ( ModeNo == 0x2E && ( pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC == RES640x480x60 ) )
1937 index = 12 ;
1938 else if ( ModeNo == 0x2E && ( pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC == RES640x480x72 ) )
1939 index = 13 ;
1940 else if ( ModeNo == 0x2F )
1941 index = 14 ;
1942 else if ( ModeNo == 0x50 )
1943 index = 15 ;
1944 else if ( ModeNo == 0x59 )
1945 index = 16 ;
1946 }
1947
1948 if( index != -1 )
1949 {
1950 XGINew_SetReg1( pVBInfo->P3d4 , 0x02 , pVBInfo->UpdateCRT1[ index ].CR02 ) ;
1951 XGINew_SetReg1( pVBInfo->P3d4 , 0x03 , pVBInfo->UpdateCRT1[ index ].CR03 ) ;
1952 XGINew_SetReg1( pVBInfo->P3d4 , 0x15 , pVBInfo->UpdateCRT1[ index ].CR15 ) ;
1953 XGINew_SetReg1( pVBInfo->P3d4 , 0x16 , pVBInfo->UpdateCRT1[ index ].CR16 ) ;
1954 }
1955}
1956
1957
1958/* --------------------------------------------------------------------- */
1959/* Function : XGI_SetCRT1DE */
1960/* Input : */
1961/* Output : */
1962/* Description : */
1963/* --------------------------------------------------------------------- */
1964void XGI_SetCRT1DE( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo,USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
1965{
1966 USHORT resindex ,
1967 tempax ,
1968 tempbx ,
1969 tempcx ,
1970 temp ,
1971 modeflag ;
1972
1973 UCHAR data ;
1974
1975 resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo ) ;
1976
1977 if ( ModeNo <= 0x13 )
1978 {
1979 modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
1980 tempax = pVBInfo->StResInfo[ resindex ].HTotal ;
1981 tempbx = pVBInfo->StResInfo[ resindex ].VTotal ;
1982 }
1983 else
1984 {
1985 modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
1986 tempax = pVBInfo->ModeResInfo[ resindex ].HTotal ;
1987 tempbx = pVBInfo->ModeResInfo[ resindex ].VTotal ;
1988 }
1989
1990 if ( modeflag & HalfDCLK )
1991 tempax = tempax >> 1 ;
1992
1993 if ( ModeNo > 0x13 )
1994 {
1995 if ( modeflag & HalfDCLK )
1996 tempax = tempax << 1 ;
1997
1998 temp = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag ;
1999
2000 if ( temp & InterlaceMode )
2001 tempbx = tempbx >> 1 ;
2002
2003 if ( modeflag & DoubleScanMode )
2004 tempbx = tempbx << 1 ;
2005 }
2006
2007 tempcx = 8 ;
2008
2009 /* if ( !( modeflag & Charx8Dot ) ) */
2010 /* tempcx = 9 ; */
2011
2012 tempax /= tempcx ;
2013 tempax -= 1 ;
2014 tempbx -= 1 ;
2015 tempcx = tempax ;
2016 temp = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ;
2017 data = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ;
2018 data &= 0x7F ;
2019 XGINew_SetReg1( pVBInfo->P3d4 , 0x11 , data ) ; /* Unlock CRTC */
2020 XGINew_SetReg1( pVBInfo->P3d4 , 0x01 , ( USHORT )( tempcx & 0xff ) ) ;
2021 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x0b , ~0x0c , ( USHORT )( ( tempcx & 0x0ff00 ) >> 10 ) ) ;
2022 XGINew_SetReg1( pVBInfo->P3d4 , 0x12 , ( USHORT )( tempbx & 0xff ) ) ;
2023 tempax = 0 ;
2024 tempbx = tempbx >> 8 ;
2025
2026 if ( tempbx & 0x01 )
2027 tempax |= 0x02 ;
2028
2029 if ( tempbx & 0x02 )
2030 tempax |= 0x40 ;
2031
2032 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x42 , tempax ) ;
2033 data =( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x07 ) ;
2034 data &= 0xFF ;
2035 tempax = 0 ;
2036
2037 if ( tempbx & 0x04 )
2038 tempax |= 0x02 ;
2039
2040 XGINew_SetRegANDOR( pVBInfo->P3d4 ,0x0a , ~0x02 , tempax ) ;
2041 XGINew_SetReg1( pVBInfo->P3d4 , 0x11 , temp ) ;
2042}
2043
2044
2045/* --------------------------------------------------------------------- */
2046/* Function : XGI_GetResInfo */
2047/* Input : */
2048/* Output : */
2049/* Description : */
2050/* --------------------------------------------------------------------- */
2051USHORT XGI_GetResInfo(USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
2052{
2053 USHORT resindex ;
2054
2055 if ( ModeNo <= 0x13 )
2056 {
2057 resindex = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ResInfo ; /* si+St_ResInfo */
2058 }
2059 else
2060 {
2061 resindex = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ; /* si+Ext_ResInfo */
2062 }
2063 return( resindex ) ;
2064}
2065
2066
2067/* --------------------------------------------------------------------- */
2068/* Function : XGI_SetCRT1Offset */
2069/* Input : */
2070/* Output : */
2071/* Description : */
2072/* --------------------------------------------------------------------- */
2073void XGI_SetCRT1Offset( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
2074{
2075 USHORT temp ,
2076 ah ,
2077 al ,
2078 temp2 ,
2079 i ,
2080 DisplayUnit ;
2081
2082 /* GetOffset */
2083 temp = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeInfo ;
2084 temp = temp >> 8 ;
2085 temp = pVBInfo->ScreenOffset[ temp ] ;
2086
2087 temp2 = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag ;
2088 temp2 &= InterlaceMode ;
2089
2090 if ( temp2 )
2091 temp = temp << 1;
2092
2093 temp2 = pVBInfo->ModeType - ModeEGA ;
2094
2095 switch( temp2 )
2096 {
2097 case 0:
2098 temp2 = 1 ;
2099 break ;
2100 case 1:
2101 temp2 = 2 ;
2102 break ;
2103 case 2:
2104 temp2 = 4 ;
2105 break ;
2106 case 3:
2107 temp2 = 4 ;
2108 break ;
2109 case 4:
2110 temp2 = 6 ;
2111 break;
2112 case 5:
2113 temp2 = 8 ;
2114 break ;
2115 default:
2116 break ;
2117 }
2118
2119 if ( ( ModeNo >= 0x26 ) && ( ModeNo <= 0x28 ) )
2120 temp = temp * temp2 + temp2 / 2 ;
2121 else
2122 temp *= temp2 ;
2123
2124 /* SetOffset */
2125 DisplayUnit = temp ;
2126 temp2 = temp ;
2127 temp = temp >> 8 ; /* ah */
2128 temp &= 0x0F ;
2129 i = XGINew_GetReg1( pVBInfo->P3c4 , 0x0E ) ;
2130 i &= 0xF0 ;
2131 i |= temp ;
2132 XGINew_SetReg1( pVBInfo->P3c4 , 0x0E , i ) ;
2133
2134 temp =( UCHAR )temp2 ;
2135 temp &= 0xFF ; /* al */
2136 XGINew_SetReg1( pVBInfo->P3d4 , 0x13 , temp ) ;
2137
2138 /* SetDisplayUnit */
2139 temp2 = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag ;
2140 temp2 &= InterlaceMode ;
2141 if ( temp2 )
2142 DisplayUnit >>= 1 ;
2143
2144 DisplayUnit = DisplayUnit << 5 ;
2145 ah = ( DisplayUnit & 0xff00 ) >> 8 ;
2146 al = DisplayUnit & 0x00ff ;
2147 if ( al == 0 )
2148 ah += 1 ;
2149 else
2150 ah += 2 ;
2151
2152 if ( HwDeviceExtension->jChipType >= XG20 )
2153 if ( ( ModeNo == 0x4A ) | (ModeNo == 0x49 ) )
2154 ah -= 1 ;
2155
2156 XGINew_SetReg1( pVBInfo->P3c4 , 0x10 , ah ) ;
2157}
2158
2159
2160/* --------------------------------------------------------------------- */
2161/* Function : XGI_SetCRT1VCLK */
2162/* Input : */
2163/* Output : */
2164/* Description : */
2165/* --------------------------------------------------------------------- */
2166void XGI_SetCRT1VCLK( USHORT ModeNo , USHORT ModeIdIndex ,
2167 PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
2168{
2169 UCHAR index , data ;
2170 USHORT vclkindex ;
2171
2172 if ( pVBInfo->IF_DEF_LVDS == 1 )
2173 {
2174 index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRTVCLK ;
2175 data = XGINew_GetReg1( pVBInfo->P3c4 , 0x31 ) & 0xCF ;
2176 XGINew_SetReg1( pVBInfo->P3c4 , 0x31 , data ) ;
2177 XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , pVBInfo->VCLKData[ index ].SR2B ) ;
2178 XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , pVBInfo->VCLKData[ index ].SR2C ) ;
2179 XGINew_SetReg1( pVBInfo->P3c4 , 0x2D , 0x01 ) ;
2180 }
2181 else if ( ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) && ( pVBInfo->VBInfo & SetCRT2ToLCDA ) )
2182 {
2183 vclkindex = XGI_GetVCLK2Ptr( ModeNo , ModeIdIndex , RefreshRateTableIndex , HwDeviceExtension, pVBInfo ) ;
2184 data = XGINew_GetReg1( pVBInfo->P3c4 , 0x31 ) & 0xCF ;
2185 XGINew_SetReg1( pVBInfo->P3c4 , 0x31 , data ) ;
2186 data = pVBInfo->VBVCLKData[ vclkindex ].Part4_A ;
2187 XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , data ) ;
2188 data = pVBInfo->VBVCLKData[ vclkindex ].Part4_B ;
2189 XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , data ) ;
2190 XGINew_SetReg1( pVBInfo->P3c4 , 0x2D , 0x01 ) ;
2191 }
2192 else
2193 {
2194 index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRTVCLK ;
2195 data = XGINew_GetReg1( pVBInfo->P3c4 , 0x31 ) & 0xCF ;
2196 XGINew_SetReg1( pVBInfo->P3c4 , 0x31 , data ) ;
2197 XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , pVBInfo->VCLKData[ index ].SR2B ) ;
2198 XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , pVBInfo->VCLKData[ index ].SR2C ) ;
2199 XGINew_SetReg1( pVBInfo->P3c4 , 0x2D , 0x01 ) ;
2200 }
2201
2202 if ( HwDeviceExtension->jChipType >= XG20 )
2203 {
2204 if ( pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag & HalfDCLK )
2205 {
2206 data = XGINew_GetReg1( pVBInfo->P3c4 , 0x2B ) ;
2207 XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , data ) ;
2208 data = XGINew_GetReg1( pVBInfo->P3c4 , 0x2C ) ;
2209 index = data ;
2210 index &= 0xE0 ;
2211 data &= 0x1F ;
2212 data = data << 1 ;
2213 data += 1 ;
2214 data |= index ;
2215 XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , data ) ;
2216 }
2217 }
2218}
2219
2220
2221/* --------------------------------------------------------------------- */
2222/* Function : XGI_SetCRT1FIFO */
2223/* Input : */
2224/* Output : */
2225/* Description : */
2226/* --------------------------------------------------------------------- */
2227void XGI_SetCRT1FIFO( USHORT ModeNo , PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo )
2228{
2229 USHORT data ;
2230
2231 data = XGINew_GetReg1( pVBInfo->P3c4 , 0x3D ) ;
2232 data &= 0xfe ;
2233 XGINew_SetReg1( pVBInfo->P3c4 , 0x3D , data ) ; /* diable auto-threshold */
2234
2235 if ( ModeNo > 0x13 )
2236 {
2237 XGINew_SetReg1( pVBInfo->P3c4 , 0x08 , 0x34 ) ;
2238 data = XGINew_GetReg1( pVBInfo->P3c4 , 0x09 ) ;
2239 data &= 0xC0 ;
2240 XGINew_SetReg1( pVBInfo->P3c4 , 0x09 , data | 0x30) ;
2241 data = XGINew_GetReg1( pVBInfo->P3c4 , 0x3D ) ;
2242 data |= 0x01 ;
2243 XGINew_SetReg1( pVBInfo->P3c4 , 0x3D , data ) ;
2244 }
2245 else
2246 {
2247 if (HwDeviceExtension->jChipType == XG27)
2248 {
2249 XGINew_SetReg1( pVBInfo->P3c4 , 0x08 , 0x0E ) ;
2250 data = XGINew_GetReg1( pVBInfo->P3c4 , 0x09 ) ;
2251 data &= 0xC0 ;
2252 XGINew_SetReg1( pVBInfo->P3c4 , 0x09 , data | 0x20 ) ;
2253 }
2254 else
2255 {
2256 XGINew_SetReg1( pVBInfo->P3c4 , 0x08 , 0xAE ) ;
2257 data = XGINew_GetReg1( pVBInfo->P3c4 , 0x09 ) ;
2258 data &= 0xF0 ;
2259 XGINew_SetReg1( pVBInfo->P3c4 , 0x09 , data ) ;
2260 }
2261 }
2262
2263 if (HwDeviceExtension->jChipType == XG21)
2264 {
2265 XGI_SetXG21FPBits(pVBInfo); /* Fix SR9[7:6] can't read back */
2266 }
2267}
2268
2269
2270/* --------------------------------------------------------------------- */
2271/* Function : XGI_SetCRT1ModeRegs */
2272/* Input : */
2273/* Output : */
2274/* Description : */
2275/* --------------------------------------------------------------------- */
2276void XGI_SetCRT1ModeRegs( PXGI_HW_DEVICE_INFO HwDeviceExtension ,
2277 USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo )
2278{
2279 USHORT data ,
2280 data2 ,
2281 data3 ,
2282 infoflag = 0 ,
2283 modeflag ,
2284 resindex ,
2285 xres ;
2286
2287 if ( ModeNo > 0x13 )
2288 {
2289 modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
2290 infoflag = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag ;
2291 }
2292 else
2293 modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; /* si+St_ModeFlag */
2294
2295 if ( XGINew_GetReg1( pVBInfo->P3d4 , 0x31 ) & 0x01 )
2296 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x1F , 0x3F , 0x00 ) ;
2297
2298 if ( ModeNo > 0x13 )
2299 data = infoflag ;
2300 else
2301 data = 0 ;
2302
2303 data2 = 0 ;
2304
2305 if ( ModeNo > 0x13 )
2306 {
2307 if ( pVBInfo->ModeType > 0x02 )
2308 {
2309 data2 |= 0x02 ;
2310 data3 = pVBInfo->ModeType - ModeVGA ;
2311 data3 = data3 << 2 ;
2312 data2 |= data3 ;
2313 }
2314 }
2315
2316 data &= InterlaceMode ;
2317
2318 if ( data )
2319 data2 |= 0x20 ;
2320
2321 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x06 , ~0x3F , data2 ) ;
2322 /* XGINew_SetReg1(pVBInfo->P3c4,0x06,data2); */
2323 resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo ) ;
2324 if ( ModeNo <= 0x13 )
2325 xres = pVBInfo->StResInfo[ resindex ].HTotal ;
2326 else
2327 xres = pVBInfo->ModeResInfo[ resindex ].HTotal ; /* xres->ax */
2328
2329 data = 0x0000 ;
2330 if ( infoflag & InterlaceMode )
2331 {
2332 if ( xres == 1024 )
2333 data = 0x0035 ;
2334 else if ( xres == 1280 )
2335 data = 0x0048 ;
2336 }
2337
2338 data2 = data & 0x00FF ;
2339 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x19 , 0xFF , data2 ) ;
2340 data2 = ( data & 0xFF00 ) >> 8 ;
2341 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x19 , 0xFC , data2 ) ;
2342
2343 if( modeflag & HalfDCLK )
2344 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x01 , 0xF7 , 0x08 ) ;
2345
2346 data2 = 0 ;
2347
2348 if ( modeflag & LineCompareOff )
2349 data2 |= 0x08 ;
2350
2351 if ( ModeNo > 0x13 )
2352 {
2353 if ( pVBInfo->ModeType == ModeEGA )
2354 data2 |= 0x40 ;
2355 }
2356
2357 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0F , ~0x48 , data2 ) ;
2358 data = 0x60 ;
2359 if ( pVBInfo->ModeType != ModeText )
2360 {
2361 data = data ^ 0x60 ;
2362 if ( pVBInfo->ModeType != ModeEGA )
2363 {
2364 data = data ^ 0xA0 ;
2365 }
2366 }
2367 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x21 , 0x1F , data ) ;
2368
2369 XGI_SetVCLKState( HwDeviceExtension , ModeNo , RefreshRateTableIndex, pVBInfo) ;
2370
2371 /* if(modeflag&HalfDCLK)//030305 fix lowresolution bug */
2372 /* if(XGINew_IF_DEF_NEW_LOWRES) */
2373 /* XGI_VesaLowResolution(ModeNo,ModeIdIndex);//030305 fix lowresolution bug */
2374
2375 data=XGINew_GetReg1( pVBInfo->P3d4 , 0x31 ) ;
2376
2377 if (HwDeviceExtension->jChipType == XG27 )
2378 {
2379 if ( data & 0x40 )
2380 data = 0x2c ;
2381 else
2382 data = 0x6c ;
2383 XGINew_SetReg1( pVBInfo->P3d4 , 0x52 , data ) ;
2384 XGINew_SetRegOR( pVBInfo->P3d4 , 0x51 , 0x10 ) ;
2385 }
2386 else
2387 if (HwDeviceExtension->jChipType >= XG20 )
2388 {
2389 if ( data & 0x40 )
2390 data = 0x33 ;
2391 else
2392 data = 0x73 ;
2393 XGINew_SetReg1( pVBInfo->P3d4 , 0x52 , data ) ;
2394 XGINew_SetReg1( pVBInfo->P3d4 , 0x51 , 0x02 ) ;
2395 }
2396 else
2397 {
2398 if ( data & 0x40 )
2399 data = 0x2c ;
2400 else
2401 data = 0x6c ;
2402 XGINew_SetReg1( pVBInfo->P3d4 , 0x52 , data ) ;
2403 }
2404
2405}
2406
2407
2408/* --------------------------------------------------------------------- */
2409/* Function : XGI_SetVCLKState */
2410/* Input : */
2411/* Output : */
2412/* Description : */
2413/* --------------------------------------------------------------------- */
2414void XGI_SetVCLKState( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo , USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo )
2415{
2416 USHORT data ,
2417 data2 = 0 ;
2418 SHORT VCLK ;
2419
2420 UCHAR index ;
2421
2422 if ( ModeNo <= 0x13 )
2423 VCLK = 0 ;
2424 else
2425 {
2426 index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRTVCLK ;
2427 index &= IndexMask ;
2428 VCLK = pVBInfo->VCLKData[ index ].CLOCK ;
2429 }
2430
2431 data = XGINew_GetReg1( pVBInfo->P3c4 , 0x32 ) ;
2432 data &= 0xf3 ;
2433 if ( VCLK >= 200 )
2434 data |= 0x0c ; /* VCLK > 200 */
2435
2436 if ( HwDeviceExtension->jChipType >= XG20 )
2437 data &= ~0x04 ; /* 2 pixel mode */
2438
2439 XGINew_SetReg1( pVBInfo->P3c4 , 0x32 , data ) ;
2440
2441 if ( HwDeviceExtension->jChipType < XG20 )
2442 {
2443 data = XGINew_GetReg1( pVBInfo->P3c4 , 0x1F ) ;
2444 data &= 0xE7 ;
2445 if ( VCLK < 200 )
2446 data |= 0x10 ;
2447 XGINew_SetReg1( pVBInfo->P3c4 , 0x1F , data ) ;
2448 }
2449
2450/* Jong for Adavantech LCD ripple issue
2451 if ( ( VCLK >= 0 ) && ( VCLK < 135 ) )
2452 data2 = 0x03 ;
2453 else if ( ( VCLK >= 135 ) && ( VCLK < 160 ) )
2454 data2 = 0x02 ;
2455 else if ( ( VCLK >= 160 ) && ( VCLK < 260 ) )
2456 data2 = 0x01 ;
2457 else if ( VCLK > 260 )
2458 data2 = 0x00 ;
2459*/
2460 data2 = 0x00 ;
2461
2462 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x07 , 0xFC , data2 ) ;
2463 if (HwDeviceExtension->jChipType >= XG27 )
2464 {
2465 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x40 , 0xFC , data2&0x03 ) ;
2466 }
2467
2468
2469}
2470
2471
2472/* --------------------------------------------------------------------- */
2473/* Function : XGI_VesaLowResolution */
2474/* Input : */
2475/* Output : */
2476/* Description : */
2477/* --------------------------------------------------------------------- */
2478/*void XGI_VesaLowResolution( USHORT ModeNo , USHORT ModeIdIndex ,PVB_DEVICE_INFO pVBInfo)
2479{
2480 USHORT modeflag;
2481
2482 if ( ModeNo > 0x13 )
2483 modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
2484 else
2485 modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
2486
2487 if ( ModeNo > 0x13 )
2488 {
2489 if ( modeflag & DoubleScanMode )
2490 {
2491 if ( modeflag & HalfDCLK )
2492 {
2493 if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
2494 {
2495 if ( !( pVBInfo->VBInfo & SetCRT2ToRAMDAC ) )
2496 {
2497 if ( pVBInfo->VBInfo & SetInSlaveMode )
2498 {
2499 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x01 , 0xf7 , 0x00 ) ;
2500 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0f , 0x7f , 0x00 ) ;
2501 return ;
2502 }
2503 }
2504 }
2505 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0f , 0xff , 0x80 ) ;
2506 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x01 , 0xf7 , 0x00 ) ;
2507 return ;
2508 }
2509 }
2510 }
2511 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0f , 0x7f , 0x00 ) ;
2512}
2513*/
2514
2515/* --------------------------------------------------------------------- */
2516/* Function : XGI_LoadDAC */
2517/* Input : */
2518/* Output : */
2519/* Description : */
2520/* --------------------------------------------------------------------- */
2521void XGI_LoadDAC( USHORT ModeNo , USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo )
2522{
2523 USHORT data , data2 , time ,
2524 i , j , k , m , n , o ,
2525 si , di , bx , dl , al , ah , dh ,
2526 *table = NULL ;
2527
2528 if ( ModeNo <= 0x13 )
2529 data = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
2530 else
2531 data = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
2532
2533 data &= DACInfoFlag ;
2534 time = 64 ;
2535
2536 if ( data == 0x00 )
2537 table = XGINew_MDA_DAC ;
2538 else if ( data == 0x08 )
2539 table = XGINew_CGA_DAC ;
2540 else if ( data == 0x10 )
2541 table = XGINew_EGA_DAC ;
2542 else if ( data == 0x18 )
2543 {
2544 time = 256 ;
2545 table = XGINew_VGA_DAC ;
2546 }
2547
2548 if ( time == 256 )
2549 j = 16 ;
2550 else
2551 j = time ;
2552
2553 XGINew_SetReg3( pVBInfo->P3c6 , 0xFF ) ;
2554 XGINew_SetReg3( pVBInfo->P3c8 , 0x00 ) ;
2555
2556 for( i = 0 ; i < j ; i++ )
2557 {
2558 data = table[ i ] ;
2559
2560 for( k = 0 ; k < 3 ; k++ )
2561 {
2562 data2 = 0 ;
2563
2564 if ( data & 0x01 )
2565 data2 = 0x2A ;
2566
2567 if ( data & 0x02 )
2568 data2 += 0x15 ;
2569
2570 XGINew_SetReg3( pVBInfo->P3c9 , data2 ) ;
2571 data = data >> 2 ;
2572 }
2573 }
2574
2575 if ( time == 256 )
2576 {
2577 for( i = 16 ; i < 32 ; i++ )
2578 {
2579 data = table[ i ] ;
2580
2581 for( k = 0 ; k < 3 ; k++ )
2582 XGINew_SetReg3( pVBInfo->P3c9 , data ) ;
2583 }
2584
2585 si = 32 ;
2586
2587 for( m = 0 ; m < 9 ; m++ )
2588 {
2589 di = si ;
2590 bx = si + 0x04 ;
2591 dl = 0 ;
2592
2593 for( n = 0 ; n < 3 ; n++ )
2594 {
2595 for( o = 0 ; o < 5 ; o++ )
2596 {
2597 dh = table[ si ] ;
2598 ah = table[ di ] ;
2599 al = table[ bx ] ;
2600 si++ ;
2601 XGI_WriteDAC( dl , ah , al , dh, pVBInfo ) ;
2602 }
2603
2604 si -= 2 ;
2605
2606 for( o = 0 ; o < 3 ; o++ )
2607 {
2608 dh = table[ bx ] ;
2609 ah = table[ di ] ;
2610 al = table[ si ] ;
2611 si-- ;
2612 XGI_WriteDAC( dl , ah , al , dh, pVBInfo ) ;
2613 }
2614
2615 dl++ ;
2616 }
2617
2618 si += 5 ;
2619 }
2620 }
2621}
2622
2623
2624/* --------------------------------------------------------------------- */
2625/* Function : XGI_WriteDAC */
2626/* Input : */
2627/* Output : */
2628/* Description : */
2629/* --------------------------------------------------------------------- */
2630void XGI_WriteDAC( USHORT dl , USHORT ah , USHORT al , USHORT dh,PVB_DEVICE_INFO pVBInfo )
2631{
2632 USHORT temp , bh , bl ;
2633
2634 bh = ah ;
2635 bl = al ;
2636
2637 if ( dl != 0 )
2638 {
2639 temp = bh ;
2640 bh = dh ;
2641 dh = temp ;
2642 if ( dl == 1 )
2643 {
2644 temp = bl ;
2645 bl = dh ;
2646 dh = temp ;
2647 }
2648 else
2649 {
2650 temp = bl ;
2651 bl = bh ;
2652 bh = temp ;
2653 }
2654 }
2655 XGINew_SetReg3( pVBInfo->P3c9 , ( USHORT )dh ) ;
2656 XGINew_SetReg3( pVBInfo->P3c9 , ( USHORT )bh ) ;
2657 XGINew_SetReg3( pVBInfo->P3c9 , ( USHORT )bl ) ;
2658}
2659
2660#if 0
2661/* --------------------------------------------------------------------- */
2662/* Function : XGI_ClearBuffer */
2663/* Input : */
2664/* Output : */
2665/* Description : */
2666/* --------------------------------------------------------------------- */
2667void XGI_ClearBuffer( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo, PVB_DEVICE_INFO pVBInfo)
2668{
2669 PVOID VideoMemoryAddress = ( PVOID )HwDeviceExtension->pjVideoMemoryAddress ;
2670 ULONG AdapterMemorySize = ( ULONG )HwDeviceExtension->ulVideoMemorySize ;
2671 PUSHORT pBuffer ;
2672#ifndef LINUX_XF86
2673 int i ;
2674#endif
2675
2676 if ( pVBInfo->ModeType >= ModeEGA )
2677 {
2678 if ( ModeNo > 0x13 )
2679 {
2680 AdapterMemorySize = 0x40000 ; /* clear 256k */
2681 /* GetDRAMSize( HwDeviceExtension ) ; */
2682 XGI_SetMemory( VideoMemoryAddress , AdapterMemorySize , 0 ) ;
2683 }
2684 else
2685 {
2686/*
2687 pBuffer = VideoMemoryAddress ;
2688 for( i = 0 ; i < 0x4000 ; i++ )
2689 pBuffer[ i ] = 0x0000 ;
2690*/
2691 }
2692 }
2693 else
2694 {
2695 pBuffer = VideoMemoryAddress ;
2696 if ( pVBInfo->ModeType < ModeCGA )
2697 {
2698/*
2699 for ( i = 0 ; i < 0x4000 ; i++ )
2700 pBuffer[ i ] = 0x0720 ;
2701*/
2702 }
2703 else
2704 XGI_SetMemory( VideoMemoryAddress , 0x8000 , 0 ) ;
2705 }
2706}
2707
2708#endif
2709/* --------------------------------------------------------------------- */
2710/* Function : XGI_SetLCDAGroup */
2711/* Input : */
2712/* Output : */
2713/* Description : */
2714/* --------------------------------------------------------------------- */
2715void XGI_SetLCDAGroup( USHORT ModeNo , USHORT ModeIdIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
2716{
2717 USHORT RefreshRateTableIndex ;
2718 /* USHORT temp ; */
2719
2720 /* pVBInfo->SelectCRT2Rate = 0 ; */
2721
2722 pVBInfo->SetFlag |= ProgrammingCRT2 ;
2723 RefreshRateTableIndex = XGI_GetRatePtrCRT2( HwDeviceExtension, ModeNo , ModeIdIndex, pVBInfo ) ;
2724 XGI_GetLVDSResInfo( ModeNo , ModeIdIndex, pVBInfo ) ;
2725 XGI_GetLVDSData( ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo);
2726 XGI_ModCRT1Regs( ModeNo , ModeIdIndex , RefreshRateTableIndex , HwDeviceExtension, pVBInfo ) ;
2727 XGI_SetLVDSRegs( ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
2728 XGI_SetCRT2ECLK( ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
2729}
2730
2731
2732/* --------------------------------------------------------------------- */
2733/* Function : XGI_GetLVDSResInfo */
2734/* Input : */
2735/* Output : */
2736/* Description : */
2737/* --------------------------------------------------------------------- */
2738void XGI_GetLVDSResInfo( USHORT ModeNo , USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo )
2739{
2740 USHORT resindex , xres , yres , modeflag ;
2741
2742 if ( ModeNo <= 0x13 )
2743 {
2744 modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ResInfo ; /* si+St_ResInfo */
2745 }
2746 else
2747 {
2748 modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ; /* si+Ext_ResInfo */
2749 }
2750
2751
2752 /* if ( ModeNo > 0x13 ) */
2753 /* modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; */
2754 /* else */
2755 /* modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; */
2756
2757 if ( ModeNo <= 0x13 )
2758 {
2759 resindex = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ResInfo ; /* si+St_ResInfo */
2760 }
2761 else
2762 {
2763 resindex = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ; /* si+Ext_ResInfo */
2764 }
2765
2766 /* resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo ) ; */
2767
2768 if ( ModeNo <= 0x13 )
2769 {
2770 xres = pVBInfo->StResInfo[ resindex ].HTotal ;
2771 yres = pVBInfo->StResInfo[ resindex ].VTotal ;
2772 }
2773 else
2774 {
2775 xres = pVBInfo->ModeResInfo[ resindex ].HTotal ;
2776 yres = pVBInfo->ModeResInfo[ resindex ].VTotal ;
2777 }
2778 if ( ModeNo > 0x13 )
2779 {
2780 if ( modeflag & HalfDCLK )
2781 xres = xres << 1 ;
2782
2783 if ( modeflag & DoubleScanMode )
2784 yres = yres << 1 ;
2785 }
2786 /* if ( modeflag & Charx8Dot ) */
2787 /* { */
2788
2789 if ( xres == 720 )
2790 xres = 640 ;
2791
2792 /* } */
2793 pVBInfo->VGAHDE = xres ;
2794 pVBInfo->HDE = xres ;
2795 pVBInfo->VGAVDE = yres ;
2796 pVBInfo->VDE = yres ;
2797}
2798
2799
2800/* --------------------------------------------------------------------- */
2801/* Function : XGI_GetLVDSData */
2802/* Input : */
2803/* Output : */
2804/* Description : */
2805/* --------------------------------------------------------------------- */
2806void XGI_GetLVDSData( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
2807{
2808 USHORT tempbx ;
2809 XGI330_LVDSDataStruct *LCDPtr = NULL ;
2810 XGI330_CHTVDataStruct *TVPtr = NULL ;
2811
2812 tempbx = 2 ;
2813
2814 if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
2815 {
2816 LCDPtr = ( XGI330_LVDSDataStruct * )XGI_GetLcdPtr( tempbx, ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo) ;
2817 pVBInfo->VGAHT = LCDPtr->VGAHT ;
2818 pVBInfo->VGAVT = LCDPtr->VGAVT ;
2819 pVBInfo->HT = LCDPtr->LCDHT ;
2820 pVBInfo->VT = LCDPtr->LCDVT ;
2821 }
2822 if ( pVBInfo->IF_DEF_CH7017 == 1 )
2823 {
2824 if ( pVBInfo->VBInfo & SetCRT2ToTV )
2825 {
2826 TVPtr = ( XGI330_CHTVDataStruct * )XGI_GetTVPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
2827 pVBInfo->VGAHT = TVPtr->VGAHT ;
2828 pVBInfo->VGAVT = TVPtr->VGAVT ;
2829 pVBInfo->HT = TVPtr->LCDHT ;
2830 pVBInfo->VT = TVPtr->LCDVT ;
2831 }
2832 }
2833
2834 if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
2835 {
2836 if ( !( pVBInfo->LCDInfo & ( SetLCDtoNonExpanding | EnableScalingLCD ) ) )
2837 {
2838 if ( ( pVBInfo->LCDResInfo == Panel1024x768 ) || ( pVBInfo->LCDResInfo == Panel1024x768x75 ) )
2839 {
2840 pVBInfo->HDE = 1024 ;
2841 pVBInfo->VDE = 768 ;
2842 }
2843 else if ( ( pVBInfo->LCDResInfo == Panel1280x1024 ) || ( pVBInfo->LCDResInfo == Panel1280x1024x75 ) )
2844 {
2845 pVBInfo->HDE = 1280 ;
2846 pVBInfo->VDE = 1024 ;
2847 }
2848 else if ( pVBInfo->LCDResInfo == Panel1400x1050 )
2849 {
2850 pVBInfo->HDE = 1400 ;
2851 pVBInfo->VDE = 1050 ;
2852 }
2853 else
2854 {
2855 pVBInfo->HDE = 1600 ;
2856 pVBInfo->VDE = 1200 ;
2857 }
2858 }
2859 }
2860}
2861
2862
2863/* --------------------------------------------------------------------- */
2864/* Function : XGI_ModCRT1Regs */
2865/* Input : */
2866/* Output : */
2867/* Description : */
2868/* --------------------------------------------------------------------- */
2869void XGI_ModCRT1Regs( USHORT ModeNo , USHORT ModeIdIndex ,
2870 USHORT RefreshRateTableIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo )
2871{
2872 UCHAR index ;
2873 USHORT tempbx , i ;
2874 XGI_LVDSCRT1HDataStruct *LCDPtr = NULL ;
2875 XGI_LVDSCRT1VDataStruct *LCDPtr1 =NULL ;
2876 /* XGI330_CHTVDataStruct *TVPtr = NULL ; */
2877 XGI_CH7007TV_TimingHStruct *CH7007TV_TimingHPtr = NULL;
2878 XGI_CH7007TV_TimingVStruct *CH7007TV_TimingVPtr = NULL;
2879
2880 if( ModeNo <= 0x13 )
2881 index = pVBInfo->SModeIDTable[ ModeIdIndex ].St_CRT2CRTC ;
2882 else
2883 index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
2884
2885 index= index & IndexMask ;
2886
2887 if ( ( pVBInfo->IF_DEF_ScaleLCD == 0 ) || ( ( pVBInfo->IF_DEF_ScaleLCD == 1 ) && ( !( pVBInfo->LCDInfo & EnableScalingLCD ) ) ) )
2888 {
2889 tempbx = 0 ;
2890
2891 if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
2892 {
2893 LCDPtr = ( XGI_LVDSCRT1HDataStruct * )XGI_GetLcdPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
2894
2895 for( i = 0 ; i < 8 ; i++ )
2896 pVBInfo->TimingH[ 0 ].data[ i ] = LCDPtr[ 0 ].Reg[ i ] ;
2897 }
2898
2899 if ( pVBInfo->IF_DEF_CH7007 == 1 )
2900 {
2901 if ( pVBInfo->VBInfo & SetCRT2ToTV )
2902 {
2903 CH7007TV_TimingHPtr = ( XGI_CH7007TV_TimingHStruct *)XGI_GetTVPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
2904
2905 for( i = 0 ; i < 8 ; i++ )
2906 pVBInfo->TimingH[ 0 ].data[ i ] = CH7007TV_TimingHPtr[ 0 ].data[ i ] ;
2907 }
2908 }
2909
2910 /* if ( pVBInfo->IF_DEF_CH7017 == 1 )
2911 {
2912 if ( pVBInfo->VBInfo & SetCRT2ToTV )
2913 TVPtr = ( XGI330_CHTVDataStruct *)XGI_GetTVPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
2914 } */
2915
2916 XGI_SetCRT1Timing_H(pVBInfo,HwDeviceExtension) ;
2917
2918 if ( pVBInfo->IF_DEF_CH7007 == 1 )
2919 {
2920 XGINew_SetReg1( pVBInfo->P3c4 , 0x2E , CH7007TV_TimingHPtr[ 0 ].data[ 8 ] ) ;
2921 XGINew_SetReg1( pVBInfo->P3c4 , 0x2F , CH7007TV_TimingHPtr[ 0 ].data[ 9 ] ) ;
2922 }
2923
2924 tempbx = 1 ;
2925
2926 if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
2927 {
2928 LCDPtr1 = ( XGI_LVDSCRT1VDataStruct * )XGI_GetLcdPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
2929 for( i = 0 ; i < 7 ; i++ )
2930 pVBInfo->TimingV[ 0 ].data[ i ] = LCDPtr1[ 0 ].Reg[ i ] ;
2931 }
2932
2933 if ( pVBInfo->IF_DEF_CH7007 == 1 )
2934 {
2935 if ( pVBInfo->VBInfo & SetCRT2ToTV )
2936 {
2937 CH7007TV_TimingVPtr = ( XGI_CH7007TV_TimingVStruct *)XGI_GetTVPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
2938
2939 for( i = 0 ; i < 7 ; i++ )
2940 pVBInfo->TimingV[ 0 ].data[ i ] = CH7007TV_TimingVPtr[ 0 ].data[ i ] ;
2941 }
2942 }
2943 /* if ( pVBInfo->IF_DEF_CH7017 == 1 )
2944 {
2945 if ( pVBInfo->VBInfo & SetCRT2ToTV )
2946 TVPtr = ( XGI330_CHTVDataStruct *)XGI_GetTVPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
2947 } */
2948
2949 XGI_SetCRT1Timing_V( ModeIdIndex , ModeNo , pVBInfo) ;
2950
2951 if ( pVBInfo->IF_DEF_CH7007 == 1 )
2952 {
2953 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x33 , ~0x01 , CH7007TV_TimingVPtr[ 0 ].data[ 7 ]&0x01 ) ;
2954 XGINew_SetReg1( pVBInfo->P3c4 , 0x34 , CH7007TV_TimingVPtr[ 0 ].data[8 ] ) ;
2955 XGINew_SetReg1( pVBInfo->P3c4 , 0x3F , CH7007TV_TimingVPtr[ 0 ].data[9 ] ) ;
2956
2957 }
2958 }
2959}
2960
2961
2962
2963/* --------------------------------------------------------------------- */
2964/* Function : XGI_SetLVDSRegs */
2965/* Input : */
2966/* Output : */
2967/* Description : */
2968/* --------------------------------------------------------------------- */
2969void XGI_SetLVDSRegs( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
2970{
2971 USHORT tempbx , tempax , tempcx , tempdx , push1 , push2 , modeflag ;
2972 unsigned long temp , temp1 , temp2 , temp3 , push3 ;
2973 XGI330_LCDDataDesStruct *LCDPtr = NULL ;
2974 XGI330_LCDDataDesStruct2 *LCDPtr1 = NULL ;
2975
2976 if ( ModeNo > 0x13 )
2977 modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
2978 else
2979 modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
2980
2981 if ( !( pVBInfo->SetFlag & Win9xDOSMode ) )
2982 {
2983 if ( ( pVBInfo->IF_DEF_CH7017 == 0 ) || ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) )
2984 {
2985 if ( pVBInfo->IF_DEF_OEMUtil == 1 )
2986 {
2987 tempbx = 8 ;
2988 LCDPtr = ( XGI330_LCDDataDesStruct * )XGI_GetLcdPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
2989 }
2990
2991 if ( ( pVBInfo->IF_DEF_OEMUtil == 0 ) || ( LCDPtr == 0 ) )
2992 {
2993 tempbx = 3 ;
2994 if ( pVBInfo->LCDInfo & EnableScalingLCD )
2995 LCDPtr1 = ( XGI330_LCDDataDesStruct2 * )XGI_GetLcdPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
2996 else
2997 LCDPtr = ( XGI330_LCDDataDesStruct * )XGI_GetLcdPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
2998 }
2999
3000 XGI_GetLCDSync( &tempax , &tempbx ,pVBInfo) ;
3001 push1 = tempbx ;
3002 push2 = tempax ;
3003
3004 /* GetLCDResInfo */
3005 if ( ( pVBInfo->LCDResInfo == Panel1024x768 ) || ( pVBInfo->LCDResInfo == Panel1024x768x75 ) )
3006 {
3007 tempax = 1024 ;
3008 tempbx = 768 ;
3009 }
3010 else if ( ( pVBInfo->LCDResInfo == Panel1280x1024 ) || ( pVBInfo->LCDResInfo == Panel1280x1024x75 ) )
3011 {
3012 tempax = 1280 ;
3013 tempbx = 1024 ;
3014 }
3015 else if ( pVBInfo->LCDResInfo == Panel1400x1050 )
3016 {
3017 tempax = 1400 ;
3018 tempbx = 1050 ;
3019 }
3020 else
3021 {
3022 tempax = 1600 ;
3023 tempbx = 1200 ;
3024 }
3025
3026 if ( pVBInfo->LCDInfo & SetLCDtoNonExpanding )
3027 {
3028 pVBInfo->HDE=tempax;
3029 pVBInfo->VDE=tempbx;
3030 pVBInfo->VGAHDE=tempax;
3031 pVBInfo->VGAVDE=tempbx;
3032 }
3033
3034 if ( ( pVBInfo->IF_DEF_ScaleLCD == 1 ) && ( pVBInfo->LCDInfo & EnableScalingLCD ) )
3035 {
3036 tempax=pVBInfo->HDE;
3037 tempbx=pVBInfo->VDE;
3038 }
3039
3040 tempax = pVBInfo->HT ;
3041
3042 if ( pVBInfo->LCDInfo & EnableScalingLCD )
3043 tempbx = LCDPtr1->LCDHDES ;
3044 else
3045 tempbx = LCDPtr->LCDHDES ;
3046
3047 tempcx = pVBInfo->HDE ;
3048 tempbx = tempbx & 0x0fff ;
3049 tempcx += tempbx ;
3050
3051 if ( tempcx >= tempax )
3052 tempcx -= tempax ;
3053
3054 XGINew_SetReg1( pVBInfo->Part1Port , 0x1A , tempbx & 0x07 ) ;
3055
3056 tempcx = tempcx >> 3 ;
3057 tempbx = tempbx >> 3 ;
3058
3059 XGINew_SetReg1( pVBInfo->Part1Port , 0x16 , ( USHORT )( tempbx & 0xff ) ) ;
3060 XGINew_SetReg1( pVBInfo->Part1Port , 0x17 , ( USHORT )( tempcx & 0xff ) ) ;
3061
3062 tempax = pVBInfo->HT ;
3063
3064 if ( pVBInfo->LCDInfo & EnableScalingLCD )
3065 tempbx = LCDPtr1->LCDHRS ;
3066 else
3067 tempbx = LCDPtr->LCDHRS ;
3068
3069 tempcx = push2 ;
3070
3071 if ( pVBInfo->LCDInfo & EnableScalingLCD )
3072 tempcx = LCDPtr1->LCDHSync ;
3073
3074 tempcx += tempbx ;
3075
3076 if ( tempcx >= tempax )
3077 tempcx -= tempax ;
3078
3079 tempax = tempbx & 0x07 ;
3080 tempax = tempax >> 5 ;
3081 tempcx = tempcx >> 3 ;
3082 tempbx = tempbx >> 3 ;
3083
3084 tempcx &= 0x1f ;
3085 tempax |= tempcx ;
3086
3087 XGINew_SetReg1( pVBInfo->Part1Port , 0x15 , tempax ) ;
3088 XGINew_SetReg1( pVBInfo->Part1Port , 0x14 , ( USHORT )( tempbx & 0xff ) ) ;
3089
3090 tempax = pVBInfo->VT ;
3091 if ( pVBInfo->LCDInfo & EnableScalingLCD )
3092 tempbx = LCDPtr1->LCDVDES ;
3093 else
3094 tempbx = LCDPtr->LCDVDES ;
3095 tempcx = pVBInfo->VDE ;
3096
3097 tempbx = tempbx & 0x0fff ;
3098 tempcx += tempbx ;
3099 if ( tempcx >= tempax )
3100 tempcx -= tempax ;
3101
3102 XGINew_SetReg1( pVBInfo->Part1Port , 0x1b , ( USHORT )( tempbx & 0xff ) ) ;
3103 XGINew_SetReg1( pVBInfo->Part1Port , 0x1c , ( USHORT )( tempcx & 0xff ) ) ;
3104
3105 tempbx = ( tempbx >> 8 ) & 0x07 ;
3106 tempcx = ( tempcx >> 8 ) & 0x07 ;
3107
3108 XGINew_SetReg1( pVBInfo->Part1Port , 0x1d , ( USHORT )( ( tempcx << 3 ) | tempbx ) ) ;
3109
3110 tempax = pVBInfo->VT ;
3111 if ( pVBInfo->LCDInfo & EnableScalingLCD )
3112 tempbx = LCDPtr1->LCDVRS ;
3113 else
3114 tempbx = LCDPtr->LCDVRS ;
3115
3116 /* tempbx = tempbx >> 4 ; */
3117 tempcx = push1 ;
3118
3119 if ( pVBInfo->LCDInfo & EnableScalingLCD )
3120 tempcx = LCDPtr1->LCDVSync ;
3121
3122 tempcx += tempbx ;
3123 if ( tempcx >= tempax )
3124 tempcx -= tempax ;
3125
3126 XGINew_SetReg1( pVBInfo->Part1Port , 0x18 , ( USHORT )( tempbx & 0xff ) ) ;
3127 XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x19 , ~0x0f , ( USHORT )( tempcx & 0x0f ) ) ;
3128
3129 tempax = ( ( tempbx >> 8 ) & 0x07 ) << 3 ;
3130
3131 tempbx = pVBInfo->VGAVDE ;
3132 if ( tempbx != pVBInfo->VDE )
3133 tempax |= 0x40 ;
3134
3135 if ( pVBInfo->LCDInfo & EnableLVDSDDA )
3136 tempax |= 0x40 ;
3137
3138 XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x1a , 0x07 , tempax ) ;
3139
3140 tempcx = pVBInfo->VGAVT ;
3141 tempbx = pVBInfo->VDE ;
3142 tempax = pVBInfo->VGAVDE ;
3143 tempcx -= tempax ;
3144
3145 temp = tempax ; /* 0430 ylshieh */
3146 temp1 = ( temp << 18 ) / tempbx ;
3147
3148 tempdx = ( USHORT )( ( temp << 18 ) % tempbx ) ;
3149
3150 if ( tempdx != 0 )
3151 temp1 += 1 ;
3152
3153 temp2 = temp1 ;
3154 push3 = temp2 ;
3155
3156 XGINew_SetReg1( pVBInfo->Part1Port , 0x37 , ( USHORT )( temp2 & 0xff ) ) ;
3157 XGINew_SetReg1( pVBInfo->Part1Port , 0x36 , ( USHORT )( ( temp2 >> 8 ) & 0xff ) ) ;
3158
3159 tempbx = ( USHORT )( temp2 >> 16 ) ;
3160 tempax = tempbx & 0x03 ;
3161
3162 tempbx = pVBInfo->VGAVDE ;
3163 if ( tempbx == pVBInfo->VDE )
3164 tempax |= 0x04 ;
3165
3166 XGINew_SetReg1( pVBInfo->Part1Port , 0x35 , tempax ) ;
3167
3168 if ( pVBInfo->VBType & VB_XGI301C )
3169 {
3170 temp2 = push3 ;
3171 XGINew_SetReg1( pVBInfo->Part4Port , 0x3c , ( USHORT )( temp2 & 0xff ) ) ;
3172 XGINew_SetReg1( pVBInfo->Part4Port , 0x3b , ( USHORT )( ( temp2 >> 8 ) & 0xff ) ) ;
3173 tempbx = ( USHORT )( temp2 >> 16 ) ;
3174 XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x3a , ~0xc0 , ( USHORT )( ( tempbx & 0xff ) << 6 ) ) ;
3175
3176 tempcx = pVBInfo->VGAVDE ;
3177 if ( tempcx == pVBInfo->VDE )
3178 XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x30 , ~0x0c , 0x00 ) ;
3179 else
3180 XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x30 , ~0x0c , 0x08 ) ;
3181 }
3182
3183 tempcx = pVBInfo->VGAHDE ;
3184 tempbx = pVBInfo->HDE ;
3185
3186 temp1 = tempcx << 16 ;
3187
3188 tempax = ( USHORT )( temp1 / tempbx ) ;
3189
3190 if ( ( tempbx & 0xffff ) == ( tempcx & 0xffff ) )
3191 tempax = 65535 ;
3192
3193 temp3 = tempax ;
3194 temp1 = pVBInfo->VGAHDE << 16 ;
3195
3196 temp1 /= temp3 ;
3197 temp3 = temp3 << 16 ;
3198 temp1 -= 1 ;
3199
3200 temp3 = ( temp3 & 0xffff0000 ) + ( temp1 & 0xffff ) ;
3201
3202 tempax = ( USHORT )( temp3 & 0xff ) ;
3203 XGINew_SetReg1( pVBInfo->Part1Port , 0x1f , tempax ) ;
3204
3205 temp1 = pVBInfo->VGAVDE << 18 ;
3206 temp1 = temp1 / push3 ;
3207 tempbx = ( USHORT )( temp1 & 0xffff ) ;
3208
3209 if ( pVBInfo->LCDResInfo == Panel1024x768 )
3210 tempbx -= 1 ;
3211
3212 tempax = ( ( tempbx >> 8 ) & 0xff ) << 3 ;
3213 tempax |= ( USHORT )( ( temp3 >> 8 ) & 0x07 ) ;
3214 XGINew_SetReg1( pVBInfo->Part1Port , 0x20 , ( USHORT )( tempax & 0xff ) ) ;
3215 XGINew_SetReg1( pVBInfo->Part1Port , 0x21 , ( USHORT )( tempbx & 0xff ) ) ;
3216
3217 temp3 = temp3 >> 16 ;
3218
3219 if ( modeflag & HalfDCLK )
3220 temp3 = temp3 >> 1 ;
3221
3222 XGINew_SetReg1(pVBInfo->Part1Port , 0x22 , ( USHORT )( ( temp3 >> 8 ) & 0xff ) ) ;
3223 XGINew_SetReg1(pVBInfo->Part1Port , 0x23 , ( USHORT )( temp3 & 0xff ) ) ;
3224 }
3225 }
3226}
3227
3228
3229/* --------------------------------------------------------------------- */
3230/* Function : XGI_SetCRT2ECLK */
3231/* Input : */
3232/* Output : */
3233/* Description : */
3234/* --------------------------------------------------------------------- */
3235void XGI_SetCRT2ECLK( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
3236{
3237 UCHAR di_0 , di_1 , tempal ;
3238 int i ;
3239
3240 tempal = XGI_GetVCLKPtr( RefreshRateTableIndex , ModeNo , ModeIdIndex, pVBInfo ) ;
3241 XGI_GetVCLKLen( tempal , &di_0 , &di_1, pVBInfo ) ;
3242 XGI_GetLCDVCLKPtr( &di_0 , &di_1, pVBInfo ) ;
3243
3244 for( i = 0 ; i < 4 ; i++ )
3245 {
3246 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x31 , ~0x30 , ( USHORT )( 0x10 * i ) ) ;
3247 if ( pVBInfo->IF_DEF_CH7007 == 1 )
3248 {
3249 XGINew_SetReg1( pVBInfo->P3c4 , 0x2b , di_0 ) ;
3250 XGINew_SetReg1( pVBInfo->P3c4 , 0x2c , di_1 ) ;
3251 }
3252 else if ( ( !( pVBInfo->VBInfo & SetCRT2ToLCDA ) ) && ( !( pVBInfo->VBInfo & SetInSlaveMode ) ) )
3253 {
3254 XGINew_SetReg1( pVBInfo->P3c4 , 0x2e , di_0 ) ;
3255 XGINew_SetReg1( pVBInfo->P3c4 , 0x2f , di_1 ) ;
3256 }
3257 else
3258 {
3259 XGINew_SetReg1( pVBInfo->P3c4 , 0x2b , di_0 ) ;
3260 XGINew_SetReg1( pVBInfo->P3c4 , 0x2c , di_1 ) ;
3261 }
3262 }
3263}
3264
3265
3266/* --------------------------------------------------------------------- */
3267/* Function : XGI_UpdateModeInfo */
3268/* Input : */
3269/* Output : */
3270/* Description : */
3271/* --------------------------------------------------------------------- */
3272void XGI_UpdateModeInfo( PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo )
3273{
3274 USHORT tempcl ,
3275 tempch ,
3276 temp ,
3277 tempbl ,
3278 tempax ;
3279
3280 if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
3281 {
3282 tempcl = 0 ;
3283 tempch = 0 ;
3284 temp = XGINew_GetReg1( pVBInfo->P3c4 , 0x01 ) ;
3285
3286 if ( !( temp & 0x20 ) )
3287 {
3288 temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x17 ) ;
3289 if ( temp & 0x80 )
3290 {
3291 if ( ( HwDeviceExtension->jChipType >= XG20 ) || ( HwDeviceExtension->jChipType >= XG40 ) )
3292 temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x53 ) ;
3293 else
3294 temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x63 ) ;
3295
3296 if ( !( temp & 0x40 ) )
3297 tempcl |= ActiveCRT1 ;
3298 }
3299 }
3300
3301 temp = XGINew_GetReg1( pVBInfo->Part1Port , 0x2e ) ;
3302 temp &= 0x0f ;
3303
3304 if ( !( temp == 0x08 ) )
3305 {
3306 tempax = XGINew_GetReg1( pVBInfo->Part1Port , 0x13 ) ; /* Check ChannelA by Part1_13 [2003/10/03] */
3307 if ( tempax & 0x04 )
3308 tempcl = tempcl | ActiveLCD ;
3309
3310 temp &= 0x05 ;
3311
3312 if ( !( tempcl & ActiveLCD ) )
3313 if ( temp == 0x01 )
3314 tempcl |= ActiveCRT2 ;
3315
3316 if ( temp == 0x04 )
3317 tempcl |= ActiveLCD ;
3318
3319 if ( temp == 0x05 )
3320 {
3321 temp = XGINew_GetReg1( pVBInfo->Part2Port , 0x00 ) ;
3322
3323 if( !( temp & 0x08 ) )
3324 tempch |= ActiveAVideo ;
3325
3326 if ( !( temp & 0x04 ) )
3327 tempch |= ActiveSVideo ;
3328
3329 if ( temp & 0x02 )
3330 tempch |= ActiveSCART ;
3331
3332 if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
3333 {
3334 if ( temp & 0x01 )
3335 tempch |= ActiveHiTV ;
3336 }
3337
3338 if ( pVBInfo->VBInfo & SetCRT2ToYPbPr )
3339 {
3340 temp = XGINew_GetReg1( pVBInfo->Part2Port , 0x4d ) ;
3341
3342 if ( temp & 0x10 )
3343 tempch |= ActiveYPbPr ;
3344 }
3345
3346 if ( tempch != 0 )
3347 tempcl |= ActiveTV ;
3348 }
3349 }
3350
3351 temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x3d ) ;
3352 if ( tempcl & ActiveLCD )
3353 {
3354 if ( ( pVBInfo->SetFlag & ReserveTVOption ) )
3355 {
3356 if ( temp & ActiveTV )
3357 tempcl |= ActiveTV ;
3358 }
3359 }
3360 temp = tempcl ;
3361 tempbl = ~ModeSwitchStatus ;
3362 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x3d , tempbl , temp ) ;
3363
3364 if ( !( pVBInfo->SetFlag & ReserveTVOption ) )
3365 XGINew_SetReg1( pVBInfo->P3d4 , 0x3e , tempch ) ;
3366 }
3367 else
3368 {
3369 return ;
3370 }
3371}
3372
3373
3374/* --------------------------------------------------------------------- */
3375/* Function : XGI_GetVGAType */
3376/* Input : */
3377/* Output : */
3378/* Description : */
3379/* --------------------------------------------------------------------- */
3380void XGI_GetVGAType( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
3381{
3382 /*
3383 if ( HwDeviceExtension->jChipType >= XG20 )
3384 {
3385 pVBInfo->Set_VGAType = XG20;
3386 }
3387 else if ( HwDeviceExtension->jChipType >= XG40 )
3388 {
3389 pVBInfo->Set_VGAType = VGA_XGI340 ;
3390 }
3391 */
3392 pVBInfo->Set_VGAType = HwDeviceExtension->jChipType;
3393}
3394
3395
3396/* --------------------------------------------------------------------- */
3397/* Function : XGI_GetVBType */
3398/* Input : */
3399/* Output : */
3400/* Description : */
3401/* --------------------------------------------------------------------- */
3402void XGI_GetVBType(PVB_DEVICE_INFO pVBInfo)
3403{
3404 USHORT flag , tempbx , tempah ;
3405
3406 if ( pVBInfo->IF_DEF_CH7007 == 1 )
3407 {
3408 pVBInfo->VBType = VB_CH7007 ;
3409 return;
3410 }
3411 if ( pVBInfo->IF_DEF_LVDS == 0 )
3412 {
3413 tempbx = VB_XGI302B ;
3414 flag = XGINew_GetReg1( pVBInfo->Part4Port , 0x00 ) ;
3415 if ( flag != 0x02 )
3416 {
3417 tempbx = VB_XGI301 ;
3418 flag = XGINew_GetReg1( pVBInfo->Part4Port , 0x01 ) ;
3419 if ( flag >= 0xB0 )
3420 {
3421 tempbx = VB_XGI301B ;
3422 if ( flag >= 0xC0 )
3423 {
3424 tempbx = VB_XGI301C ;
3425 if ( flag >= 0xD0 )
3426 {
3427 tempbx = VB_XGI301LV ;
3428 if ( flag >= 0xE0 )
3429 {
3430 tempbx = VB_XGI302LV ;
3431 tempah = XGINew_GetReg1( pVBInfo->Part4Port , 0x39 ) ;
3432 if ( tempah != 0xFF )
3433 tempbx = VB_XGI301C ;
3434 }
3435 }
3436 }
3437
3438 if ( tempbx & ( VB_XGI301B | VB_XGI302B ) )
3439 {
3440 flag = XGINew_GetReg1( pVBInfo->Part4Port , 0x23 ) ;
3441
3442 if ( !( flag & 0x02 ) )
3443 tempbx = tempbx | VB_NoLCD ;
3444 }
3445 }
3446 }
3447 pVBInfo->VBType = tempbx ;
3448 }
3449/*
3450 else if ( pVBInfo->IF_DEF_CH7017 == 1 )
3451 pVBInfo->VBType = VB_CH7017 ;
3452 else //LVDS
3453 pVBInfo->VBType = VB_LVDS_NS ;
3454*/
3455
3456}
3457
3458
3459/* --------------------------------------------------------------------- */
3460/* Function : XGI_GetVBInfo */
3461/* Input : */
3462/* Output : */
3463/* Description : */
3464/* --------------------------------------------------------------------- */
3465void XGI_GetVBInfo( USHORT ModeNo , USHORT ModeIdIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
3466{
3467 USHORT tempax ,
3468 push ,
3469 tempbx ,
3470 temp ,
3471 modeflag ;
3472
3473 if ( ModeNo <= 0x13 )
3474 {
3475 modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
3476 }
3477 else
3478 {
3479 modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
3480 }
3481
3482 pVBInfo->SetFlag = 0 ;
3483 pVBInfo->ModeType = modeflag & ModeInfoFlag ;
3484 tempbx = 0 ;
3485
3486 if ( pVBInfo->VBType & 0xFFFF )
3487 {
3488 temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x30 ) ; /* Check Display Device */
3489 tempbx = tempbx | temp ;
3490 temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x31 ) ;
3491 push = temp ;
3492 push = push << 8 ;
3493 tempax = temp << 8 ;
3494 tempbx = tempbx | tempax ;
3495 temp = ( SetCRT2ToDualEdge | SetCRT2ToYPbPr | SetCRT2ToLCDA | SetInSlaveMode | DisableCRT2Display ) ;
3496 temp = 0xFFFF ^ temp ;
3497 tempbx &= temp ;
3498
3499 temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) ;
3500
3501 if ( pVBInfo->IF_DEF_LCDA == 1 )
3502 {
3503
3504 if ( ( pVBInfo->Set_VGAType >= XG20 ) || ( pVBInfo->Set_VGAType >= XG40 ))
3505 {
3506 if ( pVBInfo->IF_DEF_LVDS == 0 )
3507 {
3508 /* if ( ( pVBInfo->VBType & VB_XGI302B ) || ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) || ( pVBInfo->VBType & VB_XGI301C ) ) */
3509 if ( pVBInfo->VBType & ( VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
3510 {
3511 if ( temp & EnableDualEdge )
3512 {
3513 tempbx |= SetCRT2ToDualEdge ;
3514
3515 if ( temp & SetToLCDA )
3516 tempbx |= SetCRT2ToLCDA ;
3517 }
3518 }
3519 }
3520 else if ( pVBInfo->IF_DEF_CH7017 == 1 )
3521 {
3522 if ( pVBInfo->VBType & VB_CH7017 )
3523 {
3524 if ( temp & EnableDualEdge )
3525 {
3526 tempbx |= SetCRT2ToDualEdge ;
3527
3528 if ( temp & SetToLCDA )
3529 tempbx |= SetCRT2ToLCDA ;
3530 }
3531 }
3532 }
3533 }
3534 }
3535
3536 if ( pVBInfo->IF_DEF_YPbPr == 1 )
3537 {
3538 if ( ( ( pVBInfo->IF_DEF_LVDS == 0 ) && ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) || ( pVBInfo->VBType & VB_XGI301C ) ) )
3539 || ( ( pVBInfo->IF_DEF_CH7017 == 1 ) && ( pVBInfo->VBType&VB_CH7017 ) ) || ( (pVBInfo->IF_DEF_CH7007 == 1) && (pVBInfo->VBType&VB_CH7007) ) ) /* [Billy] 07/05/04 */
3540 {
3541 if ( temp & SetYPbPr ) /* temp = CR38 */
3542 {
3543 if ( pVBInfo->IF_DEF_HiVision == 1 )
3544 {
3545 temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x35 ) ; /* shampoo add for new scratch */
3546 temp &= YPbPrMode ;
3547 tempbx |= SetCRT2ToHiVisionTV ;
3548
3549 if ( temp != YPbPrMode1080i ) {
3550 tempbx &= ( ~SetCRT2ToHiVisionTV ) ;
3551 tempbx |= SetCRT2ToYPbPr ; }
3552 }
3553
3554 /* tempbx |= SetCRT2ToYPbPr ; */
3555 }
3556 }
3557 }
3558
3559 tempax = push ; /* restore CR31 */
3560
3561 if ( pVBInfo->IF_DEF_LVDS == 0 )
3562 {
3563 if ( pVBInfo->IF_DEF_YPbPr == 1 )
3564 {
3565 if ( pVBInfo->IF_DEF_HiVision == 1 )
3566 temp = 0x09FC ;
3567 else
3568 temp = 0x097C ;
3569 }
3570 else
3571 {
3572 if ( pVBInfo->IF_DEF_HiVision == 1 )
3573 temp = 0x01FC ;
3574 else
3575 temp = 0x017C ;
3576 }
3577 }
3578 else /* 3nd party chip */
3579 {
3580 if ( pVBInfo->IF_DEF_CH7017 == 1 )
3581 temp = ( SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToLCDA ) ;
3582 else if ( pVBInfo->IF_DEF_CH7007 == 1 ) /* [Billy] 07/05/03 */
3583 {
3584 temp = SetCRT2ToTV ;
3585 }
3586 else
3587 temp = SetCRT2ToLCD ;
3588 }
3589
3590 if ( !( tempbx & temp ) )
3591 {
3592 tempax |= DisableCRT2Display ;
3593 tempbx = 0 ;
3594 }
3595
3596 if ( pVBInfo->IF_DEF_LCDA == 1 ) /* Select Display Device */
3597 {
3598 if ( !( pVBInfo->VBType & VB_NoLCD ) )
3599 {
3600 if ( tempbx & SetCRT2ToLCDA )
3601 {
3602 if ( tempbx & SetSimuScanMode )
3603 tempbx &= ( ~( SetCRT2ToLCD | SetCRT2ToRAMDAC | SwitchToCRT2 ) ) ;
3604 else
3605 tempbx &= ( ~( SetCRT2ToLCD | SetCRT2ToRAMDAC | SetCRT2ToTV | SwitchToCRT2 ) ) ;
3606 }
3607 }
3608 }
3609
3610 /* shampoo add */
3611 if ( !( tempbx & ( SwitchToCRT2 | SetSimuScanMode ) ) ) /* for driver abnormal */
3612 {
3613 if ( pVBInfo->IF_DEF_CRT2Monitor == 1 )
3614 {
3615 if ( tempbx & SetCRT2ToRAMDAC )
3616 {
3617 tempbx &= ( 0xFF00 | SetCRT2ToRAMDAC | SwitchToCRT2 | SetSimuScanMode ) ;
3618 tempbx &= ( 0x00FF | ( ~SetCRT2ToYPbPr ) ) ;
3619 }
3620 }
3621 else
3622 tempbx &= ( ~( SetCRT2ToRAMDAC | SetCRT2ToLCD | SetCRT2ToTV ) ) ;
3623 }
3624
3625 if ( !( pVBInfo->VBType & VB_NoLCD ) )
3626 {
3627 if ( tempbx & SetCRT2ToLCD )
3628 {
3629 tempbx &= ( 0xFF00 | SetCRT2ToLCD | SwitchToCRT2 | SetSimuScanMode ) ;
3630 tempbx &= ( 0x00FF | ( ~SetCRT2ToYPbPr ) ) ;
3631 }
3632 }
3633
3634 if ( tempbx & SetCRT2ToSCART )
3635 {
3636 tempbx &= ( 0xFF00 | SetCRT2ToSCART | SwitchToCRT2 | SetSimuScanMode ) ;
3637 tempbx &= ( 0x00FF | ( ~SetCRT2ToYPbPr ) ) ;
3638 }
3639
3640 if ( pVBInfo->IF_DEF_YPbPr == 1 )
3641 {
3642 if ( tempbx & SetCRT2ToYPbPr )
3643 tempbx &= ( 0xFF00 | SwitchToCRT2 | SetSimuScanMode ) ;
3644 }
3645
3646 if ( pVBInfo->IF_DEF_HiVision == 1 )
3647 {
3648 if ( tempbx & SetCRT2ToHiVisionTV )
3649 tempbx &= ( 0xFF00 | SetCRT2ToHiVisionTV | SwitchToCRT2 | SetSimuScanMode ) ;
3650 }
3651
3652 if ( tempax & DisableCRT2Display ) /* Set Display Device Info */
3653 {
3654 if ( !( tempbx & ( SwitchToCRT2 | SetSimuScanMode ) ) )
3655 tempbx = DisableCRT2Display ;
3656 }
3657
3658 if ( !( tempbx & DisableCRT2Display ) )
3659 {
3660 if ( ( !( tempbx & DriverMode ) ) || ( !( modeflag & CRT2Mode ) ) )
3661 {
3662 if ( pVBInfo->IF_DEF_LCDA == 1 )
3663 {
3664 if ( !( tempbx & SetCRT2ToLCDA ) )
3665 tempbx |= ( SetInSlaveMode | SetSimuScanMode ) ;
3666 }
3667
3668 if ( pVBInfo->IF_DEF_VideoCapture == 1 )
3669 {
3670 if ( ( ( HwDeviceExtension->jChipType == XG40 ) && ( pVBInfo->Set_VGAType == XG40 ) )
3671 || ( ( HwDeviceExtension->jChipType == XG41 ) && ( pVBInfo->Set_VGAType == XG41 ) )
3672 || ( ( HwDeviceExtension->jChipType == XG42 ) && ( pVBInfo->Set_VGAType == XG42 ) )
3673 || ( ( HwDeviceExtension->jChipType == XG45 ) && ( pVBInfo->Set_VGAType == XG45 ) ) )
3674 {
3675 if ( ModeNo <= 13 )
3676 {
3677 if ( !( tempbx & SetCRT2ToRAMDAC ) ) /*CRT2 not need to support*/
3678 {
3679 tempbx &= ( 0x00FF | ( ~SetInSlaveMode ) ) ;
3680 pVBInfo->SetFlag |= EnableVCMode ;
3681 }
3682 }
3683 }
3684 }
3685 }
3686
3687 /*LCD+TV can't support in slave mode (Force LCDA+TV->LCDB)*/
3688 if ( ( tempbx & SetInSlaveMode ) && ( tempbx & SetCRT2ToLCDA ) )
3689 {
3690 tempbx ^= ( SetCRT2ToLCD | SetCRT2ToLCDA | SetCRT2ToDualEdge ) ;
3691 pVBInfo->SetFlag |= ReserveTVOption ;
3692 }
3693 }
3694 }
3695
3696 pVBInfo->VBInfo = tempbx ;
3697}
3698
3699
3700/* --------------------------------------------------------------------- */
3701/* Function : XGI_GetTVInfo */
3702/* Input : */
3703/* Output : */
3704/* Description : */
3705/* --------------------------------------------------------------------- */
3706void XGI_GetTVInfo( USHORT ModeNo , USHORT ModeIdIndex ,PVB_DEVICE_INFO pVBInfo )
3707{
3708 USHORT temp ,
3709 tempbx = 0 ,
3710 resinfo = 0 ,
3711 modeflag ,
3712 index1 ;
3713
3714 tempbx = 0 ;
3715 resinfo = 0 ;
3716
3717 if ( pVBInfo->VBInfo & SetCRT2ToTV )
3718 {
3719 if ( ModeNo <= 0x13 )
3720 {
3721 modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; /* si+St_ModeFlag */
3722 resinfo = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ResInfo ; /* si+St_ResInfo */
3723 }
3724 else
3725 {
3726 modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
3727 resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ; /* si+Ext_ResInfo */
3728 }
3729
3730 if ( pVBInfo->VBInfo & SetCRT2ToTV )
3731 {
3732 temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x35 ) ;
3733 tempbx = temp;
3734 if ( tempbx & SetPALTV )
3735 {
3736 tempbx &= ( SetCHTVOverScan | SetPALMTV | SetPALNTV | SetPALTV ) ;
3737 if ( tempbx & SetPALMTV )
3738 tempbx &= ~SetPALTV ; /* set to NTSC if PAL-M */
3739 }
3740 else
3741 tempbx &= ( SetCHTVOverScan | SetNTSCJ | SetPALTV ) ;
3742/*
3743 if ( pVBInfo->IF_DEF_LVDS == 0 )
3744 {
3745 index1 = XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) ; //PAL-M/PAL-N Info
3746 temp2 = ( index1 & 0xC0 ) >> 5 ; //00:PAL, 01:PAL-M, 10:PAL-N
3747 tempbx |= temp2 ;
3748 if ( temp2 & 0x02 ) //PAL-M
3749 tempbx &= ( ~SetPALTV ) ;
3750 }
3751*/
3752 }
3753
3754 if ( pVBInfo->IF_DEF_CH7017 == 1 )
3755 {
3756 tempbx = XGINew_GetReg1( pVBInfo->P3d4 , 0x35 ) ;
3757
3758 if ( tempbx & TVOverScan )
3759 tempbx |= SetCHTVOverScan ;
3760 }
3761
3762 if ( pVBInfo->IF_DEF_CH7007 == 1 ) /* [Billy] 07/05/04 */
3763 {
3764 tempbx = XGINew_GetReg1( pVBInfo->P3d4 , 0x35 ) ;
3765
3766 if ( tempbx & TVOverScan )
3767 {
3768 tempbx |= SetCHTVOverScan ;
3769 }
3770 }
3771
3772
3773 if ( pVBInfo->IF_DEF_LVDS == 0 )
3774 {
3775 if ( pVBInfo->VBInfo & SetCRT2ToSCART )
3776 tempbx |= SetPALTV ;
3777 }
3778
3779 if ( pVBInfo->IF_DEF_YPbPr == 1 )
3780 {
3781 if ( pVBInfo->VBInfo & SetCRT2ToYPbPr )
3782 {
3783 index1 = XGINew_GetReg1( pVBInfo->P3d4 , 0x35 ) ;
3784 index1 &= YPbPrMode ;
3785
3786 if ( index1 == YPbPrMode525i )
3787 tempbx |= SetYPbPrMode525i ;
3788
3789 if ( index1 == YPbPrMode525p )
3790 tempbx = tempbx | SetYPbPrMode525p;
3791 if ( index1 == YPbPrMode750p)
3792 tempbx = tempbx | SetYPbPrMode750p;
3793 }
3794 }
3795
3796 if ( pVBInfo->IF_DEF_HiVision == 1 )
3797 {
3798 if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
3799 {
3800 tempbx = tempbx | SetYPbPrMode1080i | SetPALTV ;
3801 }
3802 }
3803
3804 if ( pVBInfo->IF_DEF_LVDS == 0 )
3805 { /* shampoo */
3806 if ( ( pVBInfo->VBInfo & SetInSlaveMode ) && ( !( pVBInfo->VBInfo & SetNotSimuMode ) ) )
3807 tempbx |= TVSimuMode ;
3808
3809 if ( !( tempbx & SetPALTV ) && ( modeflag > 13 ) && ( resinfo == 8 ) ) /* NTSC 1024x768, */
3810 tempbx |= NTSC1024x768 ;
3811
3812 tempbx |= RPLLDIV2XO ;
3813
3814 if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
3815 {
3816 if ( pVBInfo->VBInfo & SetInSlaveMode )
3817 tempbx &=( ~RPLLDIV2XO ) ;
3818 }
3819 else
3820 {
3821 if ( tempbx & ( SetYPbPrMode525p | SetYPbPrMode750p ) )
3822 tempbx &= ( ~RPLLDIV2XO ) ;
3823 else if ( !( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) )
3824 {
3825 if ( tempbx & TVSimuMode )
3826 tempbx &= ( ~RPLLDIV2XO ) ;
3827 }
3828 }
3829 }
3830 }
3831 pVBInfo->TVInfo = tempbx ;
3832}
3833
3834
3835/* --------------------------------------------------------------------- */
3836/* Function : XGI_GetLCDInfo */
3837/* Input : */
3838/* Output : */
3839/* Description : */
3840/* --------------------------------------------------------------------- */
3841BOOLEAN XGI_GetLCDInfo( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
3842{
3843 USHORT temp ,
3844 tempax ,
3845 tempbx ,
3846 modeflag ,
3847 resinfo = 0 ,
3848 LCDIdIndex ;
3849
3850 pVBInfo->LCDResInfo = 0 ;
3851 pVBInfo->LCDTypeInfo = 0 ;
3852 pVBInfo->LCDInfo = 0 ;
3853
3854 if ( ModeNo <= 0x13 )
3855 {
3856 modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; /* si+St_ModeFlag // */
3857 }
3858 else
3859 {
3860 modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
3861 resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ; /* si+Ext_ResInfo// */
3862 }
3863
3864 temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x36 ) ; /* Get LCD Res.Info */
3865 tempbx = temp & 0x0F ;
3866
3867 if ( tempbx == 0 )
3868 tempbx = Panel1024x768 ; /* default */
3869
3870 /* LCD75 [2003/8/22] Vicent */
3871 if ( ( tempbx == Panel1024x768 ) || ( tempbx == Panel1280x1024 ) )
3872 {
3873 if ( pVBInfo->VBInfo & DriverMode )
3874 {
3875 tempax = XGINew_GetReg1( pVBInfo->P3d4 , 0x33 ) ;
3876 if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
3877 tempax &= 0x0F ;
3878 else
3879 tempax = tempax >> 4 ;
3880
3881 if ( ( resinfo == 6 ) || ( resinfo == 9 ) )
3882 {
3883 if ( tempax >= 3 )
3884 tempbx |= PanelRef75Hz ;
3885 }
3886 else if ( ( resinfo == 7 ) || ( resinfo == 8 ) )
3887 {
3888 if ( tempax >= 4 )
3889 tempbx |= PanelRef75Hz ;
3890 }
3891 }
3892 }
3893
3894 pVBInfo->LCDResInfo = tempbx ;
3895
3896 /* End of LCD75 */
3897
3898 if( pVBInfo->IF_DEF_OEMUtil == 1 )
3899 {
3900 pVBInfo->LCDTypeInfo = ( temp & 0xf0 ) >> 4 ;
3901 }
3902
3903 if ( !( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) )
3904 {
3905 return 0;
3906 }
3907
3908 tempbx = 0 ;
3909
3910 temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x37 ) ;
3911
3912 temp &= ( ScalingLCD | LCDNonExpanding | LCDSyncBit | SetPWDEnable ) ;
3913
3914 if ( ( pVBInfo->IF_DEF_ScaleLCD == 1 ) && ( temp & LCDNonExpanding ) )
3915 temp &= ~EnableScalingLCD ;
3916
3917 tempbx |= temp ;
3918
3919 LCDIdIndex = XGI_GetLCDCapPtr1(pVBInfo) ;
3920
3921 tempax = pVBInfo->LCDCapList[ LCDIdIndex ].LCD_Capability ;
3922
3923 if ( pVBInfo->IF_DEF_LVDS == 0 ) /* shampoo */
3924 {
3925 if ( ( ( pVBInfo->VBType & VB_XGI302LV ) || ( pVBInfo->VBType & VB_XGI301C ) ) && ( tempax & LCDDualLink ) )
3926 {
3927 tempbx |= SetLCDDualLink ;
3928 }
3929 }
3930
3931 if ( pVBInfo->IF_DEF_CH7017 == 1 )
3932 {
3933 if ( tempax & LCDDualLink )
3934 {
3935 tempbx |= SetLCDDualLink ;
3936 }
3937 }
3938
3939 if ( pVBInfo->IF_DEF_LVDS == 0 )
3940 {
3941 if ( ( pVBInfo->LCDResInfo == Panel1400x1050 ) && ( pVBInfo->VBInfo & SetCRT2ToLCD ) && ( ModeNo > 0x13 ) && ( resinfo == 9 ) && ( !( tempbx & EnableScalingLCD ) ) )
3942 tempbx |= SetLCDtoNonExpanding ; /* set to center in 1280x1024 LCDB for Panel1400x1050 */
3943 }
3944
3945/*
3946 if ( tempax & LCDBToA )
3947 {
3948 tempbx |= SetLCDBToA ;
3949 }
3950*/
3951
3952 if ( pVBInfo->IF_DEF_ExpLink == 1 )
3953 {
3954 if ( modeflag & HalfDCLK )
3955 {
3956 /* if ( !( pVBInfo->LCDInfo&LCDNonExpanding ) ) */
3957 if ( !( tempbx & SetLCDtoNonExpanding ) )
3958 {
3959 tempbx |= EnableLVDSDDA ;
3960 }
3961 else
3962 {
3963 if ( ModeNo > 0x13 )
3964 {
3965 if ( pVBInfo->LCDResInfo == Panel1024x768 )
3966 {
3967 if ( resinfo == 4 )
3968 { /* 512x384 */
3969 tempbx |= EnableLVDSDDA ;
3970 }
3971 }
3972 }
3973 }
3974 }
3975 }
3976
3977 if ( pVBInfo->VBInfo & SetInSlaveMode )
3978 {
3979 if ( pVBInfo->VBInfo & SetNotSimuMode )
3980 {
3981 tempbx |= LCDVESATiming ;
3982 }
3983 }
3984 else
3985 {
3986 tempbx |= LCDVESATiming ;
3987 }
3988
3989 pVBInfo->LCDInfo = tempbx ;
3990
3991 if ( pVBInfo->IF_DEF_PWD == 1 )
3992 {
3993 if ( pVBInfo->LCDInfo & SetPWDEnable )
3994 {
3995 if ( ( pVBInfo->VBType & VB_XGI302LV ) || ( pVBInfo->VBType & VB_XGI301C ) )
3996 {
3997 if ( !( tempax & PWDEnable ) )
3998 {
3999 pVBInfo->LCDInfo &= ~SetPWDEnable ;
4000 }
4001 }
4002 }
4003 }
4004
4005 if ( pVBInfo->IF_DEF_LVDS == 0 )
4006 {
4007 if ( tempax & ( LockLCDBToA | StLCDBToA ) )
4008 {
4009 if ( pVBInfo->VBInfo & SetInSlaveMode )
4010 {
4011 if ( !( tempax & LockLCDBToA ) )
4012 {
4013 if ( ModeNo <= 0x13 )
4014 {
4015 pVBInfo->VBInfo &= ~( SetSimuScanMode | SetInSlaveMode | SetCRT2ToLCD ) ;
4016 pVBInfo->VBInfo |= SetCRT2ToLCDA | SetCRT2ToDualEdge ;
4017 }
4018 }
4019 }
4020 }
4021 }
4022
4023/*
4024 if ( pVBInfo->IF_DEF_LVDS == 0 )
4025 {
4026 if ( tempax & ( LockLCDBToA | StLCDBToA ) )
4027 {
4028 if ( pVBInfo->VBInfo & SetInSlaveMode )
4029 {
4030 if ( !( ( !( tempax & LockLCDBToA ) ) && ( ModeNo > 0x13 ) ) )
4031 {
4032 pVBInfo->VBInfo&=~(SetSimuScanMode|SetInSlaveMode|SetCRT2ToLCD);
4033 pVBInfo->VBInfo|=SetCRT2ToLCDA|SetCRT2ToDualEdge;
4034 }
4035 }
4036 }
4037 }
4038*/
4039
4040 return( 1 ) ;
4041}
4042
4043
4044/* --------------------------------------------------------------------- */
4045/* Function : XGI_SearchModeID */
4046/* Input : */
4047/* Output : */
4048/* Description : */
4049/* --------------------------------------------------------------------- */
4050BOOLEAN XGI_SearchModeID( USHORT ModeNo , USHORT *ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
4051{
4052
4053#ifdef TC
4054
4055 if ( ModeNo <= 5 )
4056 ModeNo |= 1 ;
4057
4058 if ( ModeNo <= 0x13 )
4059 {
4060 /* for (*ModeIdIndex=0;*ModeIdIndex<sizeof(pVBInfo->SModeIDTable)/sizeof(XGI_StStruct);(*ModeIdIndex)++) */
4061 for( *ModeIdIndex = 0 ; ; ( *ModeIdIndex )++ )
4062 {
4063 if ( pVBInfo->SModeIDTable[ *ModeIdIndex ].St_ModeID == ModeNo )
4064 break ;
4065 if ( pVBInfo->SModeIDTable[ *ModeIdIndex ].St_ModeID == 0xFF )
4066 return( FALSE ) ;
4067 }
4068
4069 VGA_INFO = ( PUCHAR )MK_FP( 0 , 0x489 ) ;
4070
4071 if ( ModeNo == 0x07 )
4072 {
4073 if ( ( *VGA_INFO & 0x10 ) != 0 )
4074 ( *ModeIdIndex )++ ; /* 400 lines */
4075 /* else 350 lines */
4076 }
4077
4078 if ( ModeNo <= 3 )
4079 {
4080 if ( ( *VGA_INFO & 0x80 ) == 0 )
4081 {
4082 ( *ModeIdIndex )++ ;
4083 if ( ( *VGA_INFO & 0x10 ) != 0 )
4084 ( *ModeIdIndex )++ ; /* 400 lines */
4085 /* else 350 lines */
4086 }
4087 /* else 200 lines */
4088 }
4089 }
4090 else
4091 {
4092 /* for (*ModeIdIndex=0;*ModeIdIndex<sizeof(pVBInfo->EModeIDTable)/sizeof(XGI_ExtStruct);(*ModeIdIndex)++) */
4093 for( *ModeIdIndex = 0 ; ; ( *ModeIdIndex )++ )
4094 {
4095 if ( pVBInfo->EModeIDTable[ *ModeIdIndex ].Ext_ModeID == ModeNo )
4096 break ;
4097 if ( pVBInfo->EModeIDTable[ *ModeIdIndex ].Ext_ModeID == 0xFF )
4098 return( FALSE ) ;
4099 }
4100 }
4101
4102
4103#endif
4104
4105#ifdef WIN2000
4106
4107 if ( ModeNo <= 5 )
4108 ModeNo |= 1 ;
4109 if ( ModeNo <= 0x13 )
4110 {
4111 /* for (*ModeIdIndex=0;*ModeIdIndex<sizeof(pVBInfo->SModeIDTable)/sizeof(XGI_StStruct);(*ModeIdIndex)++) */
4112 for( *ModeIdIndex = 0 ; ; ( *ModeIdIndex )++ )
4113 {
4114 if ( pVBInfo->SModeIDTable[ *ModeIdIndex ].St_ModeID == ModeNo )
4115 break ;
4116 if ( pVBInfo->SModeIDTable[ *ModeIdIndex ].St_ModeID == 0xFF )
4117 return( FALSE ) ;
4118 }
4119
4120 if ( ModeNo == 0x07 )
4121 ( *ModeIdIndex )++ ; /* 400 lines */
4122
4123 if ( ModeNo <=3 )
4124 ( *ModeIdIndex ) += 2 ; /* 400 lines */
4125 /* else 350 lines */
4126 }
4127 else
4128 {
4129 /* for (*ModeIdIndex=0;*ModeIdIndex<sizeof(pVBInfo->EModeIDTable)/sizeof(XGI_ExtStruct);(*ModeIdIndex)++) */
4130 for( *ModeIdIndex = 0 ; ; ( *ModeIdIndex )++ )
4131 {
4132 if ( pVBInfo->EModeIDTable[ *ModeIdIndex ].Ext_ModeID == ModeNo )
4133 break ;
4134 if ( pVBInfo->EModeIDTable[ *ModeIdIndex ].Ext_ModeID == 0xFF )
4135 return( FALSE ) ;
4136 }
4137 }
4138
4139#endif
4140
4141#ifdef LINUX /* chiawen for linux solution */
4142
4143 if ( ModeNo <= 5 )
4144 ModeNo |= 1 ;
4145 if ( ModeNo <= 0x13 )
4146 {
4147 /* for (*ModeIdIndex=0;*ModeIdIndex<sizeof(pVBInfo->SModeIDTable)/sizeof(XGI_StStruct);(*ModeIdIndex)++) */
4148 for( *ModeIdIndex = 0 ; ; ( *ModeIdIndex )++ )
4149 {
4150 if ( pVBInfo->SModeIDTable[ *ModeIdIndex ].St_ModeID == ModeNo )
4151 break ;
4152 if ( pVBInfo->SModeIDTable[ *ModeIdIndex ].St_ModeID == 0xFF )
4153 return( FALSE ) ;
4154 }
4155
4156 if ( ModeNo == 0x07 )
4157 ( *ModeIdIndex )++ ; /* 400 lines */
4158
4159 if ( ModeNo <= 3 )
4160 ( *ModeIdIndex ) += 2 ; /* 400 lines */
4161 /* else 350 lines */
4162 }
4163 else
4164 {
4165 /* for (*ModeIdIndex=0;*ModeIdIndex<sizeof(pVBInfo->EModeIDTable)/sizeof(XGI_ExtStruct);(*ModeIdIndex)++) */
4166 for( *ModeIdIndex = 0 ; ; ( *ModeIdIndex )++ )
4167 {
4168 if ( pVBInfo->EModeIDTable[ *ModeIdIndex ].Ext_ModeID == ModeNo )
4169 break ;
4170 if ( pVBInfo->EModeIDTable[ *ModeIdIndex ].Ext_ModeID == 0xFF )
4171 return( FALSE ) ;
4172 }
4173 }
4174
4175#endif
4176
4177 return( TRUE ) ;
4178}
4179
4180
4181
4182
4183/* win2000 MM adapter not support standard mode! */
4184
4185/* --------------------------------------------------------------------- */
4186/* Function : */
4187/* Input : */
4188/* Output : */
4189/* Description : */
4190/* --------------------------------------------------------------------- */
4191BOOLEAN XGINew_CheckMemorySize(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo)
4192{
4193 USHORT memorysize ,
4194 modeflag ,
4195 temp ,
4196 temp1 ,
4197 tmp ;
4198
4199/* if ( ( HwDeviceExtension->jChipType == XGI_650 ) ||
4200 ( HwDeviceExtension->jChipType == XGI_650M ) )
4201 {
4202 return( TRUE ) ;
4203 } */
4204
4205 if ( ModeNo <= 0x13 )
4206 {
4207 modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
4208 }
4209 else {
4210 modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
4211 }
4212
4213 /* ModeType = modeflag&ModeInfoFlag ; // Get mode type */
4214
4215 memorysize = modeflag & MemoryInfoFlag ;
4216 memorysize = memorysize > MemorySizeShift ;
4217 memorysize++ ; /* Get memory size */
4218
4219 temp = XGINew_GetReg1( pVBInfo->P3c4 , 0x14 ) ; /* Get DRAM Size */
4220 tmp = temp ;
4221
4222 if ( HwDeviceExtension->jChipType == XG40 )
4223 {
4224 temp = 1 << ( ( temp & 0x0F0 ) >> 4 ) ; /* memory size per channel SR14[7:4] */
4225 if ( ( tmp & 0x0c ) == 0x0C ) /* Qual channels */
4226 {
4227 temp <<= 2 ;
4228 }
4229 else if ( ( tmp & 0x0c ) == 0x08 ) /* Dual channels */
4230 {
4231 temp <<= 1 ;
4232 }
4233 }
4234 else if ( HwDeviceExtension->jChipType == XG42 )
4235 {
4236 temp = 1 << ( ( temp & 0x0F0 ) >> 4 ) ; /* memory size per channel SR14[7:4] */
4237 if ( ( tmp & 0x04 ) == 0x04 ) /* Dual channels */
4238 {
4239 temp <<= 1 ;
4240 }
4241 }
4242 else if ( HwDeviceExtension->jChipType == XG45 )
4243 {
4244 temp = 1 << ( ( temp & 0x0F0 ) >> 4 ) ; /* memory size per channel SR14[7:4] */
4245 if ( ( tmp & 0x0c ) == 0x0C ) /* Qual channels */
4246 {
4247 temp <<= 2 ;
4248 }
4249 else if ( ( tmp & 0x0c ) == 0x08 ) /* triple channels */
4250 {
4251 temp1 = temp ;
4252 temp <<= 1 ;
4253 temp += temp1 ;
4254 }
4255 else if ( ( tmp & 0x0c ) == 0x04 ) /* Dual channels */
4256 {
4257 temp <<= 1 ;
4258 }
4259 }
4260 if ( temp < memorysize )
4261 return( FALSE ) ;
4262 else
4263 return( TRUE ) ;
4264}
4265
4266
4267/* --------------------------------------------------------------------- */
4268/* Function : XGINew_IsLowResolution */
4269/* Input : */
4270/* Output : */
4271/* Description : */
4272/* --------------------------------------------------------------------- */
4273/*void XGINew_IsLowResolution( USHORT ModeNo , USHORT ModeIdIndex, BOOLEAN XGINew_CheckMemorySize(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo)
4274{
4275 USHORT data ;
4276 USHORT ModeFlag ;
4277
4278 data = XGINew_GetReg1( pVBInfo->P3c4 , 0x0F ) ;
4279 data &= 0x7F ;
4280 XGINew_SetReg1( pVBInfo->P3c4 , 0x0F , data ) ;
4281
4282 if ( ModeNo > 0x13 )
4283 {
4284 ModeFlag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
4285 if ( ( ModeFlag & HalfDCLK ) && ( ModeFlag & DoubleScanMode ) )
4286 {
4287 data = XGINew_GetReg1( pVBInfo->P3c4 , 0x0F ) ;
4288 data |= 0x80 ;
4289 XGINew_SetReg1( pVBInfo->P3c4 , 0x0F , data ) ;
4290 data = XGINew_GetReg1( pVBInfo->P3c4 , 0x01 ) ;
4291 data &= 0xF7 ;
4292 XGINew_SetReg1( pVBInfo->P3c4 , 0x01 , data ) ;
4293 }
4294 }
4295}
4296
4297*/
4298
4299/* --------------------------------------------------------------------- */
4300/* Function : XGI_DisplayOn */
4301/* Input : */
4302/* Output : */
4303/* Description : */
4304/* --------------------------------------------------------------------- */
4305void XGI_DisplayOn( PXGI_HW_DEVICE_INFO pXGIHWDE , PVB_DEVICE_INFO pVBInfo )
4306{
4307
4308 XGINew_SetRegANDOR(pVBInfo->P3c4,0x01,0xDF,0x00);
4309 if ( pXGIHWDE->jChipType == XG21 )
4310 {
4311 if ( pVBInfo->IF_DEF_LVDS == 1 )
4312 {
4313 if (!(XGI_XG21GetPSCValue( pVBInfo )&0x1))
4314 {
4315 XGI_XG21BLSignalVDD( 0x01 , 0x01, pVBInfo ) ; /* LVDS VDD on */
4316 XGI_XG21SetPanelDelay( 2,pVBInfo ) ;
4317 }
4318 if (!(XGI_XG21GetPSCValue( pVBInfo )&0x20))
4319 {
4320 XGI_XG21BLSignalVDD( 0x20 , 0x20, pVBInfo ) ; /* LVDS signal on */
4321 }
4322 XGI_XG21SetPanelDelay( 3,pVBInfo ) ;
4323 XGI_XG21BLSignalVDD( 0x02 , 0x02, pVBInfo ) ; /* LVDS backlight on */
4324 }
4325 else
4326 {
4327 XGI_XG21BLSignalVDD( 0x20 , 0x20, pVBInfo ) ; /* DVO/DVI signal on */
4328 }
4329
4330 }
4331
4332 if (pVBInfo->IF_DEF_CH7007 == 1) /* [Billy] 07/05/23 For CH7007 */
4333 {
4334#ifdef WIN2000
4335 if ( IsCH7007TVMode( pVBInfo ) )
4336 {
4337 TurnOnCH7007(pXGIHWDE->pDevice) ; /* 07/05/28 */
4338 }
4339#endif
4340
4341 }
4342
4343
4344 if ( pXGIHWDE->jChipType == XG27 )
4345 {
4346 if ( pVBInfo->IF_DEF_LVDS == 1 )
4347 {
4348 if (!(XGI_XG27GetPSCValue( pVBInfo )&0x1))
4349 {
4350 XGI_XG27BLSignalVDD( 0x01 , 0x01, pVBInfo ) ; /* LVDS VDD on */
4351 XGI_XG21SetPanelDelay( 2,pVBInfo ) ;
4352 }
4353 if (!(XGI_XG27GetPSCValue( pVBInfo )&0x20))
4354 {
4355 XGI_XG27BLSignalVDD( 0x20 , 0x20, pVBInfo ) ; /* LVDS signal on */
4356 }
4357 XGI_XG21SetPanelDelay( 3,pVBInfo ) ;
4358 XGI_XG27BLSignalVDD( 0x02 , 0x02, pVBInfo ) ; /* LVDS backlight on */
4359 }
4360 else
4361 {
4362 XGI_XG27BLSignalVDD( 0x20 , 0x20, pVBInfo ) ; /* DVO/DVI signal on */
4363 }
4364
4365 }
4366}
4367
4368
4369/* --------------------------------------------------------------------- */
4370/* Function : XGI_DisplayOff */
4371/* Input : */
4372/* Output : */
4373/* Description : */
4374/* --------------------------------------------------------------------- */
4375void XGI_DisplayOff( PXGI_HW_DEVICE_INFO pXGIHWDE , PVB_DEVICE_INFO pVBInfo )
4376{
4377
4378 if ( pXGIHWDE->jChipType == XG21 )
4379 {
4380 if ( pVBInfo->IF_DEF_LVDS == 1 )
4381 {
4382 XGI_XG21BLSignalVDD( 0x02 , 0x00, pVBInfo ) ; /* LVDS backlight off */
4383 XGI_XG21SetPanelDelay( 3,pVBInfo ) ;
4384 }
4385 else
4386 {
4387 XGI_XG21BLSignalVDD( 0x20 , 0x00, pVBInfo ) ; /* DVO/DVI signal off */
4388 }
4389 }
4390
4391 if (pVBInfo->IF_DEF_CH7007 == 1) /*[Billy] 07/05/23 For CH7007 */
4392 {
4393 /* if( IsCH7007TVMode( pVBInfo ) == 0 ) */
4394 {
4395#ifdef WIN2000
4396 TurnOffCH7007(pXGIHWDE->pDevice) ; /* 07/05/28 */
4397#endif
4398 }
4399 }
4400
4401
4402 if ( pXGIHWDE->jChipType == XG27 )
4403 {
4404 if ((XGI_XG27GetPSCValue( pVBInfo )&0x2))
4405 {
4406 XGI_XG27BLSignalVDD( 0x02 , 0x00, pVBInfo ) ; /* LVDS backlight off */
4407 XGI_XG21SetPanelDelay( 3,pVBInfo ) ;
4408 }
4409
4410 if ( pVBInfo->IF_DEF_LVDS == 0 )
4411 {
4412 XGI_XG27BLSignalVDD( 0x20 , 0x00, pVBInfo ) ; /* DVO/DVI signal off */
4413 }
4414 }
4415
4416 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x01 , 0xDF , 0x20 ) ;
4417}
4418
4419
4420/* --------------------------------------------------------------------- */
4421/* Function : XGI_WaitDisply */
4422/* Input : */
4423/* Output : */
4424/* Description : chiawen for sensecrt1 */
4425/* --------------------------------------------------------------------- */
4426void XGI_WaitDisply( PVB_DEVICE_INFO pVBInfo )
4427{
4428 while( ( XGINew_GetReg2( pVBInfo->P3da ) & 0x01 ) )
4429 break ;
4430
4431 while( !( XGINew_GetReg2( pVBInfo->P3da ) & 0x01 ) )
4432 break ;
4433}
4434
4435/* --------------------------------------------------------------------- */
4436/* Function : XGI_SenseCRT1 */
4437/* Input : */
4438/* Output : */
4439/* Description : */
4440/* --------------------------------------------------------------------- */
4441
4442void XGI_SenseCRT1( PVB_DEVICE_INFO pVBInfo )
4443{
4444 UCHAR CRTCData[ 17 ] = { 0x5F , 0x4F , 0x50 , 0x82 , 0x55 , 0x81 ,
4445 0x0B , 0x3E , 0xE9 , 0x0B , 0xDF , 0xE7 ,
4446 0x04 , 0x00 , 0x00 , 0x05 , 0x00 } ;
4447
4448 UCHAR SR01 = 0 , SR1F = 0 , SR07 = 0 , SR06 = 0 ;
4449
4450 UCHAR CR17 , CR63 , SR31 ;
4451 USHORT temp ;
4452 UCHAR DAC_TEST_PARMS[ 3 ] = { 0x0F , 0x0F , 0x0F } ;
4453
4454 int i ;
4455 XGINew_SetReg1( pVBInfo->P3c4 , 0x05 , 0x86 ) ;
4456
4457 /* [2004/05/06] Vicent to fix XG42 single LCD sense to CRT+LCD */
4458 XGINew_SetReg1( pVBInfo->P3d4 , 0x57 , 0x4A ) ;
4459 XGINew_SetReg1( pVBInfo->P3d4 , 0x53 , ( UCHAR )( XGINew_GetReg1( pVBInfo->P3d4 , 0x53 ) | 0x02 ) ) ;
4460
4461 SR31 = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x31 ) ;
4462 CR63 = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x63 ) ;
4463 SR01 = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x01 ) ;
4464
4465 XGINew_SetReg1( pVBInfo->P3c4 , 0x01 , ( UCHAR )( SR01 & 0xDF ) ) ;
4466 XGINew_SetReg1( pVBInfo->P3d4 , 0x63 , ( UCHAR )( CR63 & 0xBF ) ) ;
4467
4468 CR17 = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x17 ) ;
4469 XGINew_SetReg1( pVBInfo->P3d4 , 0x17 , ( UCHAR )( CR17 | 0x80 ) ) ;
4470
4471 SR1F = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x1F ) ;
4472 XGINew_SetReg1( pVBInfo->P3c4 , 0x1F , ( UCHAR )( SR1F | 0x04 ) ) ;
4473
4474 SR07 = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x07 ) ;
4475 XGINew_SetReg1( pVBInfo->P3c4 , 0x07 , ( UCHAR )( SR07 & 0xFB ) ) ;
4476 SR06 = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x06 ) ;
4477 XGINew_SetReg1( pVBInfo->P3c4 , 0x06 , ( UCHAR )( SR06 & 0xC3 ) ) ;
4478
4479 XGINew_SetReg1( pVBInfo->P3d4 , 0x11 , 0x00 ) ;
4480
4481 for( i = 0 ; i < 8 ; i++ )
4482 XGINew_SetReg1( pVBInfo->P3d4 , ( USHORT )i , CRTCData[ i ] ) ;
4483
4484 for( i = 8 ; i < 11 ; i++ )
4485 XGINew_SetReg1( pVBInfo->P3d4 , ( USHORT )( i + 8 ) , CRTCData[ i ] ) ;
4486
4487 for( i = 11 ; i < 13 ; i++ )
4488 XGINew_SetReg1( pVBInfo->P3d4 , ( USHORT )( i + 4 ) , CRTCData[ i ] ) ;
4489
4490 for( i = 13 ; i < 16 ; i++ )
4491 XGINew_SetReg1( pVBInfo->P3c4 , ( USHORT )( i - 3 ) , CRTCData[ i ] ) ;
4492
4493 XGINew_SetReg1( pVBInfo->P3c4 , 0x0E , ( UCHAR )( CRTCData[ 16 ] & 0xE0 ) ) ;
4494
4495 XGINew_SetReg1( pVBInfo->P3c4 , 0x31 , 0x00 ) ;
4496 XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , 0x1B ) ;
4497 XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , 0xE1 ) ;
4498
4499 XGINew_SetReg3( pVBInfo->P3c8 , 0x00 ) ;
4500
4501 for( i = 0 ; i < 256 ; i++ )
4502 {
4503 XGINew_SetReg3( ( pVBInfo->P3c8 + 1 ) , ( UCHAR )DAC_TEST_PARMS[ 0 ] ) ;
4504 XGINew_SetReg3( ( pVBInfo->P3c8 + 1 ) , ( UCHAR )DAC_TEST_PARMS[ 1 ] ) ;
4505 XGINew_SetReg3( ( pVBInfo->P3c8 + 1 ) , ( UCHAR )DAC_TEST_PARMS[ 2 ] ) ;
4506 }
4507
4508 XGI_VBLongWait( pVBInfo ) ;
4509 XGI_VBLongWait( pVBInfo ) ;
4510 XGI_VBLongWait( pVBInfo ) ;
4511
4512 XGINew_LCD_Wait_Time( 0x01 , pVBInfo ) ;
4513
4514 XGI_WaitDisply( pVBInfo ) ;
4515 temp = XGINew_GetReg2( pVBInfo->P3c2 ) ;
4516
4517 if( temp & 0x10 )
4518 {
4519 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , 0xDF , 0x20 ) ;
4520 }
4521 else
4522 {
4523 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , 0xDF , 0x00 ) ;
4524 }
4525
4526 /* alan, avoid display something, set BLACK DAC if not restore DAC */
4527 XGINew_SetReg3( pVBInfo->P3c8 , 0x00 ) ;
4528
4529 for( i = 0 ; i < 256 ; i++ )
4530 {
4531 XGINew_SetReg3( ( pVBInfo->P3c8 + 1 ) , 0 ) ;
4532 XGINew_SetReg3( ( pVBInfo->P3c8 + 1 ) , 0 ) ;
4533 XGINew_SetReg3( ( pVBInfo->P3c8 + 1 ) , 0 ) ;
4534 }
4535
4536 XGINew_SetReg1( pVBInfo->P3c4 , 0x01 , SR01 ) ;
4537 XGINew_SetReg1( pVBInfo->P3d4 , 0x63 , CR63 ) ;
4538 XGINew_SetReg1( pVBInfo->P3c4 , 0x31 , SR31 ) ;
4539
4540 /* [2004/05/11] Vicent */
4541 XGINew_SetReg1( pVBInfo->P3d4 , 0x53 , ( UCHAR )( XGINew_GetReg1( pVBInfo->P3d4 , 0x53 ) & 0xFD ) ) ;
4542 XGINew_SetReg1( pVBInfo->P3c4 , 0x1F , ( UCHAR ) SR1F ) ;
4543}
4544
4545
4546
4547
4548
4549#ifdef TC
4550/* --------------------------------------------------------------------- */
4551/* Function : INT1AReturnCode */
4552/* Input : */
4553/* Output : */
4554/* Description : */
4555/* --------------------------------------------------------------------- */
4556int INT1AReturnCode( union REGS regs )
4557{
4558 if ( regs.x.cflag )
4559 {
4560 /* printf( "Error to find pci device!\n" ) ; */
4561 return( 1 ) ;
4562 }
4563
4564 switch(regs.h.ah)
4565 {
4566 case 0: return 0;
4567 break ;
4568 case 0x81:
4569 printf( "Function not support\n" ) ;
4570 break ;
4571 case 0x83:
4572 printf( "bad vendor id\n" ) ;
4573 break ;
4574 case 0x86:
4575 printf( "device not found\n" ) ;
4576 break ;
4577 case 0x87:
4578 printf( "bad register number\n" ) ;
4579 break ;
4580 case 0x88:
4581 printf( "set failed\n" ) ;
4582 break ;
4583 case 0x89:
4584 printf( "buffer too small" ) ;
4585 break ;
4586 default:
4587 break ;
4588 }
4589 return( 1 ) ;
4590}
4591
4592
4593/* --------------------------------------------------------------------- */
4594/* Function : FindPCIIOBase */
4595/* Input : */
4596/* Output : */
4597/* Description : */
4598/* --------------------------------------------------------------------- */
4599unsigned FindPCIIOBase( unsigned index , unsigned deviceid )
4600{
4601 union REGS regs ;
4602
4603 regs.h.ah = 0xb1 ; /* PCI_FUNCTION_ID */
4604 regs.h.al = 0x02 ; /* FIND_PCI_DEVICE */
4605 regs.x.cx = deviceid ;
4606 regs.x.dx = 0x1039 ;
4607 regs.x.si = index ; /* find n-th device */
4608
4609 int86( 0x1A , &regs , &regs ) ;
4610
4611 if ( INT1AReturnCode( regs ) != 0 )
4612 return( 0 ) ;
4613
4614 /* regs.h.bh bus number */
4615 /* regs.h.bl device number */
4616 regs.h.ah = 0xb1 ; /* PCI_FUNCTION_ID */
4617 regs.h.al = 0x09 ; /* READ_CONFIG_WORD */
4618 regs.x.cx = deviceid ;
4619 regs.x.dx = 0x1039 ;
4620 regs.x.di = 0x18 ; /* register number */
4621 int86( 0x1A , &regs , &regs ) ;
4622
4623 if ( INT1AReturnCode( regs ) != 0 )
4624 return( 0 ) ;
4625
4626 return( regs.x.cx ) ;
4627}
4628
4629#endif
4630
4631
4632
4633#ifdef TC
4634/* --------------------------------------------------------------------- */
4635/* Function : main */
4636/* Input : */
4637/* Output : */
4638/* Description : */
4639/* --------------------------------------------------------------------- */
4640void main(int argc, char *argv[])
4641{
4642 XGI_HW_DEVICE_INFO HwDeviceExtension ;
4643 USHORT temp ;
4644 USHORT ModeNo ;
4645
4646 /* HwDeviceExtension.pjVirtualRomBase =(PUCHAR) MK_FP(0xC000,0); */
4647 /* HwDeviceExtension.pjVideoMemoryAddress = (PUCHAR)MK_FP(0xA000,0); */
4648
4649
4650 HwDeviceExtension.pjIOAddress = ( FindPCIIOBase( 0 ,0x6300 ) & 0xFF80 ) + 0x30 ;
4651 HwDeviceExtension.jChipType = XGI_340 ;
4652
4653
4654
4655 /* HwDeviceExtension.pjIOAddress = ( FindPCIIOBase( 0 , 0x5315 ) & 0xFF80 ) + 0x30 ; */
4656
4657 HwDeviceExtension.pjIOAddress = ( FindPCIIOBase( 0 , 0x330 ) & 0xFF80 ) + 0x30 ;
4658 HwDeviceExtension.jChipType = XGI_340 ;
4659
4660
4661 HwDeviceExtension.ujVBChipID = VB_CHIP_301 ;
4662 StrCpy(HwDeviceExtension.szVBIOSVer , "0.84" ) ;
4663 HwDeviceExtension.bSkipDramSizing = FALSE ;
4664 HwDeviceExtension.ulVideoMemorySize = 0 ;
4665
4666 if ( argc == 2 )
4667 {
4668 ModeNo = atoi( argv[ 1 ] ) ;
4669 }
4670 else
4671 {
4672 ModeNo = 0x2e ;
4673 /* ModeNo = 0x37 ; 1024x768x 4bpp */
4674 /* ModeNo = 0x38 ; 1024x768x 8bpp */
4675 /* ModeNo = 0x4A ; 1024x768x 16bpp */
4676 /* ModeNo = 0x47 ; 800x600x 16bpp */
4677 }
4678
4679 /* XGIInitNew( &HwDeviceExtension ) ; */
4680 XGISetModeNew( &HwDeviceExtension , ModeNo ) ;
4681}
4682#endif
4683
4684
4685/* --------------------------------------------------------------------- */
4686/* Function : XGI_WaitDisplay */
4687/* Input : */
4688/* Output : */
4689/* Description : */
4690/* --------------------------------------------------------------------- */
4691void XGI_WaitDisplay( PVB_DEVICE_INFO pVBInfo )
4692{
4693 while( !( XGINew_GetReg2( pVBInfo->P3da ) & 0x01 ) ) ;
4694
4695 while( XGINew_GetReg2( pVBInfo->P3da ) & 0x01 ) ;
4696}
4697
4698
4699
4700
4701/* --------------------------------------------------------------------- */
4702/* Function : XGI_SetCRT2Group301 */
4703/* Input : */
4704/* Output : */
4705/* Description : */
4706/* --------------------------------------------------------------------- */
4707BOOLEAN XGI_SetCRT2Group301( USHORT ModeNo , PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
4708{
4709 USHORT tempbx ,
4710 ModeIdIndex ,
4711 RefreshRateTableIndex ;
4712
4713 tempbx=pVBInfo->VBInfo ;
4714 pVBInfo->SetFlag |= ProgrammingCRT2 ;
4715 XGI_SearchModeID( ModeNo , &ModeIdIndex, pVBInfo ) ;
4716 pVBInfo->SelectCRT2Rate = 4 ;
4717 RefreshRateTableIndex = XGI_GetRatePtrCRT2( HwDeviceExtension, ModeNo , ModeIdIndex, pVBInfo ) ;
4718 XGI_SaveCRT2Info( ModeNo, pVBInfo ) ;
4719 XGI_GetCRT2ResInfo( ModeNo , ModeIdIndex, pVBInfo) ;
4720 XGI_GetCRT2Data( ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
4721 XGI_PreSetGroup1( ModeNo , ModeIdIndex , HwDeviceExtension , RefreshRateTableIndex, pVBInfo ) ;
4722 XGI_SetGroup1( ModeNo , ModeIdIndex , HwDeviceExtension , RefreshRateTableIndex, pVBInfo ) ;
4723 XGI_SetLockRegs( ModeNo , ModeIdIndex , HwDeviceExtension , RefreshRateTableIndex, pVBInfo ) ;
4724 XGI_SetGroup2( ModeNo , ModeIdIndex , RefreshRateTableIndex , HwDeviceExtension, pVBInfo ) ;
4725 XGI_SetLCDRegs(ModeNo , ModeIdIndex , HwDeviceExtension , RefreshRateTableIndex, pVBInfo ) ;
4726 XGI_SetTap4Regs(pVBInfo) ;
4727 XGI_SetGroup3(ModeNo, ModeIdIndex, pVBInfo);
4728 XGI_SetGroup4( ModeNo , ModeIdIndex , RefreshRateTableIndex , HwDeviceExtension, pVBInfo ) ;
4729 XGI_SetCRT2VCLK( ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
4730 XGI_SetGroup5( ModeNo , ModeIdIndex, pVBInfo) ;
4731 XGI_AutoThreshold( pVBInfo) ;
4732 return 1 ;
4733}
4734
4735
4736/* --------------------------------------------------------------------- */
4737/* Function : XGI_AutoThreshold */
4738/* Input : */
4739/* Output : */
4740/* Description : */
4741/* --------------------------------------------------------------------- */
4742void XGI_AutoThreshold( PVB_DEVICE_INFO pVBInfo )
4743{
4744 if ( !( pVBInfo->SetFlag & Win9xDOSMode ) )
4745 XGINew_SetRegOR( pVBInfo->Part1Port , 0x01 , 0x40 ) ;
4746}
4747
4748
4749/* --------------------------------------------------------------------- */
4750/* Function : XGI_SaveCRT2Info */
4751/* Input : */
4752/* Output : */
4753/* Description : */
4754/* --------------------------------------------------------------------- */
4755void XGI_SaveCRT2Info( USHORT ModeNo , PVB_DEVICE_INFO pVBInfo)
4756{
4757 USHORT temp1 ,
4758 temp2 ;
4759
4760 XGINew_SetReg1( pVBInfo->P3d4 , 0x34 , ModeNo ) ; /* reserve CR34 for CRT1 Mode No */
4761 temp1 = ( pVBInfo->VBInfo&SetInSlaveMode ) >> 8 ;
4762 temp2 = ~( SetInSlaveMode >> 8 ) ;
4763 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x31 , temp2 , temp1 ) ;
4764}
4765
4766
4767/* --------------------------------------------------------------------- */
4768/* Function : XGI_GetCRT2ResInfo */
4769/* Input : */
4770/* Output : */
4771/* Description : */
4772/* --------------------------------------------------------------------- */
4773void XGI_GetCRT2ResInfo( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
4774{
4775 USHORT xres ,
4776 yres ,
4777 modeflag ,
4778 resindex ;
4779
4780 resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo) ;
4781 if ( ModeNo <= 0x13 )
4782 {
4783 xres = pVBInfo->StResInfo[ resindex ].HTotal ;
4784 yres = pVBInfo->StResInfo[ resindex ].VTotal ;
4785 /* modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; si+St_ResInfo */
4786 }
4787 else
4788 {
4789 xres = pVBInfo->ModeResInfo[ resindex ].HTotal ; /* xres->ax */
4790 yres = pVBInfo->ModeResInfo[ resindex ].VTotal ; /* yres->bx */
4791 modeflag = pVBInfo->EModeIDTable[ ModeIdIndex].Ext_ModeFlag ; /* si+St_ModeFlag */
4792
4793/* if ( pVBInfo->IF_DEF_FSTN )
4794 {
4795 xres *= 2 ;
4796 yres *= 2 ;
4797 }
4798 else
4799 {
4800*/
4801 if ( modeflag & HalfDCLK )
4802 xres *= 2;
4803
4804 if ( modeflag & DoubleScanMode )
4805 yres *= 2 ;
4806/* } */
4807 }
4808
4809 if ( pVBInfo->VBInfo & SetCRT2ToLCD )
4810 {
4811 if ( pVBInfo->IF_DEF_LVDS == 0 )
4812 {
4813 if ( pVBInfo->LCDResInfo == Panel1600x1200 )
4814 {
4815 if ( !( pVBInfo->LCDInfo & LCDVESATiming ) )
4816 {
4817 if ( yres == 1024 )
4818 yres = 1056 ;
4819 }
4820 }
4821
4822 if ( pVBInfo->LCDResInfo == Panel1280x1024 )
4823 {
4824 if ( yres == 400 )
4825 yres = 405 ;
4826 else if ( yres == 350 )
4827 yres = 360 ;
4828
4829 if ( pVBInfo->LCDInfo & LCDVESATiming )
4830 {
4831 if ( yres == 360 )
4832 yres = 375 ;
4833 }
4834 }
4835
4836 if ( pVBInfo->LCDResInfo == Panel1024x768 )
4837 {
4838 if ( !( pVBInfo->LCDInfo & LCDVESATiming ) )
4839 {
4840 if ( !( pVBInfo->LCDInfo & LCDNonExpanding ) )
4841 {
4842 if ( yres == 350 )
4843 yres = 357 ;
4844 else if ( yres == 400 )
4845 yres = 420 ;
4846 else if ( yres == 480 )
4847 yres = 525 ;
4848 }
4849 }
4850 }
4851 }
4852
4853 if ( xres == 720 )
4854 xres = 640 ;
4855 }
4856
4857 pVBInfo->VGAHDE = xres ;
4858 pVBInfo->HDE = xres ;
4859 pVBInfo->VGAVDE = yres ;
4860 pVBInfo->VDE = yres ;
4861}
4862
4863
4864/* --------------------------------------------------------------------- */
4865/* Function : XGI_IsLCDDualLink */
4866/* Input : */
4867/* Output : */
4868/* Description : */
4869/* --------------------------------------------------------------------- */
4870BOOLEAN XGI_IsLCDDualLink( PVB_DEVICE_INFO pVBInfo )
4871{
4872
4873 if ( ( ( ( pVBInfo->VBInfo & SetCRT2ToLCD ) | SetCRT2ToLCDA ) ) && ( pVBInfo->LCDInfo & SetLCDDualLink ) ) /* shampoo0129 */
4874 return ( 1 ) ;
4875
4876 return( 0 ) ;
4877}
4878
4879
4880/* --------------------------------------------------------------------- */
4881/* Function : XGI_GetCRT2Data */
4882/* Input : */
4883/* Output : */
4884/* Description : */
4885/* --------------------------------------------------------------------- */
4886void XGI_GetCRT2Data( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
4887{
4888 USHORT tempax = 0,
4889 tempbx ,
4890 modeflag ,
4891 resinfo ;
4892
4893 XGI_LCDDataStruct *LCDPtr = NULL ;
4894 XGI_TVDataStruct *TVPtr = NULL ;
4895
4896 if ( ModeNo <= 0x13 )
4897 {
4898 modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; /* si+St_ResInfo */
4899 resinfo = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ResInfo ;
4900 }
4901 else
4902 {
4903 modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; /* si+Ext_ResInfo */
4904 resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ;
4905 }
4906
4907 pVBInfo->NewFlickerMode = 0 ;
4908 pVBInfo->RVBHRS = 50 ;
4909
4910 if ( pVBInfo->VBInfo & SetCRT2ToRAMDAC )
4911 {
4912 XGI_GetRAMDAC2DATA( ModeNo , ModeIdIndex , RefreshRateTableIndex,pVBInfo ) ;
4913 return ;
4914 }
4915
4916 tempbx = 4 ;
4917
4918 if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
4919 {
4920 LCDPtr = (XGI_LCDDataStruct* )XGI_GetLcdPtr( tempbx, ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
4921
4922 pVBInfo->RVBHCMAX = LCDPtr->RVBHCMAX ;
4923 pVBInfo->RVBHCFACT = LCDPtr->RVBHCFACT ;
4924 pVBInfo->VGAHT = LCDPtr->VGAHT ;
4925 pVBInfo->VGAVT = LCDPtr->VGAVT ;
4926 pVBInfo->HT = LCDPtr->LCDHT ;
4927 pVBInfo->VT = LCDPtr->LCDVT ;
4928
4929 if ( pVBInfo->LCDResInfo == Panel1024x768 )
4930 {
4931 tempax = 1024 ;
4932 tempbx = 768 ;
4933
4934 if ( !( pVBInfo->LCDInfo & LCDVESATiming ) )
4935 {
4936 if ( pVBInfo->VGAVDE == 357 )
4937 tempbx = 527 ;
4938 else if ( pVBInfo->VGAVDE == 420 )
4939 tempbx = 620 ;
4940 else if ( pVBInfo->VGAVDE == 525 )
4941 tempbx = 775 ;
4942 else if ( pVBInfo->VGAVDE == 600 )
4943 tempbx = 775 ;
4944 /* else if(pVBInfo->VGAVDE==350) tempbx=560; */
4945 /* else if(pVBInfo->VGAVDE==400) tempbx=640; */
4946 else
4947 tempbx = 768 ;
4948 }
4949 else
4950 tempbx = 768 ;
4951 }
4952 else if ( pVBInfo->LCDResInfo == Panel1024x768x75 )
4953 {
4954 tempax = 1024 ;
4955 tempbx = 768 ;
4956 }
4957 else if ( pVBInfo->LCDResInfo == Panel1280x1024 )
4958 {
4959 tempax = 1280 ;
4960 if ( pVBInfo->VGAVDE == 360 )
4961 tempbx = 768 ;
4962 else if ( pVBInfo->VGAVDE == 375 )
4963 tempbx = 800 ;
4964 else if ( pVBInfo->VGAVDE == 405 )
4965 tempbx = 864 ;
4966 else
4967 tempbx = 1024 ;
4968 }
4969 else if ( pVBInfo->LCDResInfo == Panel1280x1024x75 )
4970 {
4971 tempax = 1280 ;
4972 tempbx = 1024 ;
4973 }
4974 else if ( pVBInfo->LCDResInfo == Panel1280x960 )
4975 {
4976 tempax = 1280 ;
4977 if ( pVBInfo->VGAVDE == 350 )
4978 tempbx = 700 ;
4979 else if ( pVBInfo->VGAVDE == 400 )
4980 tempbx = 800 ;
4981 else if ( pVBInfo->VGAVDE == 1024 )
4982 tempbx = 960 ;
4983 else
4984 tempbx = 960 ;
4985 }
4986 else if ( pVBInfo->LCDResInfo == Panel1400x1050 )
4987 {
4988 tempax = 1400 ;
4989 tempbx = 1050 ;
4990
4991 if ( pVBInfo->VGAVDE == 1024 )
4992 {
4993 tempax = 1280 ;
4994 tempbx = 1024 ;
4995 }
4996 }
4997 else if ( pVBInfo->LCDResInfo == Panel1600x1200 )
4998 {
4999 tempax = 1600 ;
5000 tempbx = 1200 ; /* alan 10/14/2003 */
5001 if ( !( pVBInfo->LCDInfo & LCDVESATiming ) )
5002 {
5003 if ( pVBInfo->VGAVDE == 350 )
5004 tempbx = 875 ;
5005 else if ( pVBInfo->VGAVDE == 400 )
5006 tempbx = 1000 ;
5007 }
5008 }
5009
5010 if ( pVBInfo->LCDInfo & LCDNonExpanding )
5011 {
5012 tempax = pVBInfo->VGAHDE ;
5013 tempbx = pVBInfo->VGAVDE ;
5014 }
5015
5016 pVBInfo->HDE = tempax ;
5017 pVBInfo->VDE = tempbx ;
5018 return ;
5019 }
5020
5021 if ( pVBInfo->VBInfo & ( SetCRT2ToTV ) )
5022 {
5023 tempbx = 4 ;
5024 TVPtr = ( XGI_TVDataStruct * )XGI_GetTVPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
5025
5026 pVBInfo->RVBHCMAX = TVPtr->RVBHCMAX ;
5027 pVBInfo->RVBHCFACT = TVPtr->RVBHCFACT ;
5028 pVBInfo->VGAHT = TVPtr->VGAHT ;
5029 pVBInfo->VGAVT = TVPtr->VGAVT ;
5030 pVBInfo->HDE = TVPtr->TVHDE ;
5031 pVBInfo->VDE = TVPtr->TVVDE ;
5032 pVBInfo->RVBHRS = TVPtr->RVBHRS ;
5033 pVBInfo->NewFlickerMode = TVPtr->FlickerMode ;
5034
5035 if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
5036 {
5037 if ( resinfo == 0x08 )
5038 pVBInfo->NewFlickerMode = 0x40 ;
5039 else if ( resinfo == 0x09 )
5040 pVBInfo->NewFlickerMode = 0x40 ;
5041 else if ( resinfo == 0x12 )
5042 pVBInfo->NewFlickerMode = 0x40 ;
5043
5044 if ( pVBInfo->VGAVDE == 350 )
5045 pVBInfo->TVInfo |= TVSimuMode ;
5046
5047 tempax = ExtHiTVHT ;
5048 tempbx = ExtHiTVVT ;
5049
5050 if ( pVBInfo->VBInfo & SetInSlaveMode )
5051 {
5052 if ( pVBInfo->TVInfo & TVSimuMode )
5053 {
5054 tempax = StHiTVHT ;
5055 tempbx = StHiTVVT ;
5056
5057 if ( !( modeflag & Charx8Dot ) )
5058 {
5059 tempax = StHiTextTVHT ;
5060 tempbx = StHiTextTVVT ;
5061 }
5062 }
5063 }
5064 }
5065 else if ( pVBInfo->VBInfo & SetCRT2ToYPbPr )
5066 {
5067 if ( pVBInfo->TVInfo & SetYPbPrMode750p )
5068 {
5069 tempax = YPbPrTV750pHT ; /* Ext750pTVHT */
5070 tempbx = YPbPrTV750pVT ; /* Ext750pTVVT */
5071 }
5072
5073 if ( pVBInfo->TVInfo & SetYPbPrMode525p )
5074 {
5075 tempax = YPbPrTV525pHT ; /* Ext525pTVHT */
5076 tempbx = YPbPrTV525pVT ; /* Ext525pTVVT */
5077 }
5078 else if ( pVBInfo->TVInfo & SetYPbPrMode525i )
5079 {
5080 tempax = YPbPrTV525iHT ; /* Ext525iTVHT */
5081 tempbx = YPbPrTV525iVT ; /* Ext525iTVVT */
5082 if ( pVBInfo->TVInfo & NTSC1024x768 )
5083 tempax = NTSC1024x768HT ;
5084 }
5085 }
5086 else
5087 {
5088 tempax = PALHT ;
5089 tempbx = PALVT ;
5090 if ( !( pVBInfo->TVInfo & SetPALTV ) )
5091 {
5092 tempax = NTSCHT ;
5093 tempbx = NTSCVT ;
5094 if ( pVBInfo->TVInfo & NTSC1024x768 )
5095 tempax = NTSC1024x768HT ;
5096 }
5097 }
5098
5099 pVBInfo->HT = tempax ;
5100 pVBInfo->VT = tempbx ;
5101 return ;
5102 }
5103}
5104
5105
5106/* --------------------------------------------------------------------- */
5107/* Function : XGI_SetCRT2VCLK */
5108/* Input : */
5109/* Output : */
5110/* Description : */
5111/* --------------------------------------------------------------------- */
5112void XGI_SetCRT2VCLK( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
5113{
5114 UCHAR di_0 ,
5115 di_1 ,
5116 tempal ;
5117
5118 tempal = XGI_GetVCLKPtr( RefreshRateTableIndex , ModeNo , ModeIdIndex, pVBInfo ) ;
5119 XGI_GetVCLKLen( tempal, &di_0 , &di_1, pVBInfo ) ;
5120 XGI_GetLCDVCLKPtr( &di_0 , &di_1, pVBInfo ) ;
5121
5122 if ( pVBInfo->VBType & VB_XGI301 ) /* shampoo 0129 */
5123 { /* 301 */
5124 XGINew_SetReg1(pVBInfo->Part4Port , 0x0A , 0x10 ) ;
5125 XGINew_SetReg1(pVBInfo->Part4Port , 0x0B , di_1 ) ;
5126 XGINew_SetReg1(pVBInfo->Part4Port , 0x0A , di_0 ) ;
5127 }
5128 else
5129 { /* 301b/302b/301lv/302lv */
5130 XGINew_SetReg1( pVBInfo->Part4Port , 0x0A , di_0 ) ;
5131 XGINew_SetReg1( pVBInfo->Part4Port , 0x0B , di_1 ) ;
5132 }
5133
5134 XGINew_SetReg1( pVBInfo->Part4Port , 0x00 , 0x12 ) ;
5135
5136 if ( pVBInfo->VBInfo & SetCRT2ToRAMDAC )
5137 XGINew_SetRegOR( pVBInfo->Part4Port , 0x12 , 0x28 ) ;
5138 else
5139 XGINew_SetRegOR( pVBInfo->Part4Port , 0x12 , 0x08 ) ;
5140}
5141
5142
5143/* --------------------------------------------------------------------- */
5144/* Function : XGI_GETLCDVCLKPtr */
5145/* Input : */
5146/* Output : al -> VCLK Index */
5147/* Description : */
5148/* --------------------------------------------------------------------- */
5149void XGI_GetLCDVCLKPtr( UCHAR* di_0 , UCHAR *di_1, PVB_DEVICE_INFO pVBInfo )
5150{
5151 USHORT index ;
5152
5153 if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
5154 {
5155 if ( pVBInfo->IF_DEF_ScaleLCD == 1 )
5156 {
5157 if ( pVBInfo->LCDInfo & EnableScalingLCD )
5158 return ;
5159 }
5160
5161 /* index = XGI_GetLCDCapPtr(pVBInfo) ; */
5162 index = XGI_GetLCDCapPtr1( pVBInfo) ;
5163
5164 if ( pVBInfo->VBInfo & SetCRT2ToLCD )
5165 { /* LCDB */
5166 *di_0 = pVBInfo->LCDCapList[ index ].LCUCHAR_VCLKData1 ;
5167 *di_1 = pVBInfo->LCDCapList[ index ].LCUCHAR_VCLKData2 ;
5168 }
5169 else
5170 { /* LCDA */
5171 *di_0 = pVBInfo->LCDCapList[ index ].LCDA_VCLKData1 ;
5172 *di_1 = pVBInfo->LCDCapList[ index ].LCDA_VCLKData2 ;
5173 }
5174 }
5175 return ;
5176}
5177
5178
5179/* --------------------------------------------------------------------- */
5180/* Function : XGI_GetVCLKPtr */
5181/* Input : */
5182/* Output : */
5183/* Description : */
5184/* --------------------------------------------------------------------- */
5185UCHAR XGI_GetVCLKPtr(USHORT RefreshRateTableIndex,USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
5186{
5187
5188 USHORT index ,
5189 modeflag ;
5190#ifndef LINUX_XF86
5191 USHORT tempbx ;
5192#endif
5193
5194 UCHAR tempal ;
5195 UCHAR *CHTVVCLKPtr = NULL ;
5196
5197 if ( ModeNo <= 0x13 )
5198 modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; /* si+St_ResInfo */
5199 else
5200 modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */
5201
5202
5203 if ( ( pVBInfo->SetFlag & ProgrammingCRT2 ) && ( !( pVBInfo->LCDInfo & EnableScalingLCD ) ) )
5204 { /* {LCDA/LCDB} */
5205 index = XGI_GetLCDCapPtr(pVBInfo) ;
5206 tempal = pVBInfo->LCDCapList[ index ].LCD_VCLK ;
5207
5208 if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
5209 return tempal ;
5210
5211 /* {TV} */
5212 if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV| VB_XGI302LV| VB_XGI301C ) )
5213 {
5214 if(pVBInfo->VBInfo&SetCRT2ToHiVisionTV)
5215 {
5216 tempal = HiTVVCLKDIV2;
5217 if(!(pVBInfo->TVInfo & RPLLDIV2XO))
5218 tempal = HiTVVCLK;
5219 if(pVBInfo->TVInfo & TVSimuMode)
5220 {
5221 tempal = HiTVSimuVCLK;
5222 if(!(modeflag & Charx8Dot))
5223 tempal = HiTVTextVCLK;
5224
5225 }
5226 return tempal;
5227 }
5228
5229 if ( pVBInfo->TVInfo & SetYPbPrMode750p )
5230 {
5231 tempal = YPbPr750pVCLK ;
5232 return tempal ;
5233 }
5234
5235 if ( pVBInfo->TVInfo & SetYPbPrMode525p )
5236 {
5237 tempal = YPbPr525pVCLK ;
5238 return tempal ;
5239 }
5240
5241 tempal = NTSC1024VCLK ;
5242
5243 if ( !( pVBInfo->TVInfo & NTSC1024x768 ) )
5244 {
5245 tempal = TVVCLKDIV2 ;
5246 if ( !( pVBInfo->TVInfo & RPLLDIV2XO ) )
5247 tempal = TVVCLK ;
5248 }
5249
5250 if ( pVBInfo->VBInfo & SetCRT2ToTV )
5251 return tempal ;
5252 }
5253 /*else
5254 if((pVBInfo->IF_DEF_CH7017==1)&&(pVBInfo->VBType&VB_CH7017))
5255 {
5256 if(ModeNo<=0x13)
5257 *tempal = pVBInfo->SModeIDTable[ModeIdIndex].St_CRT2CRTC;
5258 else
5259 *tempal = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
5260 *tempal = *tempal & 0x1F;
5261
5262 tempbx = 0;
5263 if(pVBInfo->TVInfo & SetPALTV)
5264 tempbx = tempbx + 2;
5265 if(pVBInfo->TVInfo & SetCHTVOverScan)
5266 tempbx++;
5267 tempbx = tempbx << 1;
5268 } */
5269 } /* {End of VB} */
5270
5271 if((pVBInfo->IF_DEF_CH7007==1)&&(pVBInfo->VBType&VB_CH7007)) /* [Billy] 07/05/08 CH7007 */
5272 {
5273 /* VideoDebugPrint((0, "XGI_GetVCLKPtr: pVBInfo->IF_DEF_CH7007==1\n")); */
5274 if ( (pVBInfo->VBInfo & SetCRT2ToTV) )
5275 {
5276 if( ModeNo <= 0x13 )
5277 {
5278 tempal = pVBInfo->SModeIDTable[ ModeIdIndex ].St_CRT2CRTC ;
5279 }
5280 else
5281 {
5282 tempal = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
5283 }
5284
5285 tempal = tempal & 0x0F;
5286 tempbx = 0;
5287
5288 if(pVBInfo->TVInfo & SetPALTV)
5289 {
5290 tempbx = tempbx + 2;
5291 }
5292 if(pVBInfo->TVInfo & SetCHTVOverScan)
5293 {
5294 tempbx++;
5295 }
5296 /** tempbx = tempbx << 1; CH7007 ? **/
5297
5298/*[Billy]07/05/29 CH7007*/
5299 if ( pVBInfo->IF_DEF_CH7007 == 1 )
5300 {
5301 switch( tempbx )
5302 {
5303 case 0:
5304 CHTVVCLKPtr = XGI7007_CHTVVCLKUNTSC ;
5305 break ;
5306 case 1:
5307 CHTVVCLKPtr = XGI7007_CHTVVCLKONTSC ;
5308 break ;
5309 case 2:
5310 CHTVVCLKPtr = XGI7007_CHTVVCLKUPAL ;
5311 break ;
5312 case 3:
5313 CHTVVCLKPtr = XGI7007_CHTVVCLKOPAL ;
5314 break ;
5315 default:
5316 break ;
5317
5318 }
5319 }
5320 /*else
5321 {
5322 switch( tempbx )
5323 {
5324 case 0:
5325 CHTVVCLKPtr = pVBInfo->CHTVVCLKUNTSC ;
5326 break ;
5327 case 1:
5328 CHTVVCLKPtr = pVBInfo->CHTVVCLKONTSC ;
5329 break ;
5330 case 2:
5331 CHTVVCLKPtr = pVBInfo->CHTVVCLKUPAL ;
5332 break ;
5333 case 3:
5334 CHTVVCLKPtr = pVBInfo->CHTVVCLKOPAL ;
5335 break ;
5336 default:
5337 break ;
5338 }
5339 }*/
5340
5341 tempal = CHTVVCLKPtr[ tempal ] ;
5342 return tempal ;
5343 }
5344
5345 }
5346
5347 tempal = ( UCHAR )XGINew_GetReg2( ( pVBInfo->P3ca + 0x02 ) ) ;
5348 tempal = tempal >> 2 ;
5349 tempal &= 0x03 ;
5350
5351 if ( ( pVBInfo->LCDInfo & EnableScalingLCD ) && ( modeflag & Charx8Dot ) ) /* for Dot8 Scaling LCD */
5352 tempal = tempal ^ tempal ; /* ; set to VCLK25MHz always */
5353
5354 if ( ModeNo <= 0x13 )
5355 return tempal ;
5356
5357 tempal = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRTVCLK ;
5358 return tempal ;
5359}
5360
5361
5362/* --------------------------------------------------------------------- */
5363/* Function : XGI_GetVCLKLen */
5364/* Input : */
5365/* Output : */
5366/* Description : */
5367/* --------------------------------------------------------------------- */
5368void XGI_GetVCLKLen(UCHAR tempal,UCHAR* di_0,UCHAR* di_1, PVB_DEVICE_INFO pVBInfo)
5369{
5370 if ( pVBInfo->IF_DEF_CH7007 == 1 ) /* [Billy] 2007/05/16 */
5371 {
5372 /* VideoDebugPrint((0, "XGI_GetVCLKLen: pVBInfo->IF_DEF_CH7007==1\n")); */
5373 *di_0 = ( UCHAR )XGI_CH7007VCLKData[ tempal ].SR2B ;
5374 *di_1 = ( UCHAR )XGI_CH7007VCLKData[ tempal ].SR2C ;
5375 }
5376 else if ( pVBInfo->VBType & ( VB_XGI301 | VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
5377 {
5378 if ( ( !( pVBInfo->VBInfo & SetCRT2ToLCDA ) ) && ( pVBInfo->SetFlag & ProgrammingCRT2 ) )
5379 {
5380 *di_0 = ( UCHAR )XGI_VBVCLKData[ tempal ].SR2B ;
5381 *di_1 = XGI_VBVCLKData[ tempal ].SR2C ;
5382 }
5383 }
5384 else
5385 {
5386 *di_0 = XGI_VCLKData[ tempal ].SR2B ;
5387 *di_1 = XGI_VCLKData[ tempal ].SR2C ;
5388 }
5389}
5390
5391
5392/* --------------------------------------------------------------------- */
5393/* Function : XGI_SetCRT2Offset */
5394/* Input : */
5395/* Output : */
5396/* Description : */
5397/* --------------------------------------------------------------------- */
5398void XGI_SetCRT2Offset( USHORT ModeNo ,
5399 USHORT ModeIdIndex , USHORT RefreshRateTableIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
5400{
5401 USHORT offset ;
5402 UCHAR temp ;
5403
5404 if ( pVBInfo->VBInfo & SetInSlaveMode )
5405 {
5406 return ;
5407 }
5408
5409 offset = XGI_GetOffset( ModeNo , ModeIdIndex , RefreshRateTableIndex , HwDeviceExtension, pVBInfo ) ;
5410 temp = ( UCHAR )( offset & 0xFF ) ;
5411 XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , temp ) ;
5412 temp =( UCHAR)( ( offset & 0xFF00 ) >> 8 ) ;
5413 XGINew_SetReg1( pVBInfo->Part1Port , 0x09 , temp ) ;
5414 temp =( UCHAR )( ( ( offset >> 3 ) & 0xFF ) + 1 ) ;
5415 XGINew_SetReg1( pVBInfo->Part1Port , 0x03 , temp ) ;
5416}
5417
5418
5419/* --------------------------------------------------------------------- */
5420/* Function : XGI_GetOffset */
5421/* Input : */
5422/* Output : */
5423/* Description : */
5424/* --------------------------------------------------------------------- */
5425USHORT XGI_GetOffset(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo)
5426{
5427 USHORT temp ,
5428 colordepth ,
5429 modeinfo ,
5430 index ,
5431 infoflag ,
5432 ColorDepth[] = { 0x01 , 0x02 , 0x04 } ;
5433
5434 modeinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeInfo ;
5435 if ( ModeNo <= 0x14 )
5436 infoflag = 0 ;
5437 else
5438 infoflag = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag ;
5439
5440
5441 index = ( modeinfo >> 8 ) & 0xFF ;
5442
5443 temp = pVBInfo->ScreenOffset[ index ] ;
5444
5445 if ( infoflag & InterlaceMode )
5446 {
5447 temp = temp << 1 ;
5448 }
5449
5450 colordepth = XGI_GetColorDepth( ModeNo , ModeIdIndex, pVBInfo ) ;
5451
5452 if ( ( ModeNo >= 0x7C ) && ( ModeNo <= 0x7E ) )
5453 {
5454 temp = ModeNo - 0x7C ;
5455 colordepth = ColorDepth[ temp ] ;
5456 temp = 0x6B ;
5457 if ( infoflag & InterlaceMode )
5458 {
5459 temp = temp << 1 ;
5460 }
5461 return( temp * colordepth ) ;
5462 }
5463 else
5464 return( temp * colordepth ) ;
5465}
5466
5467
5468/* --------------------------------------------------------------------- */
5469/* Function : XGI_SetCRT2FIFO */
5470/* Input : */
5471/* Output : */
5472/* Description : */
5473/* --------------------------------------------------------------------- */
5474void XGI_SetCRT2FIFO( PVB_DEVICE_INFO pVBInfo)
5475{
5476 XGINew_SetReg1( pVBInfo->Part1Port , 0x01 , 0x3B ) ; /* threshold high ,disable auto threshold */
5477 XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x02 , ~( 0x3F ) , 0x04 ) ; /* threshold low default 04h */
5478}
5479
5480
5481/* --------------------------------------------------------------------- */
5482/* Function : XGI_PreSetGroup1 */
5483/* Input : */
5484/* Output : */
5485/* Description : */
5486/* --------------------------------------------------------------------- */
5487void XGI_PreSetGroup1(USHORT ModeNo , USHORT ModeIdIndex ,PXGI_HW_DEVICE_INFO HwDeviceExtension,
5488 USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
5489{
5490 USHORT tempcx = 0 ,
5491 CRT1Index = 0 ,
5492 resinfo = 0 ;
5493
5494 if ( ModeNo > 0x13 )
5495 {
5496 CRT1Index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC ;
5497 CRT1Index &= IndexMask ;
5498 resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ;
5499 }
5500
5501 XGI_SetCRT2Offset( ModeNo , ModeIdIndex , RefreshRateTableIndex , HwDeviceExtension, pVBInfo ) ;
5502 XGI_SetCRT2FIFO(pVBInfo) ;
5503 /* XGI_SetCRT2Sync(ModeNo,RefreshRateTableIndex); */
5504
5505 for( tempcx = 4 ; tempcx < 7 ; tempcx++ )
5506 {
5507 XGINew_SetReg1( pVBInfo->Part1Port , tempcx , 0x0 ) ;
5508 }
5509
5510 XGINew_SetReg1( pVBInfo->Part1Port , 0x50 , 0x00 ) ;
5511 XGINew_SetReg1( pVBInfo->Part1Port , 0x02 , 0x44 ) ; /* temp 0206 */
5512}
5513
5514
5515/* --------------------------------------------------------------------- */
5516/* Function : XGI_SetGroup1 */
5517/* Input : */
5518/* Output : */
5519/* Description : */
5520/* --------------------------------------------------------------------- */
5521void XGI_SetGroup1( USHORT ModeNo , USHORT ModeIdIndex ,
5522 PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
5523{
5524 USHORT temp = 0 ,
5525 tempax = 0 ,
5526 tempbx = 0 ,
5527 tempcx = 0 ,
5528 pushbx = 0 ,
5529 CRT1Index = 0 ,
5530 modeflag ,
5531 resinfo = 0 ;
5532
5533 if ( ModeNo > 0x13 )
5534 {
5535 CRT1Index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC ;
5536 CRT1Index &= IndexMask ;
5537 resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ;
5538 }
5539
5540 if ( ModeNo <= 0x13 )
5541 {
5542 modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
5543 }
5544 else
5545 {
5546 modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
5547 }
5548
5549 /* bainy change table name */
5550 if ( modeflag & HalfDCLK )
5551 {
5552 temp = ( pVBInfo->VGAHT / 2 - 1 ) & 0x0FF ; /* BTVGA2HT 0x08,0x09 */
5553 XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , temp ) ;
5554 temp = ( ( ( pVBInfo->VGAHT / 2 - 1 ) & 0xFF00 ) >> 8 ) << 4 ;
5555 XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x09 , ~0x0F0 , temp ) ;
5556 temp = ( pVBInfo->VGAHDE / 2 + 16 ) & 0x0FF ; /* BTVGA2HDEE 0x0A,0x0C */
5557 XGINew_SetReg1( pVBInfo->Part1Port , 0x0A , temp ) ;
5558 tempcx = ( ( pVBInfo->VGAHT - pVBInfo->VGAHDE ) / 2 ) >> 2 ;
5559 pushbx = pVBInfo->VGAHDE / 2 + 16 ;
5560 tempcx = tempcx >> 1 ;
5561 tempbx = pushbx + tempcx ; /* bx BTVGA@HRS 0x0B,0x0C */
5562 tempcx += tempbx ;
5563
5564 if ( pVBInfo->VBInfo & SetCRT2ToRAMDAC )
5565 {
5566 tempbx = pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 4 ] ;
5567 tempbx |= ( ( pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 14 ] & 0xC0 ) << 2 ) ;
5568 tempbx = ( tempbx - 3 ) << 3 ; /* (VGAHRS-3)*8 */
5569 tempcx = pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[ 5 ] ;
5570 tempcx &= 0x1F ;
5571 temp = pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 15 ] ;
5572 temp = ( temp & 0x04 ) << ( 5 - 2 ) ; /* VGAHRE D[5] */
5573 tempcx = ( ( tempcx | temp ) - 3 ) << 3 ; /* (VGAHRE-3)*8 */
5574 }
5575
5576 tempbx += 4 ;
5577 tempcx += 4 ;
5578
5579 if ( tempcx > ( pVBInfo->VGAHT / 2 ) )
5580 tempcx = pVBInfo->VGAHT / 2 ;
5581
5582 temp = tempbx & 0x00FF ;
5583
5584 XGINew_SetReg1( pVBInfo->Part1Port , 0x0B , temp ) ;
5585 }
5586 else
5587 {
5588 temp = ( pVBInfo->VGAHT - 1 ) & 0x0FF ; /* BTVGA2HT 0x08,0x09 */
5589 XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , temp ) ;
5590 temp = ( ( ( pVBInfo->VGAHT - 1 ) & 0xFF00 ) >> 8 ) << 4 ;
5591 XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x09 , ~0x0F0 , temp ) ;
5592 temp = ( pVBInfo->VGAHDE + 16 ) & 0x0FF ; /* BTVGA2HDEE 0x0A,0x0C */
5593 XGINew_SetReg1( pVBInfo->Part1Port , 0x0A , temp ) ;
5594 tempcx = ( pVBInfo->VGAHT - pVBInfo->VGAHDE ) >> 2 ; /* cx */
5595 pushbx = pVBInfo->VGAHDE + 16 ;
5596 tempcx = tempcx >> 1 ;
5597 tempbx = pushbx + tempcx ; /* bx BTVGA@HRS 0x0B,0x0C */
5598 tempcx += tempbx ;
5599
5600 if ( pVBInfo->VBInfo & SetCRT2ToRAMDAC )
5601 {
5602 tempbx = pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 3 ] ;
5603 tempbx |= ( ( pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 5 ] & 0xC0 ) << 2 ) ;
5604 tempbx = ( tempbx - 3 ) << 3 ; /* (VGAHRS-3)*8 */
5605 tempcx = pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 4 ] ;
5606 tempcx &= 0x1F ;
5607 temp = pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 6 ] ;
5608 temp = ( temp & 0x04 ) << ( 5 - 2 ) ; /* VGAHRE D[5] */
5609 tempcx = ( ( tempcx | temp ) - 3 ) << 3 ; /* (VGAHRE-3)*8 */
5610 tempbx += 16 ;
5611 tempcx += 16 ;
5612 }
5613
5614 if ( tempcx > pVBInfo->VGAHT )
5615 tempcx = pVBInfo->VGAHT ;
5616
5617 temp = tempbx & 0x00FF ;
5618 XGINew_SetReg1( pVBInfo->Part1Port , 0x0B , temp ) ;
5619 }
5620
5621 tempax = ( tempax & 0x00FF ) | ( tempbx & 0xFF00 ) ;
5622 tempbx = pushbx ;
5623 tempbx = ( tempbx & 0x00FF ) | ( ( tempbx & 0xFF00 ) << 4 ) ;
5624 tempax |= ( tempbx & 0xFF00 ) ;
5625 temp = ( tempax & 0xFF00 ) >> 8 ;
5626 XGINew_SetReg1( pVBInfo->Part1Port , 0x0C , temp ) ;
5627 temp = tempcx & 0x00FF ;
5628 XGINew_SetReg1( pVBInfo->Part1Port , 0x0D , temp ) ;
5629 tempcx = ( pVBInfo->VGAVT - 1 ) ;
5630 temp = tempcx & 0x00FF ;
5631
5632 if ( pVBInfo->IF_DEF_CH7005 == 1 )
5633 {
5634 if ( pVBInfo->VBInfo & 0x0C )
5635 {
5636 temp-- ;
5637 }
5638 }
5639
5640 XGINew_SetReg1( pVBInfo->Part1Port , 0x0E , temp ) ;
5641 tempbx = pVBInfo->VGAVDE - 1 ;
5642 temp = tempbx & 0x00FF ;
5643 XGINew_SetReg1( pVBInfo->Part1Port , 0x0F , temp ) ;
5644 temp = ( ( tempbx & 0xFF00 ) << 3 ) >> 8 ;
5645 temp |= ( ( tempcx & 0xFF00 ) >> 8 ) ;
5646 XGINew_SetReg1( pVBInfo->Part1Port , 0x12 , temp ) ;
5647
5648 tempax = pVBInfo->VGAVDE ;
5649 tempbx = pVBInfo->VGAVDE ;
5650 tempcx = pVBInfo->VGAVT ;
5651 tempbx = ( pVBInfo->VGAVT + pVBInfo->VGAVDE ) >> 1 ; /* BTVGA2VRS 0x10,0x11 */
5652 tempcx = ( ( pVBInfo->VGAVT - pVBInfo->VGAVDE ) >> 4 ) + tempbx + 1 ; /* BTVGA2VRE 0x11 */
5653
5654 if ( pVBInfo->VBInfo & SetCRT2ToRAMDAC )
5655 {
5656 tempbx = pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 10 ] ;
5657 temp = pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 9 ] ;
5658
5659 if ( temp & 0x04 )
5660 tempbx |= 0x0100 ;
5661
5662 if ( temp & 0x080 )
5663 tempbx |= 0x0200 ;
5664
5665 temp = pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 14 ] ;
5666
5667 if ( temp & 0x08 )
5668 tempbx |= 0x0400 ;
5669
5670 temp = pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 11 ] ;
5671 tempcx = ( tempcx & 0xFF00 ) | ( temp & 0x00FF ) ;
5672 }
5673
5674 temp = tempbx & 0x00FF ;
5675 XGINew_SetReg1( pVBInfo->Part1Port , 0x10 , temp ) ;
5676 temp = ( ( tempbx & 0xFF00 ) >> 8 ) << 4 ;
5677 temp = ( ( tempcx & 0x000F ) | ( temp ) ) ;
5678 XGINew_SetReg1( pVBInfo->Part1Port , 0x11 , temp ) ;
5679 tempax = 0 ;
5680
5681 if ( modeflag & DoubleScanMode )
5682 tempax |= 0x80 ;
5683
5684 if ( modeflag & HalfDCLK )
5685 tempax |= 0x40 ;
5686
5687 XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2C , ~0x0C0 , tempax ) ;
5688}
5689
5690
5691/* --------------------------------------------------------------------- */
5692/* Function : XGI_SetLockRegs */
5693/* Input : */
5694/* Output : */
5695/* Description : */
5696/* --------------------------------------------------------------------- */
5697void XGI_SetLockRegs( USHORT ModeNo , USHORT ModeIdIndex ,
5698 PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
5699{
5700 USHORT push1 ,
5701 push2 ,
5702 tempax ,
5703 tempbx = 0 ,
5704 tempcx ,
5705 temp ,
5706 resinfo ,
5707 modeflag ,
5708 CRT1Index ;
5709
5710 if ( ModeNo <= 0x13 )
5711 {
5712 modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; /* si+St_ResInfo */
5713 resinfo = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ResInfo ;
5714 }
5715 else
5716 {
5717 modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; /* si+Ext_ResInfo */
5718 resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ;
5719 CRT1Index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC ;
5720 CRT1Index &= IndexMask;
5721 }
5722
5723 if ( !( pVBInfo->VBInfo & SetInSlaveMode ) )
5724 {
5725 return ;
5726 }
5727
5728 temp = 0xFF ; /* set MAX HT */
5729 XGINew_SetReg1( pVBInfo->Part1Port , 0x03 , temp ) ;
5730 /* if ( modeflag & Charx8Dot ) tempcx = 0x08 ; */
5731 /* else */
5732 tempcx=0x08;
5733
5734 if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
5735 modeflag |= Charx8Dot ;
5736
5737 tempax = pVBInfo->VGAHDE ; /* 0x04 Horizontal Display End */
5738
5739 if ( modeflag & HalfDCLK )
5740 tempax = tempax >> 1 ;
5741
5742 tempax = ( tempax / tempcx ) - 1 ;
5743 tempbx |= ( ( tempax & 0x00FF ) << 8 ) ;
5744 temp = tempax & 0x00FF ;
5745 XGINew_SetReg1( pVBInfo->Part1Port , 0x04 , temp ) ;
5746
5747 temp = ( tempbx & 0xFF00 ) >> 8 ;
5748
5749 if ( pVBInfo->VBInfo & SetCRT2ToTV )
5750 {
5751 if ( !( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) )
5752 temp += 2 ;
5753
5754 if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
5755 {
5756 if ( pVBInfo->VBType & VB_XGI301LV )
5757 {
5758 if ( pVBInfo->VBExtInfo == VB_YPbPr1080i )
5759 {
5760 if ( resinfo == 7 )
5761 temp -= 2 ;
5762 }
5763 }
5764 else
5765 if ( resinfo == 7 )
5766 temp -= 2 ;
5767 }
5768 }
5769
5770 XGINew_SetReg1( pVBInfo->Part1Port , 0x05 , temp ) ; /* 0x05 Horizontal Display Start */
5771 XGINew_SetReg1( pVBInfo->Part1Port , 0x06 , 0x03 ) ; /* 0x06 Horizontal Blank end */
5772
5773 if ( !( pVBInfo->VBInfo & DisableCRT2Display ) )
5774 { /* 030226 bainy */
5775 if ( pVBInfo->VBInfo & SetCRT2ToTV )
5776 tempax = pVBInfo->VGAHT ;
5777 else
5778 tempax = XGI_GetVGAHT2( pVBInfo) ;
5779 }
5780
5781 if ( tempax >= pVBInfo->VGAHT )
5782 {
5783 tempax = pVBInfo->VGAHT ;
5784 }
5785
5786 if ( modeflag & HalfDCLK )
5787 {
5788 tempax = tempax >> 1 ;
5789 }
5790
5791 tempax = ( tempax / tempcx ) - 5 ;
5792 tempcx = tempax ; /* 20030401 0x07 horizontal Retrace Start */
5793 if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
5794 {
5795 temp = ( tempbx & 0x00FF ) - 1 ;
5796 if ( !( modeflag & HalfDCLK ) )
5797 {
5798 temp -= 6 ;
5799 if ( pVBInfo->TVInfo & TVSimuMode )
5800 {
5801 temp -= 4 ;
5802 if ( ModeNo > 0x13 )
5803 temp -= 10 ;
5804 }
5805 }
5806 }
5807 else
5808 {
5809 /* tempcx = tempbx & 0x00FF ; */
5810 tempbx = ( tempbx & 0xFF00 ) >> 8 ;
5811 tempcx = ( tempcx + tempbx ) >> 1 ;
5812 temp = ( tempcx & 0x00FF ) + 2 ;
5813
5814 if ( pVBInfo->VBInfo & SetCRT2ToTV )
5815 {
5816 temp -= 1 ;
5817 if ( !( modeflag & HalfDCLK ) )
5818 {
5819 if ( ( modeflag & Charx8Dot ) )
5820 {
5821 temp += 4 ;
5822 if ( pVBInfo->VGAHDE >= 800 )
5823 {
5824 temp -= 6 ;
5825 }
5826 }
5827 }
5828 }
5829 else
5830 {
5831 if ( !( modeflag & HalfDCLK ) )
5832 {
5833 temp -= 4 ;
5834 if ( pVBInfo->LCDResInfo != Panel1280x960 )
5835 {
5836 if( pVBInfo->VGAHDE >= 800 )
5837 {
5838 temp -= 7 ;
5839 if ( pVBInfo->ModeType == ModeEGA )
5840 {
5841 if ( pVBInfo->VGAVDE == 1024 )
5842 {
5843 temp += 15 ;
5844 if ( pVBInfo->LCDResInfo != Panel1280x1024 )
5845 {
5846 temp += 7 ;
5847 }
5848 }
5849 }
5850
5851 if ( pVBInfo->VGAHDE >= 1280 )
5852 {
5853 if ( pVBInfo->LCDResInfo != Panel1280x960 )
5854 {
5855 if ( pVBInfo->LCDInfo & LCDNonExpanding )
5856 {
5857 temp += 28 ;
5858 }
5859 }
5860 }
5861 }
5862 }
5863 }
5864 }
5865 }
5866
5867 XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , temp ) ; /* 0x07 Horizontal Retrace Start */
5868 XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , 0 ) ; /* 0x08 Horizontal Retrace End */
5869
5870 if ( pVBInfo->VBInfo & SetCRT2ToTV )
5871 {
5872 if ( pVBInfo->TVInfo & TVSimuMode )
5873 {
5874 if ( ( ModeNo == 0x06 ) || ( ModeNo == 0x10 ) || ( ModeNo == 0x11 ) || ( ModeNo == 0x13 ) || ( ModeNo == 0x0F ) )
5875 {
5876 XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , 0x5b ) ;
5877 XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , 0x03 ) ;
5878 }
5879
5880 if ( ( ModeNo == 0x00 ) || ( ModeNo == 0x01 ) )
5881 {
5882 if ( pVBInfo->TVInfo & SetNTSCTV )
5883 {
5884 XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , 0x2A ) ;
5885 XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , 0x61 ) ;
5886 }
5887 else
5888 {
5889 XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , 0x2A ) ;
5890 XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , 0x41 ) ;
5891 XGINew_SetReg1( pVBInfo->Part1Port , 0x0C , 0xF0 ) ;
5892 }
5893 }
5894
5895 if ( ( ModeNo == 0x02 ) || ( ModeNo == 0x03 ) || ( ModeNo == 0x07 ) )
5896 {
5897 if ( pVBInfo->TVInfo & SetNTSCTV )
5898 {
5899 XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , 0x54 ) ;
5900 XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , 0x00 ) ;
5901 }
5902 else
5903 {
5904 XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , 0x55 ) ;
5905 XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , 0x00 ) ;
5906 XGINew_SetReg1( pVBInfo->Part1Port , 0x0C , 0xF0 ) ;
5907 }
5908 }
5909
5910 if ( ( ModeNo == 0x04 ) || ( ModeNo == 0x05 ) || ( ModeNo == 0x0D ) || ( ModeNo == 0x50 ) )
5911 {
5912 if ( pVBInfo->TVInfo & SetNTSCTV )
5913 {
5914 XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , 0x30 ) ;
5915 XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , 0x03 ) ;
5916 }
5917 else
5918 {
5919 XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , 0x2f ) ;
5920 XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , 0x02 ) ;
5921 }
5922 }
5923 }
5924 }
5925
5926 XGINew_SetReg1( pVBInfo->Part1Port , 0x18 , 0x03 ) ; /* 0x18 SR0B */
5927 XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x19 , 0xF0 , 0x00 ) ;
5928 XGINew_SetReg1( pVBInfo->Part1Port , 0x09 , 0xFF ) ; /* 0x09 Set Max VT */
5929
5930 tempbx = pVBInfo->VGAVT ;
5931 push1 = tempbx ;
5932 tempcx = 0x121 ;
5933 tempbx = pVBInfo->VGAVDE ; /* 0x0E Virtical Display End */
5934
5935 if ( tempbx == 357 )
5936 tempbx = 350 ;
5937 if ( tempbx == 360 )
5938 tempbx =350 ;
5939 if ( tempbx == 375 )
5940 tempbx = 350 ;
5941 if ( tempbx == 405 )
5942 tempbx = 400 ;
5943 if ( tempbx == 525 )
5944 tempbx = 480 ;
5945
5946 push2 = tempbx ;
5947
5948 if ( pVBInfo->VBInfo & SetCRT2ToLCD )
5949 {
5950 if ( pVBInfo->LCDResInfo == Panel1024x768 )
5951 {
5952 if ( !( pVBInfo->LCDInfo & LCDVESATiming ) )
5953 {
5954 if ( tempbx == 350 )
5955 tempbx += 5 ;
5956 if ( tempbx == 480 )
5957 tempbx += 5 ;
5958 }
5959 }
5960 }
5961 tempbx-- ;
5962 temp = tempbx & 0x00FF ;
5963 tempbx-- ;
5964 temp = tempbx & 0x00FF ;
5965 XGINew_SetReg1( pVBInfo->Part1Port , 0x10 ,temp ) ; /* 0x10 vertical Blank Start */
5966 tempbx = push2 ;
5967 tempbx-- ;
5968 temp = tempbx & 0x00FF ;
5969 XGINew_SetReg1( pVBInfo->Part1Port , 0x0E , temp ) ;
5970
5971 if ( tempbx & 0x0100 )
5972 {
5973 tempcx |= 0x0002 ;
5974 }
5975
5976 tempax = 0x000B ;
5977
5978 if ( modeflag & DoubleScanMode )
5979 {
5980 tempax |= 0x08000 ;
5981 }
5982
5983 if ( tempbx & 0x0200 )
5984 {
5985 tempcx |= 0x0040 ;
5986 }
5987
5988 temp = ( tempax & 0xFF00 ) >> 8 ;
5989 XGINew_SetReg1( pVBInfo->Part1Port , 0x0B , temp ) ;
5990
5991 if ( tempbx & 0x0400 )
5992 {
5993 tempcx |= 0x0600 ;
5994 }
5995
5996 XGINew_SetReg1( pVBInfo->Part1Port , 0x11 , 0x00 ) ; /* 0x11 Vertival Blank End */
5997
5998 tempax = push1 ;
5999 tempax -= tempbx ; /* 0x0C Vertical Retrace Start */
6000 tempax = tempax >> 2 ;
6001 push1 = tempax ; /* push ax */
6002
6003 if ( resinfo != 0x09 )
6004 {
6005 tempax = tempax << 1 ;
6006 tempbx += tempax ;
6007 }
6008
6009 if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
6010 {
6011 if ( pVBInfo->VBType & VB_XGI301LV )
6012 {
6013 if ( pVBInfo->TVInfo & SetYPbPrMode1080i )
6014 tempbx -= 10 ;
6015 else
6016 {
6017 if ( pVBInfo->TVInfo & TVSimuMode )
6018 {
6019 if ( pVBInfo->TVInfo & SetPALTV )
6020 {
6021 if ( pVBInfo->VBType & VB_XGI301LV )
6022 {
6023 if ( !( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p | SetYPbPrMode1080i ) ) )
6024 tempbx += 40 ;
6025 }
6026 else
6027 tempbx += 40 ;
6028 }
6029 }
6030 }
6031 }
6032 else
6033 tempbx -= 10 ;
6034 }
6035 else
6036 {
6037 if ( pVBInfo->TVInfo & TVSimuMode )
6038 {
6039 if ( pVBInfo->TVInfo & SetPALTV )
6040 {
6041 if ( pVBInfo->VBType & VB_XGI301LV )
6042 {
6043 if ( !( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p | SetYPbPrMode1080i ) ) )
6044 tempbx += 40 ;
6045 }
6046 else
6047 tempbx += 40 ;
6048 }
6049 }
6050 }
6051 tempax = push1 ;
6052 tempax = tempax >> 2 ;
6053 tempax++ ;
6054 tempax += tempbx ;
6055 push1 = tempax ; /* push ax */
6056
6057 if ( ( pVBInfo->TVInfo & SetPALTV ) )
6058 {
6059 if ( tempbx <= 513 )
6060 {
6061 if ( tempax >= 513 )
6062 {
6063 tempbx = 513 ;
6064 }
6065 }
6066 }
6067
6068 temp = tempbx & 0x00FF ;
6069 XGINew_SetReg1( pVBInfo->Part1Port , 0x0C , temp ) ;
6070 tempbx-- ;
6071 temp = tempbx & 0x00FF ;
6072 XGINew_SetReg1( pVBInfo->Part1Port , 0x10 , temp ) ;
6073
6074 if ( tempbx & 0x0100 )
6075 {
6076 tempcx |= 0x0008 ;
6077 }
6078
6079 if ( tempbx & 0x0200 )
6080 {
6081 XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x0B , 0x0FF , 0x20 ) ;
6082 }
6083
6084 tempbx++ ;
6085
6086 if ( tempbx & 0x0100 )
6087 {
6088 tempcx |= 0x0004 ;
6089 }
6090
6091 if ( tempbx & 0x0200 )
6092 {
6093 tempcx |= 0x0080 ;
6094 }
6095
6096 if ( tempbx & 0x0400 )
6097 {
6098 tempcx |= 0x0C00 ;
6099 }
6100
6101 tempbx = push1 ; /* pop ax */
6102 temp = tempbx & 0x00FF ;
6103 temp &= 0x0F ;
6104 XGINew_SetReg1( pVBInfo->Part1Port , 0x0D , temp ) ; /* 0x0D vertical Retrace End */
6105
6106 if ( tempbx & 0x0010 )
6107 {
6108 tempcx |= 0x2000 ;
6109 }
6110
6111 temp = tempcx & 0x00FF ;
6112 XGINew_SetReg1( pVBInfo->Part1Port , 0x0A , temp ) ; /* 0x0A CR07 */
6113 temp = ( tempcx & 0x0FF00 ) >> 8 ;
6114 XGINew_SetReg1( pVBInfo->Part1Port , 0x17 , temp ) ; /* 0x17 SR0A */
6115 tempax = modeflag ;
6116 temp = ( tempax & 0xFF00 ) >> 8 ;
6117
6118 temp = ( temp >> 1 ) & 0x09 ;
6119
6120 if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
6121 temp |= 0x01 ;
6122
6123 XGINew_SetReg1( pVBInfo->Part1Port , 0x16 , temp ) ; /* 0x16 SR01 */
6124 XGINew_SetReg1( pVBInfo->Part1Port , 0x0F , 0 ) ; /* 0x0F CR14 */
6125 XGINew_SetReg1( pVBInfo->Part1Port , 0x12 , 0 ) ; /* 0x12 CR17 */
6126
6127 if ( pVBInfo->LCDInfo & LCDRGB18Bit )
6128 temp = 0x80 ;
6129 else
6130 temp = 0x00 ;
6131
6132 XGINew_SetReg1( pVBInfo->Part1Port , 0x1A , temp ) ; /* 0x1A SR0E */
6133
6134 return ;
6135}
6136
6137
6138/* --------------------------------------------------------------------- */
6139/* Function : XGI_SetGroup2 */
6140/* Input : */
6141/* Output : */
6142/* Description : */
6143/* --------------------------------------------------------------------- */
6144void XGI_SetGroup2( USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex,
6145 PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
6146{
6147 USHORT i ,
6148 j ,
6149 tempax ,
6150 tempbx ,
6151 tempcx ,
6152 temp ,
6153 push1 ,
6154 push2 ,
6155 modeflag ,
6156 resinfo ,
6157 crt2crtc ;
6158 UCHAR *TimingPoint ;
6159
6160 ULONG longtemp ,
6161 tempeax ,
6162 tempebx ,
6163 temp2 ,
6164 tempecx ;
6165
6166 if ( ModeNo <= 0x13 )
6167 {
6168 modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; /* si+St_ResInfo */
6169 resinfo = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ResInfo ;
6170 crt2crtc = pVBInfo->SModeIDTable[ ModeIdIndex ].St_CRT2CRTC ;
6171 }
6172 else
6173 {
6174 modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; /* si+Ext_ResInfo */
6175 resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ;
6176 crt2crtc = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT2CRTC ;
6177 }
6178
6179 tempax = 0 ;
6180
6181 if ( !( pVBInfo->VBInfo & SetCRT2ToAVIDEO ) )
6182 tempax |= 0x0800 ;
6183
6184 if ( !( pVBInfo->VBInfo & SetCRT2ToSVIDEO ) )
6185 tempax |= 0x0400 ;
6186
6187 if ( pVBInfo->VBInfo & SetCRT2ToSCART )
6188 tempax |= 0x0200 ;
6189
6190 if ( !( pVBInfo->TVInfo & SetPALTV ) )
6191 tempax |= 0x1000 ;
6192
6193 if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
6194 tempax |= 0x0100 ;
6195
6196 if ( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p ) )
6197 tempax &= 0xfe00 ;
6198
6199 tempax = ( tempax & 0xff00 ) >> 8 ;
6200
6201 XGINew_SetReg1( pVBInfo->Part2Port , 0x0 , tempax ) ;
6202 TimingPoint = pVBInfo->NTSCTiming ;
6203
6204 if ( pVBInfo->TVInfo & SetPALTV )
6205 {
6206 TimingPoint = pVBInfo->PALTiming ;
6207 }
6208
6209 if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
6210 {
6211 TimingPoint = pVBInfo->HiTVExtTiming ;
6212
6213 if ( pVBInfo->VBInfo & SetInSlaveMode )
6214 TimingPoint = pVBInfo->HiTVSt2Timing ;
6215
6216 if ( pVBInfo->SetFlag & TVSimuMode )
6217 TimingPoint = pVBInfo->HiTVSt1Timing ;
6218
6219 if ( !(modeflag & Charx8Dot) )
6220 TimingPoint = pVBInfo->HiTVTextTiming ;
6221 }
6222
6223 if ( pVBInfo->VBInfo & SetCRT2ToYPbPr )
6224 {
6225 if ( pVBInfo->TVInfo & SetYPbPrMode525i )
6226 TimingPoint = pVBInfo->YPbPr525iTiming ;
6227
6228 if ( pVBInfo->TVInfo & SetYPbPrMode525p )
6229 TimingPoint = pVBInfo->YPbPr525pTiming ;
6230
6231 if ( pVBInfo->TVInfo & SetYPbPrMode750p )
6232 TimingPoint = pVBInfo->YPbPr750pTiming ;
6233 }
6234
6235 for( i = 0x01 , j = 0 ; i <= 0x2D ; i++ , j++ )
6236 {
6237 XGINew_SetReg1( pVBInfo->Part2Port , i , TimingPoint[ j ] ) ;
6238 }
6239
6240 for( i = 0x39 ; i <= 0x45 ; i++ , j++ )
6241 {
6242 XGINew_SetReg1( pVBInfo->Part2Port , i , TimingPoint[ j ] ) ; /* di->temp2[j] */
6243 }
6244
6245 if ( pVBInfo->VBInfo & SetCRT2ToTV )
6246 {
6247 XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x3A , 0x1F , 0x00 ) ;
6248 }
6249
6250 temp = pVBInfo->NewFlickerMode ;
6251 temp &= 0x80 ;
6252 XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x0A , 0xFF , temp ) ;
6253
6254 if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
6255 tempax = 950 ;
6256
6257 if ( pVBInfo->TVInfo & SetPALTV )
6258 tempax = 520 ;
6259 else
6260 tempax = 440 ;
6261
6262 if ( pVBInfo->VDE <= tempax )
6263 {
6264 tempax -= pVBInfo->VDE ;
6265 tempax = tempax >> 2 ;
6266 tempax = ( tempax & 0x00FF ) | ( ( tempax & 0x00FF ) << 8 ) ;
6267 push1 = tempax ;
6268 temp = ( tempax & 0xFF00 ) >> 8 ;
6269 temp += ( USHORT )TimingPoint[ 0 ] ;
6270
6271 if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
6272 {
6273 if ( pVBInfo->VBInfo & ( SetCRT2ToAVIDEO | SetCRT2ToSVIDEO | SetCRT2ToSCART | SetCRT2ToYPbPr ) )
6274 {
6275 tempcx=pVBInfo->VGAHDE;
6276 if ( tempcx >= 1024 )
6277 {
6278 temp = 0x17 ; /* NTSC */
6279 if ( pVBInfo->TVInfo & SetPALTV )
6280 temp = 0x19 ; /* PAL */
6281 }
6282 }
6283 }
6284
6285 XGINew_SetReg1( pVBInfo->Part2Port , 0x01 , temp ) ;
6286 tempax = push1 ;
6287 temp = ( tempax & 0xFF00 ) >> 8 ;
6288 temp += TimingPoint[ 1 ] ;
6289
6290 if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
6291 {
6292 if ( ( pVBInfo->VBInfo & ( SetCRT2ToAVIDEO | SetCRT2ToSVIDEO | SetCRT2ToSCART | SetCRT2ToYPbPr ) ) )
6293 {
6294 tempcx = pVBInfo->VGAHDE ;
6295 if ( tempcx >= 1024 )
6296 {
6297 temp = 0x1D ; /* NTSC */
6298 if ( pVBInfo->TVInfo & SetPALTV )
6299 temp = 0x52 ; /* PAL */
6300 }
6301 }
6302 }
6303 XGINew_SetReg1( pVBInfo->Part2Port , 0x02 , temp ) ;
6304 }
6305
6306 /* 301b */
6307 tempcx = pVBInfo->HT ;
6308
6309 if ( XGI_IsLCDDualLink( pVBInfo ) )
6310 tempcx = tempcx >> 1 ;
6311
6312 tempcx -= 2 ;
6313 temp = tempcx & 0x00FF ;
6314 XGINew_SetReg1( pVBInfo->Part2Port , 0x1B , temp ) ;
6315
6316 temp = ( tempcx & 0xFF00 ) >> 8 ;
6317 XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x1D , ~0x0F , temp ) ;
6318
6319 tempcx = pVBInfo->HT >> 1 ;
6320 push1 = tempcx ; /* push cx */
6321 tempcx += 7 ;
6322
6323 if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
6324 {
6325 tempcx -= 4 ;
6326 }
6327
6328 temp = tempcx & 0x00FF ;
6329 temp = temp << 4 ;
6330 XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x22 , 0x0F , temp ) ;
6331
6332 tempbx = TimingPoint[ j ] | ( ( TimingPoint[ j + 1 ] ) << 8 ) ;
6333 tempbx += tempcx ;
6334 push2 = tempbx ;
6335 temp = tempbx & 0x00FF ;
6336 XGINew_SetReg1( pVBInfo->Part2Port , 0x24 , temp ) ;
6337 temp = ( tempbx & 0xFF00 ) >> 8 ;
6338 temp = temp << 4 ;
6339 XGINew_SetRegANDOR(pVBInfo->Part2Port,0x25,0x0F,temp);
6340
6341 tempbx=push2;
6342 tempbx=tempbx+8;
6343 if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
6344 {
6345 tempbx=tempbx-4;
6346 tempcx=tempbx;
6347 }
6348
6349 temp = ( tempbx & 0x00FF ) << 4 ;
6350 XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x29 , 0x0F , temp ) ;
6351
6352 j += 2 ;
6353 tempcx += ( TimingPoint[ j ] | ( ( TimingPoint[ j + 1 ] ) << 8 ) ) ;
6354 temp = tempcx & 0x00FF ;
6355 XGINew_SetReg1( pVBInfo->Part2Port , 0x27 , temp ) ;
6356 temp = ( ( tempcx & 0xFF00 ) >> 8 ) << 4 ;
6357 XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x28 , 0x0F , temp ) ;
6358
6359 tempcx += 8 ;
6360 if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
6361 {
6362 tempcx -= 4 ;
6363 }
6364
6365 temp = tempcx & 0xFF ;
6366 temp = temp << 4 ;
6367 XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x2A , 0x0F , temp ) ;
6368
6369 tempcx = push1 ; /* pop cx */
6370 j += 2 ;
6371 temp = TimingPoint[ j ] | ( ( TimingPoint[ j + 1 ] ) << 8 ) ;
6372 tempcx -= temp ;
6373 temp = tempcx & 0x00FF ;
6374 temp = temp << 4 ;
6375 XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x2D , 0x0F ,temp ) ;
6376
6377 tempcx -= 11 ;
6378
6379 if ( !( pVBInfo->VBInfo & SetCRT2ToTV ) )
6380 {
6381 tempax = XGI_GetVGAHT2( pVBInfo) ;
6382 tempcx = tempax - 1 ;
6383 }
6384 temp = tempcx & 0x00FF ;
6385 XGINew_SetReg1( pVBInfo->Part2Port , 0x2E , temp ) ;
6386
6387 tempbx = pVBInfo->VDE ;
6388
6389 if ( pVBInfo->VGAVDE == 360 )
6390 tempbx = 746 ;
6391 if ( pVBInfo->VGAVDE == 375 )
6392 tempbx = 746 ;
6393 if ( pVBInfo->VGAVDE == 405 )
6394 tempbx = 853 ;
6395
6396 if ( pVBInfo->VBInfo & SetCRT2ToTV )
6397 {
6398 if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
6399 {
6400 if ( !( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p ) ) )
6401 tempbx = tempbx >> 1 ;
6402 }
6403 else
6404 tempbx = tempbx >> 1 ;
6405 }
6406
6407 tempbx -= 2 ;
6408 temp = tempbx & 0x00FF ;
6409
6410 if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
6411 {
6412 if ( pVBInfo->VBType & VB_XGI301LV )
6413 {
6414 if ( pVBInfo->TVInfo & SetYPbPrMode1080i )
6415 {
6416 if ( pVBInfo->VBInfo & SetInSlaveMode )
6417 {
6418 if ( ModeNo == 0x2f )
6419 temp += 1 ;
6420 }
6421 }
6422 }
6423 else
6424 {
6425 if ( pVBInfo->VBInfo & SetInSlaveMode )
6426 {
6427 if ( ModeNo == 0x2f )
6428 temp += 1 ;
6429 }
6430 }
6431 }
6432
6433 XGINew_SetReg1( pVBInfo->Part2Port , 0x2F , temp ) ;
6434
6435 temp = ( tempcx & 0xFF00 ) >> 8 ;
6436 temp |= ( ( tempbx & 0xFF00 ) >> 8 ) << 6 ;
6437
6438 if ( !( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) )
6439 {
6440 if ( pVBInfo->VBType & VB_XGI301LV )
6441 {
6442 if ( pVBInfo->TVInfo & SetYPbPrMode1080i )
6443 {
6444 temp |= 0x10 ;
6445
6446 if ( !( pVBInfo->VBInfo & SetCRT2ToSVIDEO ) )
6447 temp |= 0x20 ;
6448 }
6449 }
6450 else
6451 {
6452 temp |= 0x10 ;
6453 if ( !( pVBInfo->VBInfo & SetCRT2ToSVIDEO ) )
6454 temp |= 0x20 ;
6455 }
6456 }
6457
6458 XGINew_SetReg1( pVBInfo->Part2Port , 0x30 , temp ) ;
6459
6460 if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) /* TV gatingno */
6461 {
6462 tempbx = pVBInfo->VDE ;
6463 tempcx = tempbx - 2 ;
6464
6465 if ( pVBInfo->VBInfo & SetCRT2ToTV )
6466 {
6467 if ( !( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p ) ) )
6468 tempbx = tempbx >> 1 ;
6469 }
6470
6471 if ( pVBInfo->VBType & ( VB_XGI302LV | VB_XGI301C ) )
6472 {
6473 temp=0;
6474 if( tempcx & 0x0400 )
6475 temp |= 0x20 ;
6476
6477 if ( tempbx & 0x0400 )
6478 temp |= 0x40 ;
6479
6480 XGINew_SetReg1( pVBInfo->Part4Port , 0x10 , temp ) ;
6481 }
6482
6483 temp = ( ( ( tempbx - 3 ) & 0x0300 ) >> 8 ) << 5 ;
6484 XGINew_SetReg1( pVBInfo->Part2Port , 0x46 , temp ) ;
6485 temp = ( tempbx - 3 ) & 0x00FF ;
6486 XGINew_SetReg1( pVBInfo->Part2Port , 0x47 , temp ) ;
6487 }
6488
6489 tempbx = tempbx & 0x00FF ;
6490
6491 if ( !( modeflag & HalfDCLK ) )
6492 {
6493 tempcx = pVBInfo->VGAHDE ;
6494 if ( tempcx >= pVBInfo->HDE )
6495 {
6496 tempbx |= 0x2000 ;
6497 tempax &= 0x00FF ;
6498 }
6499 }
6500
6501 tempcx = 0x0101 ;
6502
6503 if( pVBInfo->VBInfo & SetCRT2ToTV ) { /*301b*/
6504 if(pVBInfo->VGAHDE>=1024)
6505 {
6506 tempcx=0x1920;
6507 if(pVBInfo->VGAHDE>=1280)
6508 {
6509 tempcx=0x1420;
6510 tempbx=tempbx&0xDFFF;
6511 }
6512 }
6513 }
6514
6515 if ( !( tempbx & 0x2000 ) )
6516 {
6517 if ( modeflag & HalfDCLK )
6518 {
6519 tempcx = ( tempcx & 0xFF00 ) | ( ( tempcx & 0x00FF ) << 1 ) ;
6520 }
6521
6522 push1 = tempbx ;
6523 tempeax = pVBInfo->VGAHDE ;
6524 tempebx = ( tempcx & 0xFF00 ) >> 8 ;
6525 longtemp = tempeax * tempebx ;
6526 tempecx = tempcx & 0x00FF ;
6527 longtemp = longtemp / tempecx ;
6528
6529 /* 301b */
6530 tempecx = 8 * 1024 ;
6531
6532 if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
6533 {
6534 tempecx = tempecx * 8 ;
6535 }
6536
6537 longtemp = longtemp * tempecx ;
6538 tempecx = pVBInfo->HDE ;
6539 temp2 = longtemp % tempecx ;
6540 tempeax = longtemp / tempecx ;
6541 if ( temp2 != 0 )
6542 {
6543 tempeax += 1 ;
6544 }
6545
6546 tempax = ( USHORT )tempeax ;
6547
6548 /* 301b */
6549 if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
6550 {
6551 tempcx = ( ( tempax & 0xFF00 ) >> 5 ) >> 8 ;
6552 }
6553 /* end 301b */
6554
6555 tempbx = push1 ;
6556 tempbx =( USHORT )( ( ( tempeax & 0x0000FF00 ) & 0x1F00 ) | ( tempbx & 0x00FF ) ) ;
6557 tempax =( USHORT )( ( ( tempeax & 0x000000FF ) << 8 ) | ( tempax & 0x00FF ) ) ;
6558 temp = ( tempax & 0xFF00 ) >> 8 ;
6559 }
6560 else
6561 {
6562 temp = ( tempax & 0x00FF ) >> 8 ;
6563 }
6564
6565 XGINew_SetReg1( pVBInfo->Part2Port , 0x44 , temp ) ;
6566 temp = ( tempbx & 0xFF00 ) >> 8 ;
6567 XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x45 , ~0x03F , temp ) ;
6568 temp = tempcx & 0x00FF ;
6569
6570 if ( tempbx & 0x2000 )
6571 temp = 0 ;
6572
6573 if ( !( pVBInfo->VBInfo & SetCRT2ToLCD ) )
6574 temp |= 0x18 ;
6575
6576 XGINew_SetRegANDOR(pVBInfo->Part2Port,0x46,~0x1F,temp);
6577 if ( pVBInfo->TVInfo & SetPALTV )
6578 {
6579 tempbx = 0x0382 ;
6580 tempcx = 0x007e ;
6581 }
6582 else
6583 {
6584 tempbx = 0x0369 ;
6585 tempcx = 0x0061 ;
6586 }
6587
6588 temp = tempbx & 0x00FF ;
6589 XGINew_SetReg1( pVBInfo->Part2Port , 0x4b , temp ) ;
6590 temp = tempcx & 0x00FF ;
6591 XGINew_SetReg1( pVBInfo->Part2Port , 0x4c , temp ) ;
6592
6593 temp = ( ( tempcx & 0xFF00 ) >> 8 ) & 0x03 ;
6594 temp = temp << 2 ;
6595 temp |= ( ( tempbx & 0xFF00 ) >> 8 ) & 0x03 ;
6596
6597 if ( pVBInfo->VBInfo & SetCRT2ToYPbPr )
6598 {
6599 temp |= 0x10 ;
6600
6601 if ( pVBInfo->TVInfo & SetYPbPrMode525p )
6602 temp |= 0x20 ;
6603
6604 if ( pVBInfo->TVInfo & SetYPbPrMode750p )
6605 temp |= 0x60 ;
6606 }
6607
6608 XGINew_SetReg1( pVBInfo->Part2Port , 0x4d , temp ) ;
6609 temp=XGINew_GetReg1( pVBInfo->Part2Port , 0x43 ) ; /* 301b change */
6610 XGINew_SetReg1( pVBInfo->Part2Port , 0x43 , ( USHORT )( temp - 3 ) ) ;
6611
6612 if ( !( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p ) ) )
6613 {
6614 if ( pVBInfo->TVInfo & NTSC1024x768 )
6615 {
6616 TimingPoint = XGI_NTSC1024AdjTime ;
6617 for( i = 0x1c , j = 0 ; i <= 0x30 ; i++ , j++ )
6618 {
6619 XGINew_SetReg1( pVBInfo->Part2Port , i , TimingPoint[ j ] ) ;
6620 }
6621 XGINew_SetReg1( pVBInfo->Part2Port , 0x43 , 0x72 ) ;
6622 }
6623 }
6624
6625 /* [ycchen] 01/14/03 Modify for 301C PALM Support */
6626 if ( pVBInfo->VBType & VB_XGI301C )
6627 {
6628 if ( pVBInfo->TVInfo & SetPALMTV )
6629 XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x4E , ~0x08 , 0x08 ) ; /* PALM Mode */
6630 }
6631
6632 if ( pVBInfo->TVInfo & SetPALMTV )
6633 {
6634 tempax = ( UCHAR )XGINew_GetReg1( pVBInfo->Part2Port , 0x01 ) ;
6635 tempax-- ;
6636 XGINew_SetRegAND( pVBInfo->Part2Port , 0x01 , tempax ) ;
6637
6638 /* if ( !( pVBInfo->VBType & VB_XGI301C ) ) */
6639 XGINew_SetRegAND( pVBInfo->Part2Port , 0x00 , 0xEF ) ;
6640 }
6641
6642 if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
6643 {
6644 if ( !( pVBInfo->VBInfo & SetInSlaveMode ) )
6645 {
6646 XGINew_SetReg1( pVBInfo->Part2Port , 0x0B , 0x00 ) ;
6647 }
6648 }
6649
6650 if ( pVBInfo->VBInfo & SetCRT2ToTV )
6651 {
6652 return ;
6653 }
6654}
6655
6656
6657/* --------------------------------------------------------------------- */
6658/* Function : XGI_SetLCDRegs */
6659/* Input : */
6660/* Output : */
6661/* Description : */
6662/* --------------------------------------------------------------------- */
6663void XGI_SetLCDRegs(USHORT ModeNo,USHORT ModeIdIndex, PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo)
6664{
6665 USHORT push1 ,
6666 push2 ,
6667 pushbx ,
6668 tempax ,
6669 tempbx ,
6670 tempcx ,
6671 temp ,
6672 tempah ,
6673 tempbh ,
6674 tempch ,
6675 resinfo ,
6676 modeflag ,
6677 CRT1Index ;
6678
6679 XGI_LCDDesStruct *LCDBDesPtr = NULL ;
6680
6681
6682 if ( ModeNo <= 0x13 )
6683 {
6684 modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; /* si+St_ResInfo */
6685 resinfo = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ResInfo ;
6686 }
6687 else
6688 {
6689 modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; /* si+Ext_ResInfo */
6690 resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ;
6691 CRT1Index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC ;
6692 CRT1Index &= IndexMask ;
6693 }
6694
6695 if ( !( pVBInfo->VBInfo & SetCRT2ToLCD ) )
6696 {
6697 return ;
6698 }
6699
6700 tempbx = pVBInfo->HDE ; /* RHACTE=HDE-1 */
6701
6702 if ( XGI_IsLCDDualLink( pVBInfo ) )
6703 tempbx = tempbx >> 1 ;
6704
6705 tempbx -= 1 ;
6706 temp = tempbx & 0x00FF ;
6707 XGINew_SetReg1( pVBInfo->Part2Port , 0x2C , temp ) ;
6708 temp = ( tempbx & 0xFF00 ) >> 8 ;
6709 temp = temp << 4 ;
6710 XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x2B , 0x0F , temp ) ;
6711 temp = 0x01 ;
6712
6713 if ( pVBInfo->LCDResInfo == Panel1280x1024 )
6714 {
6715 if ( pVBInfo->ModeType == ModeEGA )
6716 {
6717 if ( pVBInfo->VGAHDE >= 1024 )
6718 {
6719 temp = 0x02 ;
6720 if ( pVBInfo->LCDInfo & LCDVESATiming )
6721 temp = 0x01 ;
6722 }
6723 }
6724 }
6725
6726 XGINew_SetReg1( pVBInfo->Part2Port , 0x0B , temp ) ;
6727 tempbx = pVBInfo->VDE ; /* RTVACTEO=(VDE-1)&0xFF */
6728 push1 = tempbx ;
6729 tempbx-- ;
6730 temp = tempbx & 0x00FF ;
6731 XGINew_SetReg1( pVBInfo->Part2Port , 0x03 , temp ) ;
6732 temp = ( ( tempbx & 0xFF00 ) >> 8 ) & 0x07 ;
6733 XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x0C , ~0x07 , temp ) ;
6734
6735 tempcx = pVBInfo->VT - 1 ;
6736 push2 = tempcx + 1 ;
6737 temp = tempcx & 0x00FF ; /* RVTVT=VT-1 */
6738 XGINew_SetReg1( pVBInfo->Part2Port , 0x19 , temp ) ;
6739 temp = ( tempcx & 0xFF00 ) >> 8 ;
6740 temp = temp << 5 ;
6741 XGINew_SetReg1( pVBInfo->Part2Port , 0x1A , temp ) ;
6742 XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x09 , 0xF0 , 0x00 ) ;
6743 XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x0A , 0xF0 , 0x00 ) ;
6744 XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x17 , 0xFB , 0x00 ) ;
6745 XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x18 , 0xDF , 0x00 ) ;
6746
6747 /* Customized LCDB Des no add */
6748 tempbx = 5 ;
6749 LCDBDesPtr = ( XGI_LCDDesStruct * )XGI_GetLcdPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
6750 tempah = pVBInfo->LCDResInfo ;
6751 tempah &= PanelResInfo ;
6752
6753 if ( ( tempah == Panel1024x768 ) || ( tempah == Panel1024x768x75 ) )
6754 {
6755 tempbx = 1024 ;
6756 tempcx = 768 ;
6757 }
6758 else if ( ( tempah == Panel1280x1024 ) || ( tempah == Panel1280x1024x75 ) )
6759 {
6760 tempbx = 1280 ;
6761 tempcx = 1024 ;
6762 }
6763 else if ( tempah == Panel1400x1050 )
6764 {
6765 tempbx = 1400 ;
6766 tempcx = 1050 ;
6767 }
6768 else
6769 {
6770 tempbx = 1600 ;
6771 tempcx = 1200 ;
6772 }
6773
6774 if ( pVBInfo->LCDInfo & EnableScalingLCD )
6775 {
6776 tempbx = pVBInfo->HDE ;
6777 tempcx = pVBInfo->VDE ;
6778 }
6779
6780 pushbx = tempbx ;
6781 tempax = pVBInfo->VT ;
6782 pVBInfo->LCDHDES = LCDBDesPtr->LCDHDES ;
6783 pVBInfo->LCDHRS = LCDBDesPtr->LCDHRS ;
6784 pVBInfo->LCDVDES = LCDBDesPtr->LCDVDES ;
6785 pVBInfo->LCDVRS = LCDBDesPtr->LCDVRS ;
6786 tempbx = pVBInfo->LCDVDES ;
6787 tempcx += tempbx ;
6788
6789 if ( tempcx >= tempax )
6790 tempcx -= tempax ; /* lcdvdes */
6791
6792 temp = tempbx & 0x00FF ; /* RVEQ1EQ=lcdvdes */
6793 XGINew_SetReg1( pVBInfo->Part2Port , 0x05 , temp ) ;
6794 temp = tempcx & 0x00FF ;
6795 XGINew_SetReg1( pVBInfo->Part2Port , 0x06 , temp ) ;
6796 tempch = ( ( tempcx & 0xFF00 ) >> 8 ) & 0x07 ;
6797 tempbh = ( ( tempbx & 0xFF00 ) >> 8 ) & 0x07 ;
6798 tempah = tempch ;
6799 tempah = tempah << 3 ;
6800 tempah |= tempbh ;
6801 XGINew_SetReg1( pVBInfo->Part2Port , 0x02 , tempah ) ;
6802
6803 /* getlcdsync() */
6804 XGI_GetLCDSync( &tempax , &tempbx,pVBInfo ) ;
6805 tempcx = tempbx ;
6806 tempax = pVBInfo->VT ;
6807 tempbx = pVBInfo->LCDVRS ;
6808
6809 /* if ( SetLCD_Info & EnableScalingLCD ) */
6810 tempcx += tempbx ;
6811 if ( tempcx >= tempax )
6812 tempcx -= tempax ;
6813
6814 temp = tempbx & 0x00FF ; /* RTVACTEE=lcdvrs */
6815 XGINew_SetReg1( pVBInfo->Part2Port , 0x04 , temp ) ;
6816 temp = ( tempbx & 0xFF00 ) >> 8 ;
6817 temp = temp << 4 ;
6818 temp |= ( tempcx & 0x000F ) ;
6819 XGINew_SetReg1( pVBInfo->Part2Port , 0x01 , temp ) ;
6820 tempcx = pushbx ;
6821 tempax = pVBInfo->HT ;
6822 tempbx = pVBInfo->LCDHDES ;
6823 tempbx &= 0x0FFF ;
6824
6825 if ( XGI_IsLCDDualLink( pVBInfo ) )
6826 {
6827 tempax = tempax >> 1 ;
6828 tempbx = tempbx >> 1 ;
6829 tempcx = tempcx >> 1 ;
6830 }
6831
6832 if ( pVBInfo->VBType & VB_XGI302LV )
6833 tempbx += 1 ;
6834
6835 if ( pVBInfo->VBType & VB_XGI301C ) /* tap4 */
6836 tempbx += 1 ;
6837
6838 tempcx += tempbx ;
6839
6840 if ( tempcx >= tempax )
6841 tempcx -= tempax ;
6842
6843 temp = tempbx & 0x00FF ;
6844 XGINew_SetReg1( pVBInfo->Part2Port , 0x1F , temp ) ; /* RHBLKE=lcdhdes */
6845 temp = ( ( tempbx & 0xFF00 ) >> 8 ) << 4 ;
6846 XGINew_SetReg1( pVBInfo->Part2Port , 0x20 , temp ) ;
6847 temp = tempcx & 0x00FF ;
6848 XGINew_SetReg1( pVBInfo->Part2Port , 0x23 , temp ) ; /* RHEQPLE=lcdhdee */
6849 temp = ( tempcx & 0xFF00 ) >> 8 ;
6850 XGINew_SetReg1( pVBInfo->Part2Port , 0x25 , temp ) ;
6851
6852 /* getlcdsync() */
6853 XGI_GetLCDSync( &tempax , &tempbx ,pVBInfo) ;
6854 tempcx = tempax ;
6855 tempax = pVBInfo->HT ;
6856 tempbx = pVBInfo->LCDHRS ;
6857 /* if ( SetLCD_Info & EnableScalingLCD) */
6858 if ( XGI_IsLCDDualLink( pVBInfo) )
6859 {
6860 tempax = tempax >> 1 ;
6861 tempbx = tempbx >> 1 ;
6862 tempcx = tempcx >> 1 ;
6863 }
6864
6865 if ( pVBInfo->VBType & VB_XGI302LV )
6866 tempbx += 1 ;
6867
6868 tempcx += tempbx ;
6869
6870 if ( tempcx >= tempax )
6871 tempcx -= tempax ;
6872
6873 temp = tempbx & 0x00FF ; /* RHBURSTS=lcdhrs */
6874 XGINew_SetReg1( pVBInfo->Part2Port , 0x1C , temp ) ;
6875
6876 temp = ( tempbx & 0xFF00 ) >> 8 ;
6877 temp = temp << 4 ;
6878 XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x1D , ~0x0F0 , temp ) ;
6879 temp = tempcx & 0x00FF ; /* RHSYEXP2S=lcdhre */
6880 XGINew_SetReg1( pVBInfo->Part2Port , 0x21 , temp ) ;
6881
6882 if ( !( pVBInfo->LCDInfo & LCDVESATiming ) )
6883 {
6884 if ( pVBInfo->VGAVDE == 525 )
6885 {
6886 if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
6887 {
6888 temp = 0xC6 ;
6889 }
6890 else
6891 temp = 0xC4 ;
6892
6893 XGINew_SetReg1( pVBInfo->Part2Port , 0x2f , temp ) ;
6894 XGINew_SetReg1( pVBInfo->Part2Port , 0x30 , 0xB3 ) ;
6895 }
6896
6897 if ( pVBInfo->VGAVDE == 420 )
6898 {
6899 if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
6900 {
6901 temp = 0x4F ;
6902 }
6903 else
6904 temp = 0x4E ;
6905 XGINew_SetReg1( pVBInfo->Part2Port , 0x2f , temp ) ;
6906 }
6907 }
6908}
6909
6910
6911/* --------------------------------------------------------------------- */
6912/* Function : XGI_GetTap4Ptr */
6913/* Input : */
6914/* Output : di -> Tap4 Reg. Setting Pointer */
6915/* Description : */
6916/* --------------------------------------------------------------------- */
6917XGI301C_Tap4TimingStruct* XGI_GetTap4Ptr(USHORT tempcx, PVB_DEVICE_INFO pVBInfo)
6918{
6919 USHORT tempax ,
6920 tempbx ,
6921 i ;
6922
6923 XGI301C_Tap4TimingStruct *Tap4TimingPtr ;
6924
6925 if ( tempcx == 0 )
6926 {
6927 tempax = pVBInfo->VGAHDE ;
6928 tempbx = pVBInfo->HDE ;
6929 }
6930 else
6931 {
6932 tempax = pVBInfo->VGAVDE ;
6933 tempbx = pVBInfo->VDE ;
6934 }
6935
6936 if ( tempax < tempbx )
6937 return &EnlargeTap4Timing[ 0 ] ;
6938 else if( tempax == tempbx )
6939 return &NoScaleTap4Timing[ 0 ] ; /* 1:1 */
6940 else
6941 Tap4TimingPtr = NTSCTap4Timing ; /* NTSC */
6942
6943 if ( pVBInfo->TVInfo & SetPALTV )
6944 Tap4TimingPtr = PALTap4Timing ;
6945
6946
6947 if ( pVBInfo->VBInfo & SetCRT2ToYPbPr )
6948 {
6949 if ( pVBInfo->TVInfo & SetYPbPrMode525i )
6950 Tap4TimingPtr = YPbPr525iTap4Timing ;
6951 if ( pVBInfo->TVInfo & SetYPbPrMode525p )
6952 Tap4TimingPtr = YPbPr525pTap4Timing ;
6953 if ( pVBInfo->TVInfo & SetYPbPrMode750p )
6954 Tap4TimingPtr = YPbPr750pTap4Timing ;
6955 }
6956
6957 if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
6958 Tap4TimingPtr = HiTVTap4Timing ;
6959
6960 i = 0 ;
6961 while( Tap4TimingPtr[ i ].DE != 0xFFFF )
6962 {
6963 if ( Tap4TimingPtr[ i ].DE == tempax )
6964 break ;
6965 i++ ;
6966 }
6967 return &Tap4TimingPtr[ i ] ;
6968}
6969
6970
6971/* --------------------------------------------------------------------- */
6972/* Function : XGI_SetTap4Regs */
6973/* Input : */
6974/* Output : */
6975/* Description : */
6976/* --------------------------------------------------------------------- */
6977void XGI_SetTap4Regs( PVB_DEVICE_INFO pVBInfo)
6978{
6979 USHORT i ,
6980 j ;
6981
6982 XGI301C_Tap4TimingStruct *Tap4TimingPtr ;
6983
6984 if ( !( pVBInfo->VBType & VB_XGI301C ) )
6985 return ;
6986
6987#ifndef Tap4
6988 XGINew_SetRegAND( pVBInfo->Part2Port , 0x4E , 0xEB ) ; /* Disable Tap4 */
6989#else /* Tap4 Setting */
6990
6991 Tap4TimingPtr = XGI_GetTap4Ptr( 0 , pVBInfo) ; /* Set Horizontal Scaling */
6992 for( i = 0x80 , j = 0 ; i <= 0xBF ; i++ , j++ )
6993 XGINew_SetReg1( pVBInfo->Part2Port , i , Tap4TimingPtr->Reg[ j ] ) ;
6994
6995 if ( ( pVBInfo->VBInfo & SetCRT2ToTV ) && ( !( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) ) )
6996 {
6997 Tap4TimingPtr = XGI_GetTap4Ptr( 1 , pVBInfo); /* Set Vertical Scaling */
6998 for( i = 0xC0 , j = 0 ; i < 0xFF ; i++ , j++ )
6999 XGINew_SetReg1( pVBInfo->Part2Port , i , Tap4TimingPtr->Reg[ j ] ) ;
7000 }
7001
7002 if ( ( pVBInfo->VBInfo & SetCRT2ToTV ) && ( !( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) ) )
7003 XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x4E , ~0x14 , 0x04 ) ; /* Enable V.Scaling */
7004 else
7005 XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x4E , ~0x14 , 0x10 ) ; /* Enable H.Scaling */
7006#endif
7007}
7008
7009/* --------------------------------------------------------------------- */
7010/* Function : XGI_SetGroup3 */
7011/* Input : */
7012/* Output : */
7013/* Description : */
7014/* --------------------------------------------------------------------- */
7015void XGI_SetGroup3(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
7016{
7017 USHORT i;
7018 UCHAR *tempdi;
7019 USHORT modeflag;
7020
7021 if(ModeNo<=0x13)
7022 {
7023 modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */
7024 }
7025 else
7026 {
7027 modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */
7028 }
7029
7030
7031 XGINew_SetReg1(pVBInfo->Part3Port,0x00,0x00);
7032 if(pVBInfo->TVInfo&SetPALTV)
7033 {
7034 XGINew_SetReg1(pVBInfo->Part3Port,0x13,0xFA);
7035 XGINew_SetReg1(pVBInfo->Part3Port,0x14,0xC8);
7036 }
7037 else
7038 {
7039 XGINew_SetReg1(pVBInfo->Part3Port,0x13,0xF5);
7040 XGINew_SetReg1(pVBInfo->Part3Port,0x14,0xB7);
7041 }
7042
7043 if(!(pVBInfo->VBInfo&SetCRT2ToTV))
7044 {
7045 return;
7046 }
7047
7048 if(pVBInfo->TVInfo&SetPALMTV)
7049 {
7050 XGINew_SetReg1(pVBInfo->Part3Port,0x13,0xFA);
7051 XGINew_SetReg1(pVBInfo->Part3Port,0x14,0xC8);
7052 XGINew_SetReg1(pVBInfo->Part3Port,0x3D,0xA8);
7053 }
7054
7055 if((pVBInfo->VBInfo&SetCRT2ToHiVisionTV)|| (pVBInfo->VBInfo&SetCRT2ToYPbPr))
7056 {
7057 if(pVBInfo->TVInfo & SetYPbPrMode525i)
7058 {
7059 return;
7060 }
7061 tempdi=pVBInfo->HiTVGroup3Data;
7062 if(pVBInfo->SetFlag&TVSimuMode)
7063 {
7064 tempdi=pVBInfo->HiTVGroup3Simu;
7065 if(!(modeflag&Charx8Dot))
7066 {
7067 tempdi=pVBInfo->HiTVGroup3Text;
7068 }
7069 }
7070
7071 if(pVBInfo->TVInfo & SetYPbPrMode525p)
7072 {
7073 tempdi=pVBInfo->Ren525pGroup3;
7074 }
7075 if(pVBInfo->TVInfo & SetYPbPrMode750p)
7076 {
7077 tempdi=pVBInfo->Ren750pGroup3;
7078 }
7079
7080 for(i=0;i<=0x3E;i++)
7081 {
7082 XGINew_SetReg1(pVBInfo->Part3Port,i,tempdi[i]);
7083 }
7084 if(pVBInfo->VBType&VB_XGI301C) /* Marcovision */
7085 {
7086 if(pVBInfo->TVInfo & SetYPbPrMode525p)
7087 {
7088 XGINew_SetReg1(pVBInfo->Part3Port,0x28,0x3f);
7089 }
7090 }
7091 }
7092 return;
7093} /* {end of XGI_SetGroup3} */
7094
7095
7096/* --------------------------------------------------------------------- */
7097/* Function : XGI_SetGroup4 */
7098/* Input : */
7099/* Output : */
7100/* Description : */
7101/* --------------------------------------------------------------------- */
7102void XGI_SetGroup4(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
7103{
7104 USHORT tempax ,
7105 tempcx ,
7106 tempbx ,
7107 modeflag ,
7108 temp ,
7109 temp2 ;
7110
7111 ULONG tempebx ,
7112 tempeax ,
7113 templong ;
7114
7115
7116 if ( ModeNo <= 0x13 )
7117 {
7118 modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; /* si+St_ResInfo */
7119 }
7120 else
7121 {
7122 modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; /* si+Ext_ResInfo */
7123 }
7124
7125 temp = pVBInfo->RVBHCFACT ;
7126 XGINew_SetReg1( pVBInfo->Part4Port , 0x13 , temp ) ;
7127
7128 tempbx = pVBInfo->RVBHCMAX ;
7129 temp = tempbx & 0x00FF ;
7130 XGINew_SetReg1( pVBInfo->Part4Port , 0x14 , temp ) ;
7131 temp2 = ( ( tempbx & 0xFF00 ) >> 8 ) << 7 ;
7132 tempcx = pVBInfo->VGAHT - 1 ;
7133 temp = tempcx & 0x00FF ;
7134 XGINew_SetReg1( pVBInfo->Part4Port , 0x16 , temp ) ;
7135
7136 temp =( ( tempcx & 0xFF00 ) >> 8 ) << 3 ;
7137 temp2 |= temp ;
7138
7139 tempcx = pVBInfo->VGAVT - 1 ;
7140 if ( !( pVBInfo->VBInfo & SetCRT2ToTV ) )
7141 {
7142 tempcx -= 5 ;
7143 }
7144
7145 temp = tempcx & 0x00FF ;
7146 XGINew_SetReg1( pVBInfo->Part4Port , 0x17 , temp ) ;
7147 temp = temp2 | ( ( tempcx & 0xFF00 ) >> 8 ) ;
7148 XGINew_SetReg1( pVBInfo->Part4Port , 0x15 , temp ) ;
7149 XGINew_SetRegOR( pVBInfo->Part4Port , 0x0D , 0x08 ) ;
7150 tempcx = pVBInfo->VBInfo ;
7151 tempbx = pVBInfo->VGAHDE ;
7152
7153 if ( modeflag & HalfDCLK )
7154 {
7155 tempbx = tempbx >> 1 ;
7156 }
7157
7158 if ( XGI_IsLCDDualLink( pVBInfo ) )
7159 tempbx = tempbx >> 1 ;
7160
7161 if(tempcx&SetCRT2ToHiVisionTV)
7162 {
7163 temp=0;
7164 if(tempbx<=1024)
7165 temp=0xA0;
7166 if(tempbx == 1280)
7167 temp = 0xC0;
7168 }
7169 else if(tempcx&SetCRT2ToTV)
7170 {
7171 temp=0xA0;
7172 if(tempbx <= 800)
7173 temp=0x80;
7174 }
7175 else
7176 {
7177 temp=0x80;
7178 if(pVBInfo->VBInfo&SetCRT2ToLCD)
7179 {
7180 temp=0;
7181 if(tempbx>800)
7182 temp=0x60;
7183 }
7184 }
7185
7186 if ( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p ) )
7187 {
7188 temp = 0x00 ;
7189 if ( pVBInfo->VGAHDE == 1280 )
7190 temp = 0x40 ;
7191 if ( pVBInfo->VGAHDE == 1024 )
7192 temp = 0x20 ;
7193 }
7194 XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x0E , ~0xEF , temp ) ;
7195
7196 tempebx = pVBInfo->VDE ;
7197
7198 if ( tempcx & SetCRT2ToHiVisionTV )
7199 {
7200 if ( !( temp & 0xE000 ) )
7201 tempbx = tempbx >> 1 ;
7202 }
7203
7204 tempcx = pVBInfo->RVBHRS ;
7205 temp = tempcx & 0x00FF ;
7206 XGINew_SetReg1( pVBInfo->Part4Port , 0x18 , temp );
7207
7208 tempeax = pVBInfo->VGAVDE ;
7209 tempcx |= 0x04000 ;
7210
7211
7212 if ( tempeax <= tempebx )
7213 {
7214 tempcx=(tempcx&(~0x4000));
7215 tempeax = pVBInfo->VGAVDE ;
7216 }
7217 else
7218 {
7219 tempeax -= tempebx ;
7220 }
7221
7222
7223 templong = ( tempeax * 256 * 1024 ) % tempebx ;
7224 tempeax = ( tempeax * 256 * 1024 ) / tempebx ;
7225 tempebx = tempeax ;
7226
7227 if ( templong != 0 )
7228 {
7229 tempebx++ ;
7230 }
7231
7232
7233 temp = ( USHORT )( tempebx & 0x000000FF ) ;
7234 XGINew_SetReg1( pVBInfo->Part4Port , 0x1B , temp ) ;
7235
7236 temp = ( USHORT )( ( tempebx & 0x0000FF00 ) >> 8 ) ;
7237 XGINew_SetReg1( pVBInfo->Part4Port , 0x1A , temp ) ;
7238 tempbx = ( USHORT )( tempebx >> 16 ) ;
7239 temp = tempbx & 0x00FF ;
7240 temp = temp << 4 ;
7241 temp |= ( ( tempcx & 0xFF00 ) >> 8 ) ;
7242 XGINew_SetReg1( pVBInfo->Part4Port , 0x19 , temp ) ;
7243
7244 /* 301b */
7245 if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
7246 {
7247 temp = 0x0028 ;
7248 XGINew_SetReg1( pVBInfo->Part4Port , 0x1C , temp ) ;
7249 tempax = pVBInfo->VGAHDE ;
7250 if ( modeflag & HalfDCLK )
7251 {
7252 tempax = tempax >> 1 ;
7253 }
7254
7255 if ( XGI_IsLCDDualLink( pVBInfo ) )
7256 tempax = tempax >> 1 ;
7257
7258 /* if((pVBInfo->VBInfo&(SetCRT2ToLCD))||((pVBInfo->TVInfo&SetYPbPrMode525p)||(pVBInfo->TVInfo&SetYPbPrMode750p))) { */
7259 if ( pVBInfo->VBInfo & SetCRT2ToLCD )
7260 {
7261 if ( tempax > 800 )
7262 tempax -= 800 ;
7263 }
7264 else
7265 {
7266 if ( pVBInfo->VGAHDE > 800 )
7267 {
7268 if ( pVBInfo->VGAHDE == 1024 )
7269 tempax = ( tempax * 25 / 32 ) - 1 ;
7270 else
7271 tempax = ( tempax * 20 / 32 ) - 1 ;
7272 }
7273 }
7274 tempax -= 1 ;
7275
7276/*
7277 if ( pVBInfo->VBInfo & ( SetCRT2ToTV | SetCRT2ToHiVisionTV ) )
7278 {
7279 if ( pVBInfo->VBType & VB_XGI301LV )
7280 {
7281 if ( !( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p | SetYPbPrMode1080i ) ) )
7282 {
7283 if ( pVBInfo->VGAHDE > 800 )
7284 {
7285 if ( pVBInfo->VGAHDE == 1024 )
7286 tempax = ( tempax * 25 / 32 ) - 1 ;
7287 else
7288 tempax = ( tempax * 20 / 32 ) - 1 ;
7289 }
7290 }
7291 }
7292 else
7293 {
7294 if ( pVBInfo->VGAHDE > 800 )
7295 {
7296 if ( pVBInfo->VGAHDE == 1024 )
7297 tempax = ( tempax * 25 / 32 ) - 1 ;
7298 else
7299 tempax = ( tempax * 20 / 32 ) - 1 ;
7300 }
7301 }
7302 }
7303*/
7304
7305 temp = ( tempax & 0xFF00 ) >> 8 ;
7306 temp = ( ( temp & 0x0003 ) << 4 ) ;
7307 XGINew_SetReg1( pVBInfo->Part4Port , 0x1E , temp ) ;
7308 temp = ( tempax & 0x00FF ) ;
7309 XGINew_SetReg1( pVBInfo->Part4Port , 0x1D , temp ) ;
7310
7311 if ( pVBInfo->VBInfo & ( SetCRT2ToTV | SetCRT2ToHiVisionTV ) )
7312 {
7313 if ( pVBInfo->VGAHDE > 800 )
7314 {
7315 XGINew_SetRegOR( pVBInfo->Part4Port , 0x1E , 0x08 ) ;
7316 }
7317 }
7318 temp = 0x0036 ;
7319
7320 if ( pVBInfo->VBInfo & SetCRT2ToTV )
7321 {
7322 if ( !( pVBInfo->TVInfo & ( NTSC1024x768 | SetYPbPrMode525p | SetYPbPrMode750p | SetYPbPrMode1080i ) ) )
7323 {
7324 temp |= 0x0001 ;
7325 if ( ( pVBInfo->VBInfo & SetInSlaveMode ) && ( !( pVBInfo->TVInfo & TVSimuMode ) ) )
7326 temp &= ( ~0x0001 ) ;
7327 }
7328 }
7329
7330 XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x1F , 0x00C0 , temp ) ;
7331 tempbx = pVBInfo->HT ;
7332 if ( XGI_IsLCDDualLink( pVBInfo ) )
7333 tempbx = tempbx >> 1 ;
7334 tempbx = ( tempbx >> 1 ) - 2 ;
7335 temp = ( ( tempbx & 0x0700 ) >> 8 ) << 3 ;
7336 XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x21 , 0x00C0 , temp ) ;
7337 temp = tempbx & 0x00FF ;
7338 XGINew_SetReg1( pVBInfo->Part4Port , 0x22 , temp ) ;
7339 }
7340 /* end 301b */
7341
7342 if ( pVBInfo->ISXPDOS == 0 )
7343 XGI_SetCRT2VCLK( ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ;
7344}
7345
7346
7347/* --------------------------------------------------------------------- */
7348/* Function : XGI_SetGroup5 */
7349/* Input : */
7350/* Output : */
7351/* Description : */
7352/* --------------------------------------------------------------------- */
7353void XGI_SetGroup5( USHORT ModeNo , USHORT ModeIdIndex , PVB_DEVICE_INFO pVBInfo)
7354{
7355 USHORT Pindex ,
7356 Pdata ;
7357
7358 Pindex = pVBInfo->Part5Port ;
7359 Pdata = pVBInfo->Part5Port + 1 ;
7360 if ( pVBInfo->ModeType == ModeVGA )
7361 {
7362 if ( !( pVBInfo->VBInfo & ( SetInSlaveMode | LoadDACFlag | CRT2DisplayFlag ) ) )
7363 {
7364 XGINew_EnableCRT2(pVBInfo) ;
7365 /* LoadDAC2(pVBInfo->Part5Port,ModeNo,ModeIdIndex); */
7366 }
7367 }
7368 return ;
7369}
7370
7371
7372/* --------------------------------------------------------------------- */
7373/* Function : XGI_GetLcdPtr */
7374/* Input : */
7375/* Output : */
7376/* Description : */
7377/* --------------------------------------------------------------------- */
7378void* XGI_GetLcdPtr( USHORT BX , USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
7379{
7380 USHORT i ,
7381 tempdx ,
7382 tempcx ,
7383 tempbx ,
7384 tempal ,
7385 modeflag ,
7386 table ;
7387
7388 XGI330_LCDDataTablStruct *tempdi = 0 ;
7389
7390
7391 tempbx = BX;
7392
7393 if ( ModeNo <= 0x13 )
7394 {
7395 modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
7396 tempal = pVBInfo->SModeIDTable[ ModeIdIndex ].St_CRT2CRTC ;
7397 }
7398 else
7399 {
7400 modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
7401 tempal = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT2CRTC ;
7402 }
7403
7404 tempal = tempal & 0x0f ;
7405
7406 if ( tempbx <= 1 ) /* ExpLink */
7407 {
7408 if ( ModeNo <= 0x13 )
7409 {
7410 tempal = pVBInfo->SModeIDTable[ ModeIdIndex ].St_CRT2CRTC ; /* find no Ext_CRT2CRTC2 */
7411 }
7412 else
7413 {
7414 tempal= pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT2CRTC ;
7415 }
7416
7417 if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
7418 {
7419 if ( ModeNo <= 0x13 )
7420 tempal = pVBInfo->SModeIDTable[ ModeIdIndex ].St_CRT2CRTC2 ;
7421 else
7422 tempal= pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT2CRTC2 ;
7423 }
7424
7425 if ( tempbx & 0x01 )
7426 tempal = ( tempal >> 4 ) ;
7427
7428 tempal = ( tempal & 0x0f ) ;
7429 }
7430
7431 tempcx = LCDLenList[ tempbx ] ; /* mov cl,byte ptr cs:LCDLenList[bx] */
7432
7433 if ( pVBInfo->LCDInfo & EnableScalingLCD ) /* ScaleLCD */
7434 {
7435 if ( ( tempbx == 5 ) || ( tempbx ) == 7 )
7436 tempcx = LCDDesDataLen2 ;
7437 else if ( ( tempbx == 3 ) || ( tempbx == 8 ) )
7438 tempcx = LVDSDesDataLen2 ;
7439 }
7440 /* mov di, word ptr cs:LCDDataList[bx] */
7441 /* tempdi=pVideoMemory[LCDDataList+tempbx*2]|(pVideoMemory[LCDDataList+tempbx*2+1]<<8); */
7442
7443 switch( tempbx )
7444 {
7445 case 0:
7446 tempdi = XGI_EPLLCDCRT1Ptr_H ;
7447 break ;
7448 case 1:
7449 tempdi = XGI_EPLLCDCRT1Ptr_V ;
7450 break ;
7451 case 2:
7452 tempdi = XGI_EPLLCDDataPtr ;
7453 break ;
7454 case 3:
7455 tempdi = XGI_EPLLCDDesDataPtr ;
7456 break ;
7457 case 4:
7458 tempdi = XGI_LCDDataTable ;
7459 break ;
7460 case 5:
7461 tempdi = XGI_LCDDesDataTable ;
7462 break ;
7463 case 6:
7464 tempdi = XGI_EPLCHLCDRegPtr ;
7465 break ;
7466 case 7:
7467 case 8:
7468 case 9:
7469 tempdi = 0 ;
7470 break ;
7471 default:
7472 break ;
7473 }
7474
7475 if ( tempdi == 0x00 ) /* OEMUtil */
7476 return 0 ;
7477
7478 table = tempbx ;
7479 i = 0 ;
7480
7481 while( tempdi[ i ].PANELID != 0xff )
7482 {
7483 tempdx = pVBInfo->LCDResInfo ;
7484 if ( tempbx & 0x0080 ) /* OEMUtil */
7485 {
7486 tempbx &= ( ~0x0080 ) ;
7487 tempdx = pVBInfo->LCDTypeInfo ;
7488 }
7489
7490 if ( pVBInfo->LCDInfo & EnableScalingLCD )
7491 tempdx &= ( ~PanelResInfo ) ;
7492
7493 if ( tempdi[ i ].PANELID == tempdx )
7494 {
7495 tempbx = tempdi[ i ].MASK ;
7496 tempdx = pVBInfo->LCDInfo ;
7497
7498 if ( ModeNo <= 0x13 ) /* alan 09/10/2003 */
7499 tempdx |= SetLCDStdMode ;
7500
7501 if ( modeflag & HalfDCLK )
7502 tempdx |= SetLCDLowResolution ;
7503
7504 tempbx &= tempdx;
7505 if ( tempbx == tempdi[ i ].CAP )
7506 break ;
7507 }
7508 i++ ;
7509 }
7510
7511 if ( table == 0 )
7512 {
7513 switch( tempdi[ i ].DATAPTR )
7514 {
7515 case 0:
7516 return &XGI_LVDSCRT11024x768_1_H[ tempal ] ;
7517 break ;
7518 case 1:
7519 return &XGI_LVDSCRT11024x768_2_H[ tempal ] ;
7520 break ;
7521 case 2:
7522 return &XGI_LVDSCRT11280x1024_1_H[ tempal ] ;
7523 break ;
7524 case 3:
7525 return &XGI_LVDSCRT11280x1024_2_H[ tempal ] ;
7526 break ;
7527 case 4:
7528 return &XGI_LVDSCRT11400x1050_1_H[ tempal ] ;
7529 break ;
7530 case 5:
7531 return &XGI_LVDSCRT11400x1050_2_H[ tempal ] ;
7532 break ;
7533 case 6:
7534 return &XGI_LVDSCRT11600x1200_1_H[ tempal ] ;
7535 break ;
7536 case 7:
7537 return &XGI_LVDSCRT11024x768_1_Hx75[ tempal ] ;
7538 break ;
7539 case 8:
7540 return &XGI_LVDSCRT11024x768_2_Hx75[ tempal ] ;
7541 break ;
7542 case 9:
7543 return &XGI_LVDSCRT11280x1024_1_Hx75[ tempal ] ;
7544 break ;
7545 case 10:
7546 return &XGI_LVDSCRT11280x1024_2_Hx75[ tempal ] ;
7547 break ;
7548 default:
7549 break ;
7550 }
7551 }
7552 else if ( table == 1 )
7553 {
7554 switch( tempdi[ i ].DATAPTR )
7555 {
7556 case 0:
7557 return &XGI_LVDSCRT11024x768_1_V[ tempal ] ;
7558 break ;
7559 case 1:
7560 return &XGI_LVDSCRT11024x768_2_V[ tempal ] ;
7561 break ;
7562 case 2:
7563 return &XGI_LVDSCRT11280x1024_1_V[ tempal ] ;
7564 break ;
7565 case 3:
7566 return &XGI_LVDSCRT11280x1024_2_V[ tempal ] ;
7567 break ;
7568 case 4:
7569 return &XGI_LVDSCRT11400x1050_1_V[ tempal ] ;
7570 break ;
7571 case 5:
7572 return &XGI_LVDSCRT11400x1050_2_V[ tempal ] ;
7573 break ;
7574 case 6:
7575 return &XGI_LVDSCRT11600x1200_1_V[ tempal ] ;
7576 break ;
7577 case 7:
7578 return &XGI_LVDSCRT11024x768_1_Vx75[ tempal ] ;
7579 break ;
7580 case 8:
7581 return &XGI_LVDSCRT11024x768_2_Vx75[ tempal ] ;
7582 break ;
7583 case 9:
7584 return &XGI_LVDSCRT11280x1024_1_Vx75[ tempal ] ;
7585 break ;
7586 case 10:
7587 return &XGI_LVDSCRT11280x1024_2_Vx75[ tempal ] ;
7588 break ;
7589 default:
7590 break ;
7591 }
7592 }
7593 else if ( table == 2 )
7594 {
7595 switch( tempdi[ i ].DATAPTR )
7596 {
7597 case 0:
7598 return &XGI_LVDS1024x768Data_1[ tempal ] ;
7599 break ;
7600 case 1:
7601 return &XGI_LVDS1024x768Data_2[ tempal ] ;
7602 break ;
7603 case 2:
7604 return &XGI_LVDS1280x1024Data_1[ tempal ] ;
7605 break ;
7606 case 3:
7607 return &XGI_LVDS1280x1024Data_2[ tempal ] ;
7608 break ;
7609 case 4:
7610 return &XGI_LVDS1400x1050Data_1[ tempal ] ;
7611 break ;
7612 case 5:
7613 return &XGI_LVDS1400x1050Data_2[ tempal ] ;
7614 break ;
7615 case 6:
7616 return &XGI_LVDS1600x1200Data_1[ tempal ] ;
7617 break ;
7618 case 7:
7619 return &XGI_LVDSNoScalingData[ tempal ] ;
7620 break ;
7621 case 8:
7622 return &XGI_LVDS1024x768Data_1x75[ tempal ] ;
7623 break ;
7624 case 9:
7625 return &XGI_LVDS1024x768Data_2x75[ tempal ] ;
7626 break ;
7627 case 10:
7628 return &XGI_LVDS1280x1024Data_1x75[ tempal ] ;
7629 break ;
7630 case 11:
7631 return &XGI_LVDS1280x1024Data_2x75[ tempal ] ;
7632 break ;
7633 case 12:
7634 return &XGI_LVDSNoScalingDatax75[ tempal ] ;
7635 break ;
7636 default:
7637 break ;
7638 }
7639 }
7640 else if ( table == 3 )
7641 {
7642 switch( tempdi[ i ].DATAPTR )
7643 {
7644 case 0:
7645 return &XGI_LVDS1024x768Des_1[ tempal ] ;
7646 break ;
7647 case 1:
7648 return &XGI_LVDS1024x768Des_3[ tempal ] ;
7649 break ;
7650 case 2:
7651 return &XGI_LVDS1024x768Des_2[ tempal ] ;
7652 break ;
7653 case 3:
7654 return &XGI_LVDS1280x1024Des_1[ tempal ] ;
7655 break ;
7656 case 4:
7657 return &XGI_LVDS1280x1024Des_2[ tempal ] ;
7658 break ;
7659 case 5:
7660 return &XGI_LVDS1400x1050Des_1[ tempal ] ;
7661 break ;
7662 case 6:
7663 return &XGI_LVDS1400x1050Des_2[ tempal ] ;
7664 break ;
7665 case 7:
7666 return &XGI_LVDS1600x1200Des_1[ tempal ] ;
7667 break ;
7668 case 8:
7669 return &XGI_LVDSNoScalingDesData[ tempal ] ;
7670 break ;
7671 case 9:
7672 return &XGI_LVDS1024x768Des_1x75[ tempal ] ;
7673 break ;
7674 case 10:
7675 return &XGI_LVDS1024x768Des_3x75[ tempal ] ;
7676 break ;
7677 case 11:
7678 return &XGI_LVDS1024x768Des_2x75[ tempal ] ;
7679 break;
7680 case 12:
7681 return &XGI_LVDS1280x1024Des_1x75[ tempal ] ;
7682 break ;
7683 case 13:
7684 return &XGI_LVDS1280x1024Des_2x75[ tempal ] ;
7685 break ;
7686 case 14:
7687 return &XGI_LVDSNoScalingDesDatax75[ tempal ] ;
7688 break ;
7689 default:
7690 break ;
7691 }
7692 }
7693 else if ( table == 4 )
7694 {
7695 switch( tempdi[ i ].DATAPTR )
7696 {
7697 case 0:
7698 return &XGI_ExtLCD1024x768Data[ tempal ] ;
7699 break ;
7700 case 1:
7701 return &XGI_StLCD1024x768Data[ tempal ] ;
7702 break ;
7703 case 2:
7704 return &XGI_CetLCD1024x768Data[ tempal ] ;
7705 break ;
7706 case 3:
7707 return &XGI_ExtLCD1280x1024Data[ tempal ] ;
7708 break ;
7709 case 4:
7710 return &XGI_StLCD1280x1024Data[ tempal ] ;
7711 break ;
7712 case 5:
7713 return &XGI_CetLCD1280x1024Data[ tempal ] ;
7714 break ;
7715 case 6:
7716 return &XGI_ExtLCD1400x1050Data[ tempal ] ;
7717 break ;
7718 case 7:
7719 return &XGI_StLCD1400x1050Data[ tempal ] ;
7720 break ;
7721 case 8:
7722 return &XGI_CetLCD1400x1050Data[ tempal ] ;
7723 break ;
7724 case 9:
7725 return &XGI_ExtLCD1600x1200Data[ tempal ] ;
7726 break ;
7727 case 10:
7728 return &XGI_StLCD1600x1200Data[ tempal ] ;
7729 break ;
7730 case 11:
7731 return &XGI_NoScalingData[ tempal ] ;
7732 break ;
7733 case 12:
7734 return &XGI_ExtLCD1024x768x75Data[ tempal ] ;
7735 break ;
7736 case 13:
7737 return &XGI_ExtLCD1024x768x75Data[ tempal ] ;
7738 break ;
7739 case 14:
7740 return &XGI_CetLCD1024x768x75Data[ tempal ] ;
7741 break ;
7742 case 15:
7743 return &XGI_ExtLCD1280x1024x75Data[ tempal ] ;
7744 break ;
7745 case 16:
7746 return &XGI_StLCD1280x1024x75Data[ tempal ] ;
7747 break;
7748 case 17:
7749 return &XGI_CetLCD1280x1024x75Data[ tempal ] ;
7750 break;
7751 case 18:
7752 return &XGI_NoScalingDatax75[ tempal ] ;
7753 break ;
7754 default:
7755 break ;
7756 }
7757 }
7758 else if ( table == 5 )
7759 {
7760 switch( tempdi[ i ].DATAPTR )
7761 {
7762 case 0:
7763 return &XGI_ExtLCDDes1024x768Data[ tempal ] ;
7764 break ;
7765 case 1:
7766 return &XGI_StLCDDes1024x768Data[ tempal ] ;
7767 break ;
7768 case 2:
7769 return &XGI_CetLCDDes1024x768Data[ tempal ] ;
7770 break ;
7771 case 3:
7772 if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) )
7773 return &XGI_ExtLCDDLDes1280x1024Data[ tempal ] ;
7774 else
7775 return &XGI_ExtLCDDes1280x1024Data[ tempal ] ;
7776 break ;
7777 case 4:
7778 if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) )
7779 return &XGI_StLCDDLDes1280x1024Data[ tempal ] ;
7780 else
7781 return &XGI_StLCDDes1280x1024Data[ tempal ] ;
7782 break ;
7783 case 5:
7784 if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) )
7785 return &XGI_CetLCDDLDes1280x1024Data[ tempal ] ;
7786 else
7787 return &XGI_CetLCDDes1280x1024Data[ tempal ] ;
7788 break ;
7789 case 6:
7790 if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) )
7791 return &XGI_ExtLCDDLDes1400x1050Data[ tempal ] ;
7792 else
7793 return &XGI_ExtLCDDes1400x1050Data[ tempal ] ;
7794 break ;
7795 case 7:
7796 if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) )
7797 return &XGI_StLCDDLDes1400x1050Data[ tempal ] ;
7798 else
7799 return &XGI_StLCDDes1400x1050Data[ tempal ] ;
7800 break ;
7801 case 8:
7802 return &XGI_CetLCDDes1400x1050Data[ tempal ] ;
7803 break ;
7804 case 9:
7805 return &XGI_CetLCDDes1400x1050Data2[ tempal ] ;
7806 break ;
7807 case 10:
7808 if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) )
7809 return &XGI_ExtLCDDLDes1600x1200Data[ tempal ] ;
7810 else
7811 return &XGI_ExtLCDDes1600x1200Data[ tempal ] ;
7812 break ;
7813 case 11:
7814 if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) )
7815 return &XGI_StLCDDLDes1600x1200Data[ tempal ] ;
7816 else
7817 return &XGI_StLCDDes1600x1200Data[ tempal ] ;
7818 break ;
7819 case 12:
7820 return &XGI_NoScalingDesData[ tempal ] ;
7821 break;
7822 case 13:
7823 return &XGI_ExtLCDDes1024x768x75Data[ tempal ] ;
7824 break ;
7825 case 14:
7826 return &XGI_StLCDDes1024x768x75Data[ tempal ] ;
7827 break ;
7828 case 15:
7829 return &XGI_CetLCDDes1024x768x75Data[ tempal ] ;
7830 break ;
7831 case 16:
7832 if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) )
7833 return &XGI_ExtLCDDLDes1280x1024x75Data[ tempal ] ;
7834 else
7835 return &XGI_ExtLCDDes1280x1024x75Data[ tempal ] ;
7836 break ;
7837 case 17:
7838 if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) )
7839 return &XGI_StLCDDLDes1280x1024x75Data[ tempal ] ;
7840 else
7841 return &XGI_StLCDDes1280x1024x75Data[ tempal ] ;
7842 break ;
7843 case 18:
7844 if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) )
7845 return &XGI_CetLCDDLDes1280x1024x75Data[ tempal ] ;
7846 else
7847 return &XGI_CetLCDDes1280x1024x75Data[ tempal ] ;
7848 break ;
7849 case 19:
7850 return &XGI_NoScalingDesDatax75[ tempal ] ;
7851 break ;
7852 default:
7853 break ;
7854 }
7855 }
7856 else if ( table == 6 )
7857 {
7858 switch( tempdi[ i ].DATAPTR )
7859 {
7860 case 0:
7861 return &XGI_CH7017LV1024x768[ tempal ] ;
7862 break ;
7863 case 1:
7864 return &XGI_CH7017LV1400x1050[ tempal ] ;
7865 break ;
7866 default:
7867 break ;
7868 }
7869 }
7870 return 0 ;
7871}
7872
7873
7874/* --------------------------------------------------------------------- */
7875/* Function : XGI_GetTVPtr */
7876/* Input : */
7877/* Output : */
7878/* Description : */
7879/* --------------------------------------------------------------------- */
7880void* XGI_GetTVPtr (USHORT BX,USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
7881{
7882 USHORT i , tempdx , tempbx , tempal , modeflag , table ;
7883 XGI330_TVDataTablStruct *tempdi = 0 ;
7884
7885 tempbx = BX ;
7886
7887 if ( ModeNo <= 0x13 )
7888 {
7889 modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
7890 tempal = pVBInfo->SModeIDTable[ ModeIdIndex ].St_CRT2CRTC ;
7891 }
7892 else
7893 {
7894 modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
7895 tempal = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT2CRTC ;
7896 }
7897
7898 tempal = tempal & 0x3f ;
7899 table = tempbx ;
7900
7901 switch( tempbx )
7902 {
7903 case 0:
7904 tempdi = 0 ; /*EPLCHTVCRT1Ptr_H;*/
7905 if ( pVBInfo->IF_DEF_CH7007 == 1 )
7906 {
7907 tempdi = XGI_EPLCHTVCRT1Ptr;
7908 }
7909 break ;
7910 case 1:
7911 tempdi = 0 ; /*EPLCHTVCRT1Ptr_V;*/
7912 if ( pVBInfo->IF_DEF_CH7007 == 1 )
7913 {
7914 tempdi = XGI_EPLCHTVCRT1Ptr;
7915 }
7916 break ;
7917 case 2:
7918 tempdi = XGI_EPLCHTVDataPtr ;
7919 break ;
7920 case 3:
7921 tempdi = 0 ;
7922 break ;
7923 case 4:
7924 tempdi = XGI_TVDataTable ;
7925 break ;
7926 case 5:
7927 tempdi = 0 ;
7928 break ;
7929 case 6:
7930 tempdi = XGI_EPLCHTVRegPtr ;
7931 break ;
7932 default:
7933 break ;
7934 }
7935
7936 if ( tempdi == 0x00 ) /* OEMUtil */
7937 return( 0 ) ;
7938
7939 tempdx = pVBInfo->TVInfo ;
7940
7941 if ( pVBInfo->VBInfo & SetInSlaveMode )
7942 tempdx = tempdx | SetTVLockMode ;
7943
7944 if ( modeflag & HalfDCLK )
7945 tempdx = tempdx | SetTVLowResolution ;
7946
7947 i = 0 ;
7948
7949 while( tempdi[ i ].MASK != 0xffff )
7950 {
7951 if ( ( tempdx & tempdi[ i ].MASK ) == tempdi[ i ].CAP )
7952 break ;
7953 i++ ;
7954 }
7955
7956 if ( table == 0x00 ) /* 07/05/22 */
7957 {
7958#ifdef WIN2000
7959 if ( pVBInfo->IF_DEF_CH7007 == 1 )
7960 {
7961 switch( tempdi[ i ].DATAPTR )
7962 {
7963 case 0:
7964 return &CH7007TVCRT1UNTSC_H[ tempal ] ;
7965 break ;
7966 case 1:
7967 return &CH7007TVCRT1ONTSC_H[ tempal ] ;
7968 break ;
7969 case 2:
7970 return &CH7007TVCRT1UPAL_H[ tempal ] ;
7971 break ;
7972 case 3:
7973 return &CH7007TVCRT1OPAL_H[ tempal ] ;
7974 break ;
7975 default:
7976 break ;
7977 }
7978 }
7979#endif
7980 }
7981 else if ( table == 0x01 )
7982 {
7983#ifdef WIN2000
7984 if ( pVBInfo->IF_DEF_CH7007 == 1 )
7985 {
7986 switch( tempdi[ i ].DATAPTR )
7987 {
7988 case 0:
7989 return &CH7007TVCRT1UNTSC_V[ tempal ] ;
7990 break ;
7991 case 1:
7992 return &CH7007TVCRT1ONTSC_V[ tempal ] ;
7993 break ;
7994 case 2:
7995 return &CH7007TVCRT1UPAL_V[ tempal ] ;
7996 break ;
7997 case 3:
7998 return &CH7007TVCRT1OPAL_V[ tempal ] ;
7999 break ;
8000 default:
8001 break ;
8002 }
8003 }
8004#endif
8005 }
8006 else if ( table == 0x04 )
8007 {
8008 switch( tempdi[ i ].DATAPTR )
8009 {
8010 case 0:
8011 return &XGI_ExtPALData[ tempal ] ;
8012 break ;
8013 case 1:
8014 return &XGI_ExtNTSCData[ tempal ] ;
8015 break ;
8016 case 2:
8017 return &XGI_StPALData[ tempal ] ;
8018 break ;
8019 case 3:
8020 return &XGI_StNTSCData[ tempal ] ;
8021 break ;
8022 case 4:
8023 return &XGI_ExtHiTVData[ tempal ] ;
8024 break ;
8025 case 5:
8026 return &XGI_St2HiTVData[ tempal ] ;
8027 break ;
8028 case 6:
8029 return &XGI_ExtYPbPr525iData[ tempal ] ;
8030 break ;
8031 case 7:
8032 return &XGI_ExtYPbPr525pData[ tempal ] ;
8033 break ;
8034 case 8:
8035 return &XGI_ExtYPbPr750pData[ tempal ] ;
8036 break ;
8037 case 9:
8038 return &XGI_StYPbPr525iData[ tempal ] ;
8039 break ;
8040 case 10:
8041 return &XGI_StYPbPr525pData[ tempal ] ;
8042 break ;
8043 case 11:
8044 return &XGI_StYPbPr750pData[ tempal ] ;
8045 break;
8046 case 12: /* avoid system hang */
8047 return &XGI_ExtNTSCData[ tempal ] ;
8048 break ;
8049 case 13:
8050 return &XGI_St1HiTVData[ tempal ] ;
8051 break ;
8052 default:
8053 break ;
8054 }
8055 }
8056 else if( table == 0x02 )
8057 {
8058 switch( tempdi[ i ].DATAPTR )
8059 {
8060 case 0:
8061 return &XGI_CHTVUNTSCData[ tempal ] ;
8062 break ;
8063 case 1:
8064 return &XGI_CHTVONTSCData[ tempal ] ;
8065 break ;
8066 case 2:
8067 return &XGI_CHTVUPALData[ tempal ] ;
8068 break ;
8069 case 3:
8070 return &XGI_CHTVOPALData[ tempal ] ;
8071 break ;
8072 default:
8073 break ;
8074 }
8075 }
8076 else if( table == 0x06 )
8077 {
8078#ifdef WIN2000
8079 if ( pVBInfo->IF_DEF_CH7007 == 1 )
8080 {
8081 /* VideoDebugPrint((0, "XGI_GetTVPtr: pVBInfo->IF_DEF_CH7007==1\n")); */
8082 switch( tempdi[ i ].DATAPTR )
8083 {
8084 case 0:
8085 return &CH7007TVReg_UNTSC[ tempal ] ;
8086 break ;
8087 case 1:
8088 return &CH7007TVReg_ONTSC[ tempal ] ;
8089 break ;
8090 case 2:
8091 return &CH7007TVReg_UPAL[ tempal ] ;
8092 break ;
8093 case 3:
8094 return &CH7007TVReg_OPAL[ tempal ] ;
8095 break ;
8096 default:
8097 break ;
8098 }
8099 }
8100 else
8101 {
8102 switch( tempdi[ i ].DATAPTR )
8103 {
8104 case 0:
8105 return &XGI_CHTVRegUNTSC[ tempal ] ;
8106 break ;
8107 case 1:
8108 return &XGI_CHTVRegONTSC[ tempal ] ;
8109 break ;
8110 case 2:
8111 return &XGI_CHTVRegUPAL[ tempal ] ;
8112 break ;
8113 case 3:
8114 return &XGI_CHTVRegOPAL[ tempal ] ;
8115 break ;
8116 default:
8117 break ;
8118 }
8119 }
8120#endif
8121 }
8122 return( 0 ) ;
8123}
8124
8125
8126/* --------------------------------------------------------------------- */
8127/* Function : XGI_BacklightByDrv */
8128/* Input : */
8129/* Output : TRUE -> Skip backlight control */
8130/* Description : */
8131/* --------------------------------------------------------------------- */
8132BOOLEAN XGI_BacklightByDrv( PVB_DEVICE_INFO pVBInfo )
8133{
8134 UCHAR tempah ;
8135
8136 tempah = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x3A ) ;
8137 if ( tempah & BacklightControlBit )
8138 return TRUE ;
8139 else
8140 return FALSE ;
8141}
8142
8143
8144/* --------------------------------------------------------------------- */
8145/* Function : XGI_FirePWDDisable */
8146/* Input : */
8147/* Output : */
8148/* Description : Turn off VDD & Backlight : Fire disable procedure */
8149/* --------------------------------------------------------------------- */
8150/*
8151void XGI_FirePWDDisable( PVB_DEVICE_INFO pVBInfo )
8152{
8153 XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x26 , 0x00 , 0xFC ) ;
8154}
8155*/
8156
8157/* --------------------------------------------------------------------- */
8158/* Function : XGI_FirePWDEnable */
8159/* Input : */
8160/* Output : */
8161/* Description : Turn on VDD & Backlight : Fire enable procedure */
8162/* --------------------------------------------------------------------- */
8163void XGI_FirePWDEnable(PVB_DEVICE_INFO pVBInfo )
8164{
8165 XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x26 , 0x03 , 0xFC ) ;
8166}
8167
8168
8169/* --------------------------------------------------------------------- */
8170/* Function : XGI_EnableGatingCRT */
8171/* Input : */
8172/* Output : */
8173/* Description : */
8174/* --------------------------------------------------------------------- */
8175void XGI_EnableGatingCRT(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
8176{
8177 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x63 , 0xBF , 0x40 ) ;
8178}
8179
8180
8181/* --------------------------------------------------------------------- */
8182/* Function : XGI_DisableGatingCRT */
8183/* Input : */
8184/* Output : */
8185/* Description : */
8186/* --------------------------------------------------------------------- */
8187void XGI_DisableGatingCRT(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
8188{
8189
8190 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x63 , 0xBF , 0x00 ) ;
8191}
8192
8193
8194/* --------------------------------------------------------------------- */
8195/* Function : XGI_SetPanelDelay */
8196/* Input : */
8197/* Output : */
8198/* Description : */
8199/* I/P : bl : 1 ; T1 : the duration between CPL on and signal on */
8200/* : bl : 2 ; T2 : the duration signal on and Vdd on */
8201/* : bl : 3 ; T3 : the duration between CPL off and signal off */
8202/* : bl : 4 ; T4 : the duration signal off and Vdd off */
8203/* --------------------------------------------------------------------- */
8204void XGI_SetPanelDelay(USHORT tempbl, PVB_DEVICE_INFO pVBInfo)
8205{
8206 USHORT index ;
8207
8208 index = XGI_GetLCDCapPtr(pVBInfo) ;
8209
8210 if ( tempbl == 1 )
8211 XGINew_LCD_Wait_Time( pVBInfo->LCDCapList[ index ].PSC_S1, pVBInfo ) ;
8212
8213 if ( tempbl == 2 )
8214 XGINew_LCD_Wait_Time( pVBInfo->LCDCapList[ index ].PSC_S2, pVBInfo ) ;
8215
8216 if ( tempbl == 3 )
8217 XGINew_LCD_Wait_Time( pVBInfo->LCDCapList[ index ].PSC_S3, pVBInfo ) ;
8218
8219 if ( tempbl == 4 )
8220 XGINew_LCD_Wait_Time( pVBInfo->LCDCapList[ index ].PSC_S4, pVBInfo ) ;
8221}
8222
8223
8224/* --------------------------------------------------------------------- */
8225/* Function : XGI_SetPanelPower */
8226/* Input : */
8227/* Output : */
8228/* Description : */
8229/* I/O : ah = 0011b = 03h ; Backlight on, Power on */
8230/* = 0111b = 07h ; Backlight on, Power off */
8231/* = 1011b = 0Bh ; Backlight off, Power on */
8232/* = 1111b = 0Fh ; Backlight off, Power off */
8233/* --------------------------------------------------------------------- */
8234void XGI_SetPanelPower(USHORT tempah,USHORT tempbl, PVB_DEVICE_INFO pVBInfo)
8235{
8236 if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
8237 XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x26 , tempbl , tempah ) ;
8238 else
8239 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x11 , tempbl , tempah ) ;
8240}
8241
8242UCHAR XG21GPIODataTransfer(UCHAR ujDate)
8243{
8244 UCHAR ujRet = 0;
8245 UCHAR i = 0;
8246
8247 for (i=0; i<8; i++)
8248 {
8249 ujRet = ujRet << 1;
8250 /* ujRet |= GETBITS(ujDate >> i, 0:0); */
8251 ujRet |= (ujDate >> i) & 1;
8252 }
8253
8254 return ujRet;
8255}
8256
8257/*----------------------------------------------------------------------------*/
8258/* output */
8259/* bl[5] : LVDS signal */
8260/* bl[1] : LVDS backlight */
8261/* bl[0] : LVDS VDD */
8262/*----------------------------------------------------------------------------*/
8263UCHAR XGI_XG21GetPSCValue(PVB_DEVICE_INFO pVBInfo)
8264{
8265 UCHAR CR4A,temp;
8266
8267 CR4A = XGINew_GetReg1( pVBInfo->P3d4 , 0x4A ) ;
8268 XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~0x23 ) ; /* enable GPIO write */
8269
8270 temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x48 ) ;
8271
8272 temp = XG21GPIODataTransfer(temp);
8273 temp &= 0x23;
8274 XGINew_SetReg1( pVBInfo->P3d4 , 0x4A , CR4A ) ;
8275 return temp;
8276}
8277
8278/*----------------------------------------------------------------------------*/
8279/* output */
8280/* bl[5] : LVDS signal */
8281/* bl[1] : LVDS backlight */
8282/* bl[0] : LVDS VDD */
8283/*----------------------------------------------------------------------------*/
8284UCHAR XGI_XG27GetPSCValue(PVB_DEVICE_INFO pVBInfo)
8285{
8286 UCHAR CR4A,CRB4,temp;
8287
8288 CR4A = XGINew_GetReg1( pVBInfo->P3d4 , 0x4A ) ;
8289 XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~0x0C ) ; /* enable GPIO write */
8290
8291 temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x48 ) ;
8292
8293 temp &= 0x0C;
8294 temp >>= 2;
8295 XGINew_SetReg1( pVBInfo->P3d4 , 0x4A , CR4A ) ;
8296 CRB4 = XGINew_GetReg1( pVBInfo->P3d4 , 0xB4 ) ;
8297 temp |= ((CRB4&0x04)<<3);
8298 return temp;
8299}
8300/*----------------------------------------------------------------------------*/
8301/* input */
8302/* bl[5] : 1;LVDS signal on */
8303/* bl[1] : 1;LVDS backlight on */
8304/* bl[0] : 1:LVDS VDD on */
8305/* bh: 100000b : clear bit 5, to set bit5 */
8306/* 000010b : clear bit 1, to set bit1 */
8307/* 000001b : clear bit 0, to set bit0 */
8308/*----------------------------------------------------------------------------*/
8309void XGI_XG21BLSignalVDD(USHORT tempbh,USHORT tempbl, PVB_DEVICE_INFO pVBInfo)
8310{
8311 UCHAR CR4A,temp;
8312
8313 CR4A = XGINew_GetReg1( pVBInfo->P3d4 , 0x4A ) ;
8314 tempbh &= 0x23;
8315 tempbl &= 0x23;
8316 XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~tempbh ) ; /* enable GPIO write */
8317
8318 if (tempbh&0x20)
8319 {
8320 temp = (tempbl>>4)&0x02;
8321
8322 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0xB4 , ~0x02 , temp) ; /* CR B4[1] */
8323
8324 }
8325
8326 temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x48 ) ;
8327
8328 temp = XG21GPIODataTransfer(temp);
8329 temp &= ~tempbh;
8330 temp |= tempbl;
8331 XGINew_SetReg1( pVBInfo->P3d4 , 0x48 , temp ) ;
8332}
8333
8334void XGI_XG27BLSignalVDD(USHORT tempbh,USHORT tempbl, PVB_DEVICE_INFO pVBInfo)
8335{
8336 UCHAR CR4A,temp;
8337 USHORT tempbh0,tempbl0;
8338
8339 tempbh0 = tempbh;
8340 tempbl0 = tempbl;
8341 tempbh0 &= 0x20;
8342 tempbl0 &= 0x20;
8343 tempbh0 >>= 3;
8344 tempbl0 >>= 3;
8345
8346 if (tempbh&0x20)
8347 {
8348 temp = (tempbl>>4)&0x02;
8349
8350 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0xB4 , ~0x02 , temp) ; /* CR B4[1] */
8351
8352 }
8353 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0xB4 , ~tempbh0 , tempbl0 ) ;
8354
8355 CR4A = XGINew_GetReg1( pVBInfo->P3d4 , 0x4A ) ;
8356 tempbh &= 0x03;
8357 tempbl &= 0x03;
8358 tempbh <<= 2;
8359 tempbl <<= 2; /* GPIOC,GPIOD */
8360 XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~tempbh ) ; /* enable GPIO write */
8361 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x48 , ~tempbh , tempbl ) ;
8362}
8363
8364/* --------------------------------------------------------------------- */
8365USHORT XGI_GetLVDSOEMTableIndex(PVB_DEVICE_INFO pVBInfo)
8366{
8367 USHORT index ;
8368
8369 index = XGINew_GetReg1( pVBInfo->P3d4 , 0x36 ) ;
8370 if (index<sizeof(XGI21_LCDCapList)/sizeof(XGI21_LVDSCapStruct))
8371 {
8372 return index;
8373 }
8374 return 0;
8375}
8376
8377/* --------------------------------------------------------------------- */
8378/* Function : XGI_XG21SetPanelDelay */
8379/* Input : */
8380/* Output : */
8381/* Description : */
8382/* I/P : bl : 1 ; T1 : the duration between CPL on and signal on */
8383/* : bl : 2 ; T2 : the duration signal on and Vdd on */
8384/* : bl : 3 ; T3 : the duration between CPL off and signal off */
8385/* : bl : 4 ; T4 : the duration signal off and Vdd off */
8386/* --------------------------------------------------------------------- */
8387void XGI_XG21SetPanelDelay(USHORT tempbl, PVB_DEVICE_INFO pVBInfo)
8388{
8389 USHORT index ;
8390
8391 index = XGI_GetLVDSOEMTableIndex( pVBInfo );
8392 if ( tempbl == 1 )
8393 XGINew_LCD_Wait_Time( pVBInfo->XG21_LVDSCapList[ index ].PSC_S1, pVBInfo ) ;
8394
8395 if ( tempbl == 2 )
8396 XGINew_LCD_Wait_Time( pVBInfo->XG21_LVDSCapList[ index ].PSC_S2, pVBInfo ) ;
8397
8398 if ( tempbl == 3 )
8399 XGINew_LCD_Wait_Time( pVBInfo->XG21_LVDSCapList[ index ].PSC_S3, pVBInfo ) ;
8400
8401 if ( tempbl == 4 )
8402 XGINew_LCD_Wait_Time( pVBInfo->XG21_LVDSCapList[ index ].PSC_S4, pVBInfo ) ;
8403}
8404
8405BOOLEAN XGI_XG21CheckLVDSMode(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
8406{
8407 USHORT xres ,
8408 yres ,
8409 colordepth ,
8410 modeflag ,
8411 resindex ,
8412 lvdstableindex;
8413
8414 resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo ) ;
8415 if ( ModeNo <= 0x13 )
8416 {
8417 xres = pVBInfo->StResInfo[ resindex ].HTotal ;
8418 yres = pVBInfo->StResInfo[ resindex ].VTotal ;
8419 modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */
8420 }
8421 else
8422 {
8423 xres = pVBInfo->ModeResInfo[ resindex ].HTotal ; /* xres->ax */
8424 yres = pVBInfo->ModeResInfo[ resindex ].VTotal ; /* yres->bx */
8425 modeflag = pVBInfo->EModeIDTable[ ModeIdIndex].Ext_ModeFlag ; /* si+St_ModeFlag */
8426 }
8427
8428 if ( !( modeflag & Charx8Dot ) )
8429 {
8430 xres /= 9;
8431 xres *= 8;
8432 }
8433
8434 if ( ModeNo > 0x13 )
8435 {
8436 if ( ( ModeNo>0x13 ) && ( modeflag & HalfDCLK ) )
8437 {
8438 xres *= 2 ;
8439 }
8440 if ( ( ModeNo>0x13 ) && ( modeflag & DoubleScanMode ) )
8441 {
8442 yres *= 2 ;
8443 }
8444 }
8445
8446 lvdstableindex = XGI_GetLVDSOEMTableIndex( pVBInfo );
8447 if ( xres > (pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHDE) )
8448 return FALSE;
8449
8450 if ( yres > (pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE) )
8451 return FALSE;
8452
8453 if ( ModeNo > 0x13 )
8454 {
8455 if ( ( xres != (pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHDE) ) ||
8456 ( yres != (pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE)) )
8457 {
8458 colordepth = XGI_GetColorDepth( ModeNo , ModeIdIndex, pVBInfo ) ;
8459 if ( colordepth > 2 )
8460 {
8461 return FALSE;
8462 }
8463 }
8464 }
8465 return TRUE;
8466}
8467
8468void XGI_SetXG21FPBits(PVB_DEVICE_INFO pVBInfo)
8469{
8470 UCHAR temp;
8471
8472 temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x37 ) ; /* D[0] 1: 18bit */
8473 temp = ( temp & 1 ) << 6;
8474 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x06 , ~0x40 , temp ) ; /* SR06[6] 18bit Dither */
8475 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x09 , ~0xc0 , temp | 0x80 ) ; /* SR09[7] enable FP output, SR09[6] 1: sigle 18bits, 0: dual 12bits */
8476
8477}
8478
8479void XGI_SetXG27FPBits(PVB_DEVICE_INFO pVBInfo)
8480{
8481 UCHAR temp;
8482
8483 temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x37 ) ; /* D[1:0] 01: 18bit, 00: dual 12, 10: single 24 */
8484 temp = ( temp & 3 ) << 6;
8485 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x06 , ~0xc0 , temp & 0x80 ) ; /* SR06[7]0: dual 12/1: single 24 [6] 18bit Dither <= 0 h/w recommend */
8486 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x09 , ~0xc0 , temp | 0x80 ) ; /* SR09[7] enable FP output, SR09[6] 1: sigle 18bits, 0: 24bits */
8487
8488}
8489
8490void XGI_SetXG21LVDSPara(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
8491{
8492 UCHAR temp,Miscdata;
8493 USHORT xres ,
8494 yres ,
8495 modeflag ,
8496 resindex ,
8497 lvdstableindex ;
8498 USHORT LVDSHT,LVDSHBS,LVDSHRS,LVDSHRE,LVDSHBE;
8499 USHORT LVDSVT,LVDSVBS,LVDSVRS,LVDSVRE,LVDSVBE;
8500 USHORT value;
8501
8502 lvdstableindex = XGI_GetLVDSOEMTableIndex( pVBInfo );
8503
8504 temp = (UCHAR) ( ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDS_Capability & (LCDPolarity << 8 ) ) >> 8 );
8505 temp &= LCDPolarity;
8506 Miscdata =(UCHAR) XGINew_GetReg2(pVBInfo->P3cc) ;
8507
8508 XGINew_SetReg3( pVBInfo->P3c2 , (Miscdata & 0x3F) | temp ) ;
8509
8510 temp = (UCHAR) ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDS_Capability & LCDPolarity ) ;
8511 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x35 , ~0x80 , temp&0x80 ) ; /* SR35[7] FP VSync polarity */
8512 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x30 , ~0x20 , (temp&0x40)>>1 ) ; /* SR30[5] FP HSync polarity */
8513
8514 XGI_SetXG21FPBits(pVBInfo);
8515 resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo ) ;
8516 if ( ModeNo <= 0x13 )
8517 {
8518 xres = pVBInfo->StResInfo[ resindex ].HTotal ;
8519 yres = pVBInfo->StResInfo[ resindex ].VTotal ;
8520 modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */
8521 }
8522 else
8523 {
8524 xres = pVBInfo->ModeResInfo[ resindex ].HTotal ; /* xres->ax */
8525 yres = pVBInfo->ModeResInfo[ resindex ].VTotal ; /* yres->bx */
8526 modeflag = pVBInfo->EModeIDTable[ ModeIdIndex].Ext_ModeFlag ; /* si+St_ModeFlag */
8527 }
8528
8529 if (!( modeflag & Charx8Dot ))
8530 xres = xres * 8 / 9;
8531
8532 LVDSHT = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHT;
8533
8534 LVDSHBS = xres + ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHDE - xres ) / 2 ;
8535 if ( ( ModeNo<=0x13 ) && ( modeflag & HalfDCLK ) )
8536 {
8537 LVDSHBS -= xres/4 ;
8538 }
8539 if (LVDSHBS > LVDSHT) LVDSHBS -= LVDSHT ;
8540
8541 LVDSHRS = LVDSHBS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHFP ;
8542 if (LVDSHRS > LVDSHT) LVDSHRS -= LVDSHT ;
8543
8544 LVDSHRE = LVDSHRS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHSYNC ;
8545 if (LVDSHRE > LVDSHT) LVDSHRE -= LVDSHT ;
8546
8547 LVDSHBE = LVDSHBS + LVDSHT - pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHDE ;
8548
8549 LVDSVT = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVT;
8550
8551 LVDSVBS = yres + ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE - yres ) / 2 ;
8552 if ( ( ModeNo>0x13 ) && ( modeflag & DoubleScanMode ) )
8553 {
8554 LVDSVBS += yres/2 ;
8555 }
8556 if (LVDSVBS > LVDSVT) LVDSVBS -= LVDSVT ;
8557
8558 LVDSVRS = LVDSVBS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVFP ;
8559 if (LVDSVRS > LVDSVT) LVDSVRS -= LVDSVT ;
8560
8561 LVDSVRE = LVDSVRS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVSYNC ;
8562 if (LVDSVRE > LVDSVT) LVDSVRE -= LVDSVT ;
8563
8564 LVDSVBE = LVDSVBS + LVDSVT - pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE ;
8565
8566 temp = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ;
8567 XGINew_SetReg1( pVBInfo->P3d4 , 0x11 , temp & 0x7f ) ; /* Unlock CRTC */
8568
8569 if (!( modeflag & Charx8Dot ))
8570 {
8571 XGINew_SetRegOR( pVBInfo->P3c4 , 0x1 , 0x1 ) ;
8572 }
8573
8574 /* HT SR0B[1:0] CR00 */
8575 value = ( LVDSHT >> 3 ) - 5;
8576 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0B , ~0x03 , ( value & 0x300 ) >> 8 ) ;
8577 XGINew_SetReg1( pVBInfo->P3d4 , 0x0 , (value & 0xFF) ) ;
8578
8579 /* HBS SR0B[5:4] CR02 */
8580 value = ( LVDSHBS >> 3 ) - 1;
8581 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0B , ~0x30 , ( value & 0x300 ) >> 4 ) ;
8582 XGINew_SetReg1( pVBInfo->P3d4 , 0x2 , (value & 0xFF) ) ;
8583
8584 /* HBE SR0C[1:0] CR05[7] CR03[4:0] */
8585 value = ( LVDSHBE >> 3 ) - 1;
8586 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0C , ~0x03 , ( value & 0xC0 ) >> 6 ) ;
8587 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x05 , ~0x80 , ( value & 0x20 ) << 2 ) ;
8588 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x03 , ~0x1F , value & 0x1F ) ;
8589
8590 /* HRS SR0B[7:6] CR04 */
8591 value = ( LVDSHRS >> 3 ) + 2;
8592 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0B , ~0xC0 , ( value & 0x300 ) >> 2 ) ;
8593 XGINew_SetReg1( pVBInfo->P3d4 , 0x4 , (value & 0xFF) ) ;
8594
8595 /* Panel HRS SR2F[1:0] SR2E[7:0] */
8596 value--;
8597 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x2F , ~0x03 , ( value & 0x300 ) >> 8 ) ;
8598 XGINew_SetReg1( pVBInfo->P3c4 , 0x2E , (value & 0xFF) ) ;
8599
8600 /* HRE SR0C[2] CR05[4:0] */
8601 value = ( LVDSHRE >> 3 ) + 2;
8602 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0C , ~0x04 , ( value & 0x20 ) >> 3 ) ;
8603 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x05 , ~0x1F , value & 0x1F ) ;
8604
8605 /* Panel HRE SR2F[7:2] */
8606 value--;
8607 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x2F , ~0xFC , value << 2 ) ;
8608
8609 /* VT SR0A[0] CR07[5][0] CR06 */
8610 value = LVDSVT - 2 ;
8611 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x01 , ( value & 0x400 ) >> 10 ) ;
8612 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x20 , ( value & 0x200 ) >> 4 ) ;
8613 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x01 , ( value & 0x100 ) >> 8 ) ;
8614 XGINew_SetReg1( pVBInfo->P3d4 , 0x06 , (value & 0xFF) ) ;
8615
8616 /* VBS SR0A[2] CR09[5] CR07[3] CR15 */
8617 value = LVDSVBS - 1 ;
8618 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x04 , ( value & 0x400 ) >> 8 ) ;
8619 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x09 , ~0x20 , ( value & 0x200 ) >> 4 ) ;
8620 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x08 , ( value & 0x100 ) >> 5 ) ;
8621 XGINew_SetReg1( pVBInfo->P3d4 , 0x15 , (value & 0xFF) ) ;
8622
8623 /* VBE SR0A[4] CR16 */
8624 value = LVDSVBE - 1;
8625 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x10 , ( value & 0x100 ) >> 4 ) ;
8626 XGINew_SetReg1( pVBInfo->P3d4 , 0x16 , (value & 0xFF) ) ;
8627
8628 /* VRS SR0A[3] CR7[7][2] CR10 */
8629 value = LVDSVRS - 1 ;
8630 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x08 , ( value & 0x400 ) >> 7 ) ;
8631 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x80 , ( value & 0x200 ) >> 2 ) ;
8632 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x04 , ( value & 0x100 ) >> 6 ) ;
8633 XGINew_SetReg1( pVBInfo->P3d4 , 0x10 , (value & 0xFF) ) ;
8634
8635 /* Panel VRS SR3F[1:0] SR34[7:0] SR33[0] */
8636 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x3F , ~0x03 , ( value & 0x600 ) >> 9 ) ;
8637 XGINew_SetReg1( pVBInfo->P3c4 , 0x34 , (value >> 1) & 0xFF ) ;
8638 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x33 , ~0x01 , value & 0x01 ) ;
8639
8640 /* VRE SR0A[5] CR11[3:0] */
8641 value = LVDSVRE - 1;
8642 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x20 , ( value & 0x10 ) << 1 ) ;
8643 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x11 , ~0x0F , value & 0x0F ) ;
8644
8645 /* Panel VRE SR3F[7:2] */ /* SR3F[7] has to be 0, h/w bug */
8646 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x3F , ~0xFC , ( value << 2 ) & 0x7C ) ;
8647
8648 for ( temp=0, value = 0; temp < 3; temp++)
8649 {
8650
8651 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x31 , ~0x30 , value ) ;
8652 XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , pVBInfo->XG21_LVDSCapList[lvdstableindex].VCLKData1) ;
8653 XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , pVBInfo->XG21_LVDSCapList[lvdstableindex].VCLKData2) ;
8654 value += 0x10;
8655 }
8656
8657 if (!( modeflag & Charx8Dot ))
8658 {
8659 XGINew_GetReg2( pVBInfo->P3da ) ; /* reset 3da */
8660 XGINew_SetReg3( pVBInfo->P3c0 , 0x13 ) ; /* set index */
8661 XGINew_SetReg3( pVBInfo->P3c0 , 0x00 ) ; /* set data, panning = 0, shift left 1 dot*/
8662
8663 XGINew_GetReg2( pVBInfo->P3da ) ; /* Enable Attribute */
8664 XGINew_SetReg3( pVBInfo->P3c0 , 0x20 ) ;
8665
8666 XGINew_GetReg2( pVBInfo->P3da ) ; /* reset 3da */
8667 }
8668
8669
8670}
8671
8672/* no shadow case */
8673void XGI_SetXG27LVDSPara(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
8674{
8675 UCHAR temp,Miscdata;
8676 USHORT xres ,
8677 yres ,
8678 modeflag ,
8679 resindex ,
8680 lvdstableindex ;
8681 USHORT LVDSHT,LVDSHBS,LVDSHRS,LVDSHRE,LVDSHBE;
8682 USHORT LVDSVT,LVDSVBS,LVDSVRS,LVDSVRE,LVDSVBE;
8683 USHORT value;
8684
8685 lvdstableindex = XGI_GetLVDSOEMTableIndex( pVBInfo );
8686 temp = (UCHAR) ( ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDS_Capability & (LCDPolarity << 8 ) ) >> 8 );
8687 temp &= LCDPolarity;
8688 Miscdata =(UCHAR) XGINew_GetReg2(pVBInfo->P3cc) ;
8689
8690 XGINew_SetReg3( pVBInfo->P3c2 , (Miscdata & 0x3F) | temp ) ;
8691
8692 temp = (UCHAR) ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDS_Capability & LCDPolarity ) ;
8693 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x35 , ~0x80 , temp&0x80 ) ; /* SR35[7] FP VSync polarity */
8694 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x30 , ~0x20 , (temp&0x40)>>1 ) ; /* SR30[5] FP HSync polarity */
8695
8696 XGI_SetXG27FPBits(pVBInfo);
8697 resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo ) ;
8698 if ( ModeNo <= 0x13 )
8699 {
8700 xres = pVBInfo->StResInfo[ resindex ].HTotal ;
8701 yres = pVBInfo->StResInfo[ resindex ].VTotal ;
8702 modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */
8703 }
8704 else
8705 {
8706 xres = pVBInfo->ModeResInfo[ resindex ].HTotal ; /* xres->ax */
8707 yres = pVBInfo->ModeResInfo[ resindex ].VTotal ; /* yres->bx */
8708 modeflag = pVBInfo->EModeIDTable[ ModeIdIndex].Ext_ModeFlag ; /* si+St_ModeFlag */
8709 }
8710
8711 if (!( modeflag & Charx8Dot ))
8712 xres = xres * 8 / 9;
8713
8714 LVDSHT = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHT;
8715
8716 LVDSHBS = xres + ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHDE - xres ) / 2 ;
8717 if ( ( ModeNo<=0x13 ) && ( modeflag & HalfDCLK ) )
8718 {
8719 LVDSHBS -= xres/4 ;
8720 }
8721 if (LVDSHBS > LVDSHT) LVDSHBS -= LVDSHT ;
8722
8723 LVDSHRS = LVDSHBS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHFP ;
8724 if (LVDSHRS > LVDSHT) LVDSHRS -= LVDSHT ;
8725
8726 LVDSHRE = LVDSHRS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHSYNC ;
8727 if (LVDSHRE > LVDSHT) LVDSHRE -= LVDSHT ;
8728
8729 LVDSHBE = LVDSHBS + LVDSHT - pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHDE ;
8730
8731 LVDSVT = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVT;
8732
8733 LVDSVBS = yres + ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE - yres ) / 2 ;
8734 if ( ( ModeNo>0x13 ) && ( modeflag & DoubleScanMode ) )
8735 {
8736 LVDSVBS += yres/2 ;
8737 }
8738 if (LVDSVBS > LVDSVT) LVDSVBS -= LVDSVT ;
8739
8740 LVDSVRS = LVDSVBS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVFP ;
8741 if (LVDSVRS > LVDSVT) LVDSVRS -= LVDSVT ;
8742
8743 LVDSVRE = LVDSVRS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVSYNC ;
8744 if (LVDSVRE > LVDSVT) LVDSVRE -= LVDSVT ;
8745
8746 LVDSVBE = LVDSVBS + LVDSVT - pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE ;
8747
8748 temp = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ;
8749 XGINew_SetReg1( pVBInfo->P3d4 , 0x11 , temp & 0x7f ) ; /* Unlock CRTC */
8750
8751 if (!( modeflag & Charx8Dot ))
8752 {
8753 XGINew_SetRegOR( pVBInfo->P3c4 , 0x1 , 0x1 ) ;
8754 }
8755
8756 /* HT SR0B[1:0] CR00 */
8757 value = ( LVDSHT >> 3 ) - 5;
8758 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0B , ~0x03 , ( value & 0x300 ) >> 8 ) ;
8759 XGINew_SetReg1( pVBInfo->P3d4 , 0x0 , (value & 0xFF) ) ;
8760
8761 /* HBS SR0B[5:4] CR02 */
8762 value = ( LVDSHBS >> 3 ) - 1;
8763 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0B , ~0x30 , ( value & 0x300 ) >> 4 ) ;
8764 XGINew_SetReg1( pVBInfo->P3d4 , 0x2 , (value & 0xFF) ) ;
8765
8766 /* HBE SR0C[1:0] CR05[7] CR03[4:0] */
8767 value = ( LVDSHBE >> 3 ) - 1;
8768 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0C , ~0x03 , ( value & 0xC0 ) >> 6 ) ;
8769 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x05 , ~0x80 , ( value & 0x20 ) << 2 ) ;
8770 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x03 , ~0x1F , value & 0x1F ) ;
8771
8772 /* HRS SR0B[7:6] CR04 */
8773 value = ( LVDSHRS >> 3 ) + 2;
8774 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0B , ~0xC0 , ( value & 0x300 ) >> 2 ) ;
8775 XGINew_SetReg1( pVBInfo->P3d4 , 0x4 , (value & 0xFF) ) ;
8776
8777 /* Panel HRS SR2F[1:0] SR2E[7:0] */
8778 value--;
8779 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x2F , ~0x03 , ( value & 0x300 ) >> 8 ) ;
8780 XGINew_SetReg1( pVBInfo->P3c4 , 0x2E , (value & 0xFF) ) ;
8781
8782 /* HRE SR0C[2] CR05[4:0] */
8783 value = ( LVDSHRE >> 3 ) + 2;
8784 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0C , ~0x04 , ( value & 0x20 ) >> 3 ) ;
8785 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x05 , ~0x1F , value & 0x1F ) ;
8786
8787 /* Panel HRE SR2F[7:2] */
8788 value--;
8789 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x2F , ~0xFC , value << 2 ) ;
8790
8791 /* VT SR0A[0] CR07[5][0] CR06 */
8792 value = LVDSVT - 2 ;
8793 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x01 , ( value & 0x400 ) >> 10 ) ;
8794 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x20 , ( value & 0x200 ) >> 4 ) ;
8795 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x01 , ( value & 0x100 ) >> 8 ) ;
8796 XGINew_SetReg1( pVBInfo->P3d4 , 0x06 , (value & 0xFF) ) ;
8797
8798 /* VBS SR0A[2] CR09[5] CR07[3] CR15 */
8799 value = LVDSVBS - 1 ;
8800 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x04 , ( value & 0x400 ) >> 8 ) ;
8801 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x09 , ~0x20 , ( value & 0x200 ) >> 4 ) ;
8802 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x08 , ( value & 0x100 ) >> 5 ) ;
8803 XGINew_SetReg1( pVBInfo->P3d4 , 0x15 , (value & 0xFF) ) ;
8804
8805 /* VBE SR0A[4] CR16 */
8806 value = LVDSVBE - 1;
8807 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x10 , ( value & 0x100 ) >> 4 ) ;
8808 XGINew_SetReg1( pVBInfo->P3d4 , 0x16 , (value & 0xFF) ) ;
8809
8810 /* VRS SR0A[3] CR7[7][2] CR10 */
8811 value = LVDSVRS - 1 ;
8812 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x08 , ( value & 0x400 ) >> 7 ) ;
8813 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x80 , ( value & 0x200 ) >> 2 ) ;
8814 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x04 , ( value & 0x100 ) >> 6 ) ;
8815 XGINew_SetReg1( pVBInfo->P3d4 , 0x10 , (value & 0xFF) ) ;
8816
8817 /* Panel VRS SR35[2:0] SR34[7:0] */
8818 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x35 , ~0x07 , ( value & 0x700 ) >> 8 ) ;
8819 XGINew_SetReg1( pVBInfo->P3c4 , 0x34 , value & 0xFF ) ;
8820
8821 /* VRE SR0A[5] CR11[3:0] */
8822 value = LVDSVRE - 1;
8823 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x20 , ( value & 0x10 ) << 1 ) ;
8824 XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x11 , ~0x0F , value & 0x0F ) ;
8825
8826 /* Panel VRE SR3F[7:2] */
8827 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x3F , ~0xFC , ( value << 2 ) & 0xFC ) ;
8828
8829 for ( temp=0, value = 0; temp < 3; temp++)
8830 {
8831
8832 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x31 , ~0x30 , value ) ;
8833 XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , pVBInfo->XG21_LVDSCapList[lvdstableindex].VCLKData1) ;
8834 XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , pVBInfo->XG21_LVDSCapList[lvdstableindex].VCLKData2) ;
8835 value += 0x10;
8836 }
8837
8838 if (!( modeflag & Charx8Dot ))
8839 {
8840 XGINew_GetReg2( pVBInfo->P3da ) ; /* reset 3da */
8841 XGINew_SetReg3( pVBInfo->P3c0 , 0x13 ) ; /* set index */
8842 XGINew_SetReg3( pVBInfo->P3c0 , 0x00 ) ; /* set data, panning = 0, shift left 1 dot*/
8843
8844 XGINew_GetReg2( pVBInfo->P3da ) ; /* Enable Attribute */
8845 XGINew_SetReg3( pVBInfo->P3c0 , 0x20 ) ;
8846
8847 XGINew_GetReg2( pVBInfo->P3da ) ; /* reset 3da */
8848 }
8849
8850
8851}
8852
8853/* --------------------------------------------------------------------- */
8854/* Function : XGI_IsLCDON */
8855/* Input : */
8856/* Output : FALSE : Skip PSC Control */
8857/* TRUE: Disable PSC */
8858/* Description : */
8859/* --------------------------------------------------------------------- */
8860BOOLEAN XGI_IsLCDON(PVB_DEVICE_INFO pVBInfo)
8861{
8862 USHORT tempax ;
8863
8864 tempax = pVBInfo->VBInfo ;
8865 if ( tempax & SetCRT2ToDualEdge )
8866 return FALSE ;
8867 else if ( tempax & ( DisableCRT2Display | SwitchToCRT2 | SetSimuScanMode ) )
8868 return TRUE ;
8869
8870 return FALSE ;
8871}
8872
8873
8874/* --------------------------------------------------------------------- */
8875/* Function : XGI_EnablePWD */
8876/* Input : */
8877/* Output : */
8878/* Description : */
8879/* --------------------------------------------------------------------- */
8880void XGI_EnablePWD( PVB_DEVICE_INFO pVBInfo )
8881{
8882 USHORT index ,
8883 temp ;
8884
8885 index = XGI_GetLCDCapPtr(pVBInfo) ;
8886 temp = pVBInfo->LCDCapList[ index ].PWD_2B ;
8887 XGINew_SetReg1( pVBInfo->Part4Port , 0x2B , temp ) ;
8888 XGINew_SetReg1( pVBInfo->Part4Port , 0x2C , pVBInfo->LCDCapList[ index ].PWD_2C ) ;
8889 XGINew_SetReg1( pVBInfo->Part4Port , 0x2D , pVBInfo->LCDCapList[ index ].PWD_2D ) ;
8890 XGINew_SetReg1( pVBInfo->Part4Port , 0x2E , pVBInfo->LCDCapList[ index ].PWD_2E ) ;
8891 XGINew_SetReg1( pVBInfo->Part4Port , 0x2F , pVBInfo->LCDCapList[ index ].PWD_2F ) ;
8892 XGINew_SetRegOR( pVBInfo->Part4Port , 0x27 , 0x80 ) ; /* enable PWD */
8893}
8894
8895
8896/* --------------------------------------------------------------------- */
8897/* Function : XGI_DisablePWD */
8898/* Input : */
8899/* Output : */
8900/* Description : */
8901/* --------------------------------------------------------------------- */
8902void XGI_DisablePWD( PVB_DEVICE_INFO pVBInfo )
8903{
8904 XGINew_SetRegAND( pVBInfo->Part4Port , 0x27 , 0x7F ) ; /* disable PWD */
8905}
8906
8907
8908/* --------------------------------------------------------------------- */
8909/* Function : XGI_DisableChISLCD */
8910/* Input : */
8911/* Output : FALSE -> Not LCD Mode */
8912/* Description : */
8913/* --------------------------------------------------------------------- */
8914BOOLEAN XGI_DisableChISLCD(PVB_DEVICE_INFO pVBInfo)
8915{
8916 USHORT tempbx ,
8917 tempah ;
8918
8919 tempbx = pVBInfo->SetFlag & ( DisableChA | DisableChB ) ;
8920 tempah = ~( ( USHORT )XGINew_GetReg1( pVBInfo->Part1Port , 0x2E ) ) ;
8921
8922 if ( tempbx & ( EnableChA | DisableChA ) )
8923 {
8924 if ( !( tempah & 0x08 ) ) /* Chk LCDA Mode */
8925 return FALSE ;
8926 }
8927
8928 if ( !( tempbx & ( EnableChB | DisableChB ) ) )
8929 return FALSE ;
8930
8931 if ( tempah & 0x01 ) /* Chk LCDB Mode */
8932 return TRUE ;
8933
8934 return FALSE ;
8935}
8936
8937
8938/* --------------------------------------------------------------------- */
8939/* Function : XGI_EnableChISLCD */
8940/* Input : */
8941/* Output : 0 -> Not LCD mode */
8942/* Description : */
8943/* --------------------------------------------------------------------- */
8944BOOLEAN XGI_EnableChISLCD(PVB_DEVICE_INFO pVBInfo)
8945{
8946 USHORT tempbx ,
8947 tempah ;
8948
8949
8950 tempbx = pVBInfo->SetFlag & ( EnableChA | EnableChB ) ;
8951 tempah = ~( ( USHORT )XGINew_GetReg1( pVBInfo->Part1Port , 0x2E ) ) ;
8952
8953 if ( tempbx & ( EnableChA | DisableChA ) )
8954 {
8955 if ( !( tempah & 0x08 ) ) /* Chk LCDA Mode */
8956 return FALSE ;
8957 }
8958
8959 if ( !( tempbx & ( EnableChB | DisableChB ) ) )
8960 return FALSE ;
8961
8962 if ( tempah & 0x01 ) /* Chk LCDB Mode */
8963 return TRUE ;
8964
8965 return FALSE ;
8966}
8967
8968
8969/* --------------------------------------------------------------------- */
8970/* Function : XGI_GetLCDCapPtr */
8971/* Input : */
8972/* Output : */
8973/* Description : */
8974/* --------------------------------------------------------------------- */
8975USHORT XGI_GetLCDCapPtr( PVB_DEVICE_INFO pVBInfo )
8976{
8977 UCHAR tempal ,
8978 tempah ,
8979 tempbl ,
8980 i ;
8981
8982 tempah = XGINew_GetReg1( pVBInfo->P3d4 , 0x36 ) ;
8983 tempal = tempah & 0x0F ;
8984 tempah = tempah & 0xF0 ;
8985 i = 0 ;
8986 tempbl = pVBInfo->LCDCapList[ i ].LCD_ID ;
8987
8988 while( tempbl != 0xFF )
8989 {
8990 if ( tempbl & 0x80 ) /* OEMUtil */
8991 {
8992 tempal = tempah ;
8993 tempbl = tempbl & ~( 0x80 ) ;
8994 }
8995
8996 if ( tempal == tempbl )
8997 break ;
8998
8999 i++ ;
9000
9001 tempbl = pVBInfo->LCDCapList[ i ].LCD_ID ;
9002 }
9003
9004 return i ;
9005}
9006
9007
9008/* --------------------------------------------------------------------- */
9009/* Function : XGI_GetLCDCapPtr1 */
9010/* Input : */
9011/* Output : */
9012/* Description : */
9013/* --------------------------------------------------------------------- */
9014USHORT XGI_GetLCDCapPtr1( PVB_DEVICE_INFO pVBInfo )
9015{
9016 USHORT tempah ,
9017 tempal ,
9018 tempbl ,
9019 i ;
9020
9021 tempal = pVBInfo->LCDResInfo ;
9022 tempah = pVBInfo->LCDTypeInfo ;
9023
9024 i = 0 ;
9025 tempbl = pVBInfo->LCDCapList[ i ].LCD_ID;
9026
9027 while( tempbl != 0xFF )
9028 {
9029 if ( ( tempbl & 0x80 ) && ( tempbl != 0x80 ) )
9030 {
9031 tempal = tempah ;
9032 tempbl &= ~0x80 ;
9033 }
9034
9035 if ( tempal == tempbl )
9036 break ;
9037
9038 i++ ;
9039 tempbl = pVBInfo->LCDCapList[ i ].LCD_ID ;
9040 }
9041
9042 if ( tempbl == 0xFF )
9043 {
9044 pVBInfo->LCDResInfo = Panel1024x768 ;
9045 pVBInfo->LCDTypeInfo = 0 ;
9046 i = 0 ;
9047 }
9048
9049 return i ;
9050}
9051
9052
9053/* --------------------------------------------------------------------- */
9054/* Function : XGI_GetLCDSync */
9055/* Input : */
9056/* Output : */
9057/* Description : */
9058/* --------------------------------------------------------------------- */
9059void XGI_GetLCDSync( USHORT* HSyncWidth , USHORT* VSyncWidth, PVB_DEVICE_INFO pVBInfo )
9060{
9061 USHORT Index ;
9062
9063 Index = XGI_GetLCDCapPtr(pVBInfo) ;
9064 *HSyncWidth = pVBInfo->LCDCapList[ Index ].LCD_HSyncWidth ;
9065 *VSyncWidth = pVBInfo->LCDCapList[ Index ].LCD_VSyncWidth ;
9066
9067 return ;
9068}
9069
9070
9071
9072/* --------------------------------------------------------------------- */
9073/* Function : XGI_EnableBridge */
9074/* Input : */
9075/* Output : */
9076/* Description : */
9077/* --------------------------------------------------------------------- */
9078void XGI_EnableBridge( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo)
9079{
9080 USHORT tempbl ,
9081 tempah ;
9082
9083 if ( pVBInfo->SetFlag == Win9xDOSMode )
9084 {
9085 if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
9086 {
9087 XGI_DisplayOn( HwDeviceExtension, pVBInfo) ;
9088 return ;
9089 }
9090 else /* LVDS or CH7017 */
9091 return ;
9092 }
9093
9094
9095 if ( HwDeviceExtension->jChipType < XG40 )
9096 {
9097 if ( !XGI_DisableChISLCD(pVBInfo) )
9098 {
9099 if ( ( XGI_EnableChISLCD(pVBInfo) ) || ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) )
9100 {
9101 if ( pVBInfo->LCDInfo & SetPWDEnable )
9102 {
9103 XGI_EnablePWD( pVBInfo);
9104 }
9105 else
9106 {
9107 pVBInfo->LCDInfo &= ( ~SetPWDEnable ) ;
9108 if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
9109 {
9110 tempbl = 0xFD ;
9111 tempah = 0x02 ;
9112 }
9113 else
9114 {
9115 tempbl = 0xFB ;
9116 tempah = 0x00 ;
9117 }
9118
9119 XGI_SetPanelPower( tempah , tempbl, pVBInfo ) ;
9120 XGI_SetPanelDelay( 1,pVBInfo ) ;
9121 }
9122 }
9123 }
9124 } /* Not 340 */
9125
9126
9127
9128 if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
9129 {
9130 if ( !( pVBInfo->SetFlag & DisableChA ) )
9131 {
9132 if ( pVBInfo->SetFlag & EnableChA )
9133 {
9134 XGINew_SetReg1( pVBInfo->Part1Port , 0x1E , 0x20 ) ; /* Power on */
9135 }
9136 else
9137 {
9138 if ( pVBInfo->VBInfo & SetCRT2ToDualEdge ) /* SetCRT2ToLCDA ) */
9139 {
9140 XGINew_SetReg1(pVBInfo->Part1Port,0x1E,0x20); /* Power on */
9141 }
9142 }
9143 }
9144
9145 if ( !( pVBInfo->SetFlag & DisableChB ) )
9146 {
9147 if ( ( pVBInfo->SetFlag & EnableChB ) || ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToTV | SetCRT2ToRAMDAC ) ) )
9148 {
9149 tempah = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x32 ) ;
9150 tempah &= 0xDF;
9151 if ( pVBInfo->VBInfo & SetInSlaveMode )
9152 {
9153 if ( !( pVBInfo->VBInfo & SetCRT2ToRAMDAC ) )
9154 tempah |= 0x20 ;
9155 }
9156 XGINew_SetReg1( pVBInfo->P3c4 , 0x32 , tempah ) ;
9157 XGINew_SetRegOR( pVBInfo->P3c4 , 0x1E , 0x20 ) ;
9158
9159
9160 tempah = ( UCHAR )XGINew_GetReg1( pVBInfo->Part1Port , 0x2E ) ;
9161
9162 if ( !( tempah & 0x80 ) )
9163 XGINew_SetRegOR( pVBInfo->Part1Port , 0x2E , 0x80 ) ; /* BVBDOENABLE = 1 */
9164
9165 XGINew_SetRegAND( pVBInfo->Part1Port , 0x00 , 0x7F ) ; /* BScreenOFF = 0 */
9166 }
9167 }
9168
9169 if ( ( pVBInfo->SetFlag & ( EnableChA | EnableChB ) ) || ( !( pVBInfo->VBInfo & DisableCRT2Display ) ) )
9170 {
9171 XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x00 , ~0xE0 , 0x20 ) ; /* shampoo 0129 */
9172 if ( pVBInfo->VBType & ( VB_XGI302LV | VB_XGI301C ) )
9173 {
9174 if ( !XGI_DisableChISLCD(pVBInfo) )
9175 {
9176 if ( XGI_EnableChISLCD( pVBInfo) || ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) )
9177 XGINew_SetRegAND( pVBInfo->Part4Port ,0x2A , 0x7F ) ; /* LVDS PLL power on */
9178 }
9179 XGINew_SetRegAND( pVBInfo->Part4Port , 0x30 , 0x7F ) ; /* LVDS Driver power on */
9180 }
9181 }
9182
9183 tempah = 0x00 ;
9184
9185 if ( !( pVBInfo->VBInfo & DisableCRT2Display ) )
9186 {
9187 tempah = 0xc0 ;
9188
9189 if ( !( pVBInfo->VBInfo & SetSimuScanMode ) )
9190 {
9191 if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
9192 {
9193 if ( pVBInfo->VBInfo & SetCRT2ToDualEdge )
9194 {
9195 tempah = tempah & 0x40;
9196 if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
9197 tempah = tempah ^ 0xC0 ;
9198
9199 if ( pVBInfo->SetFlag & DisableChB )
9200 tempah &= 0xBF ;
9201
9202 if ( pVBInfo->SetFlag & DisableChA )
9203 tempah &= 0x7F ;
9204
9205 if ( pVBInfo->SetFlag & EnableChB )
9206 tempah |= 0x40 ;
9207
9208 if ( pVBInfo->SetFlag & EnableChA )
9209 tempah |= 0x80 ;
9210 }
9211 }
9212 }
9213 }
9214
9215 XGINew_SetRegOR( pVBInfo->Part4Port , 0x1F , tempah ) ; /* EnablePart4_1F */
9216
9217 if ( pVBInfo->SetFlag & Win9xDOSMode )
9218 {
9219 XGI_DisplayOn( HwDeviceExtension, pVBInfo) ;
9220 return ;
9221 }
9222
9223 if ( !( pVBInfo->SetFlag & DisableChA ) )
9224 {
9225 XGI_VBLongWait( pVBInfo) ;
9226 if ( !( pVBInfo->SetFlag & GatingCRT ) )
9227 {
9228 XGI_DisableGatingCRT( HwDeviceExtension, pVBInfo ) ;
9229 XGI_DisplayOn( HwDeviceExtension, pVBInfo) ;
9230 XGI_VBLongWait( pVBInfo) ;
9231 }
9232 }
9233 } /* 301 */
9234 else /* LVDS */
9235 {
9236 if ( pVBInfo->VBInfo & ( SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToLCDA ) )
9237 XGINew_SetRegOR( pVBInfo->Part1Port , 0x1E , 0x20 ) ; /* enable CRT2 */
9238
9239
9240
9241 tempah = ( UCHAR )XGINew_GetReg1( pVBInfo->Part1Port , 0x2E ) ;
9242 if ( !( tempah & 0x80 ) )
9243 XGINew_SetRegOR( pVBInfo->Part1Port , 0x2E , 0x80 ) ; /* BVBDOENABLE = 1 */
9244
9245 XGINew_SetRegAND(pVBInfo->Part1Port,0x00,0x7F);
9246 XGI_DisplayOn( HwDeviceExtension, pVBInfo);
9247 } /* End of VB */
9248
9249
9250 if ( HwDeviceExtension->jChipType < XG40 )
9251 {
9252 if ( !XGI_EnableChISLCD(pVBInfo) )
9253 {
9254 if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
9255 {
9256 if ( XGI_BacklightByDrv(pVBInfo) )
9257 return ;
9258 }
9259 else
9260 return ;
9261 }
9262
9263 if ( pVBInfo->LCDInfo & SetPWDEnable )
9264 {
9265 XGI_FirePWDEnable(pVBInfo) ;
9266 return ;
9267 }
9268
9269 XGI_SetPanelDelay( 2,pVBInfo ) ;
9270
9271 if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
9272 {
9273 tempah = 0x01 ;
9274 tempbl = 0xFE ; /* turn on backlght */
9275 }
9276 else
9277 {
9278 tempbl = 0xF7 ;
9279 tempah = 0x00 ;
9280 }
9281 XGI_SetPanelPower( tempah , tempbl , pVBInfo) ;
9282 }
9283}
9284
9285
9286/* --------------------------------------------------------------------- */
9287/* Function : XGI_DisableBridge */
9288/* Input : */
9289/* Output : */
9290/* Description : */
9291/* --------------------------------------------------------------------- */
9292void XGI_DisableBridge(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
9293{
9294 USHORT tempax ,
9295 tempbx ,
9296 tempah = 0 ,
9297 tempbl = 0 ;
9298
9299 if ( pVBInfo->SetFlag == Win9xDOSMode )
9300 return ;
9301
9302
9303 if ( HwDeviceExtension->jChipType < XG40 )
9304 {
9305 if ( ( !( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) ) || ( XGI_DisableChISLCD(pVBInfo) ) )
9306 {
9307 if ( !XGI_IsLCDON(pVBInfo) )
9308 {
9309 if ( pVBInfo->LCDInfo & SetPWDEnable )
9310 XGI_EnablePWD( pVBInfo) ;
9311 else
9312 {
9313 pVBInfo->LCDInfo &= ~SetPWDEnable ;
9314 XGI_DisablePWD(pVBInfo) ;
9315 if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
9316 {
9317 tempbx = 0xFE ; /* not 01h */
9318 tempax = 0 ;
9319 }
9320 else
9321 {
9322 tempbx = 0xF7 ; /* not 08h */
9323 tempax = 0x08 ;
9324 }
9325 XGI_SetPanelPower( tempax , tempbx , pVBInfo) ;
9326 XGI_SetPanelDelay( 3,pVBInfo ) ;
9327 }
9328 } /* end if(!XGI_IsLCDON(pVBInfo)) */
9329 }
9330 }
9331
9332/* if ( CH7017 )
9333 {
9334 if ( !( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2toLCDA ) ) || ( XGI_DisableChISLCD(pVBInfo) ) )
9335 {
9336 if ( !XGI_IsLCDON(pVBInfo) )
9337 {
9338 if ( DISCHARGE )
9339 {
9340 tempbx = XGINew_GetCH7005( 0x61 ) ;
9341 if ( tempbx < 0x01 ) //first time we power up
9342 XGINew_SetCH7005( 0x0066 ) ; //and disable power sequence
9343 else
9344 XGINew_SetCH7005( 0x5f66 ) ; //leave VDD on - disable power
9345 }
9346 }
9347 }
9348 } */
9349
9350 if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B| VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
9351 {
9352 tempah = 0x3F ;
9353 if ( !( pVBInfo->VBInfo & ( DisableCRT2Display | SetSimuScanMode ) ) )
9354 {
9355 if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
9356 {
9357 if ( pVBInfo->VBInfo & SetCRT2ToDualEdge )
9358 {
9359 tempah = 0x7F; /* Disable Channel A */
9360 if ( !( pVBInfo->VBInfo & SetCRT2ToLCDA ) )
9361 tempah = 0xBF ; /* Disable Channel B */
9362
9363 if ( pVBInfo->SetFlag & DisableChB )
9364 tempah &= 0xBF ; /* force to disable Cahnnel */
9365
9366 if ( pVBInfo->SetFlag & DisableChA )
9367 tempah &= 0x7F ; /* Force to disable Channel B */
9368 }
9369 }
9370 }
9371
9372 XGINew_SetRegAND( pVBInfo->Part4Port , 0x1F , tempah ) ; /* disable part4_1f */
9373
9374 if ( pVBInfo->VBType & ( VB_XGI302LV | VB_XGI301C ) )
9375 {
9376 if ( ( ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) ) || ( XGI_DisableChISLCD(pVBInfo) ) || ( XGI_IsLCDON(pVBInfo) ) )
9377 XGINew_SetRegOR( pVBInfo->Part4Port , 0x30 , 0x80 ) ; /* LVDS Driver power down */
9378 }
9379
9380 if ( ( pVBInfo->SetFlag & DisableChA ) || ( pVBInfo->VBInfo & ( DisableCRT2Display | SetCRT2ToLCDA | SetSimuScanMode ) ) )
9381 {
9382 if ( pVBInfo->SetFlag & GatingCRT )
9383 XGI_EnableGatingCRT( HwDeviceExtension, pVBInfo ) ;
9384 XGI_DisplayOff( HwDeviceExtension, pVBInfo) ;
9385 }
9386
9387 if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
9388 {
9389 if ( ( pVBInfo->SetFlag & DisableChA ) || ( pVBInfo->VBInfo & SetCRT2ToLCDA ) )
9390 XGINew_SetRegAND( pVBInfo->Part1Port , 0x1e , 0xdf ) ; /* Power down */
9391 }
9392
9393 XGINew_SetRegAND( pVBInfo->P3c4 , 0x32 , 0xdf ) ; /* disable TV as primary VGA swap */
9394
9395 if ( ( pVBInfo->VBInfo & ( SetSimuScanMode | SetCRT2ToDualEdge ) ) )
9396 XGINew_SetRegAND(pVBInfo->Part2Port,0x00,0xdf);
9397
9398 if ( ( pVBInfo->SetFlag & DisableChB ) || ( pVBInfo->VBInfo & ( DisableCRT2Display | SetSimuScanMode ) )
9399 || ( ( !( pVBInfo->VBInfo & SetCRT2ToLCDA ) ) && ( pVBInfo->VBInfo & ( SetCRT2ToRAMDAC | SetCRT2ToLCD | SetCRT2ToTV ) ) ) )
9400 XGINew_SetRegOR( pVBInfo->Part1Port , 0x00 , 0x80 ) ; /* BScreenOff=1 */
9401
9402 if ( ( pVBInfo->SetFlag & DisableChB ) || ( pVBInfo->VBInfo & ( DisableCRT2Display | SetSimuScanMode ) )
9403 || ( !( pVBInfo->VBInfo & SetCRT2ToLCDA ) ) || ( pVBInfo->VBInfo & ( SetCRT2ToRAMDAC | SetCRT2ToLCD | SetCRT2ToTV ) ) )
9404 {
9405 tempah= XGINew_GetReg1( pVBInfo->Part1Port , 0x00 ) ; /* save Part1 index 0 */
9406 XGINew_SetRegOR( pVBInfo->Part1Port , 0x00 , 0x10 ) ; /* BTDAC = 1, avoid VB reset */
9407 XGINew_SetRegAND( pVBInfo->Part1Port , 0x1E , 0xDF ) ; /* disable CRT2 */
9408 XGINew_SetReg1( pVBInfo->Part1Port , 0x00 , tempah ) ; /* restore Part1 index 0 */
9409 }
9410 }
9411 else /* {301} */
9412 {
9413 if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToTV ) )
9414 {
9415 XGINew_SetRegOR( pVBInfo->Part1Port , 0x00 , 0x80 ) ; /* BScreenOff=1 */
9416 XGINew_SetRegAND( pVBInfo->Part1Port , 0x1E , 0xDF ) ; /* Disable CRT2 */
9417 XGINew_SetRegAND( pVBInfo->P3c4 , 0x32 , 0xDF ) ; /* Disable TV asPrimary VGA swap */
9418 }
9419
9420 if ( pVBInfo->VBInfo & ( DisableCRT2Display | SetCRT2ToLCDA | SetSimuScanMode ) )
9421 XGI_DisplayOff( HwDeviceExtension, pVBInfo) ;
9422 }
9423
9424
9425
9426
9427 if ( HwDeviceExtension->jChipType < XG40 )
9428 {
9429 if ( !( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) || ( XGI_DisableChISLCD(pVBInfo) ) || ( XGI_IsLCDON(pVBInfo) ) )
9430 {
9431 if ( pVBInfo->LCDInfo & SetPWDEnable )
9432 {
9433 if ( pVBInfo->LCDInfo & SetPWDEnable )
9434 XGI_BacklightByDrv(pVBInfo) ;
9435 else
9436 {
9437 XGI_SetPanelDelay( 4 ,pVBInfo) ;
9438 if ( pVBInfo->VBType & VB_XGI301LV )
9439 {
9440 tempbl = 0xFD ;
9441 tempah = 0x00 ;
9442 }
9443 else
9444 {
9445 tempbl = 0xFB ;
9446 tempah = 0x04 ;
9447 }
9448 }
9449 }
9450 XGI_SetPanelPower( tempah , tempbl , pVBInfo) ;
9451 }
9452 }
9453}
9454
9455
9456/* --------------------------------------------------------------------- */
9457/* Function : XGI_GetTVPtrIndex */
9458/* Input : */
9459/* Output : */
9460/* Description : bx 0 : ExtNTSC */
9461/* 1 : StNTSC */
9462/* 2 : ExtPAL */
9463/* 3 : StPAL */
9464/* 4 : ExtHiTV */
9465/* 5 : StHiTV */
9466/* 6 : Ext525i */
9467/* 7 : St525i */
9468/* 8 : Ext525p */
9469/* 9 : St525p */
9470/* A : Ext750p */
9471/* B : St750p */
9472/* --------------------------------------------------------------------- */
9473USHORT XGI_GetTVPtrIndex( PVB_DEVICE_INFO pVBInfo )
9474{
9475 USHORT tempbx = 0 ;
9476
9477 if ( pVBInfo->TVInfo & SetPALTV )
9478 tempbx = 2 ;
9479 if ( pVBInfo->TVInfo & SetYPbPrMode1080i )
9480 tempbx = 4 ;
9481 if ( pVBInfo->TVInfo & SetYPbPrMode525i )
9482 tempbx = 6 ;
9483 if ( pVBInfo->TVInfo & SetYPbPrMode525p )
9484 tempbx = 8 ;
9485 if ( pVBInfo->TVInfo & SetYPbPrMode750p )
9486 tempbx = 10 ;
9487 if ( pVBInfo->TVInfo & TVSimuMode )
9488 tempbx++ ;
9489
9490 return tempbx ;
9491}
9492
9493
9494/* --------------------------------------------------------------------- */
9495/* Function : XGI_OEM310Setting */
9496/* Input : */
9497/* Output : */
9498/* Description : Customized Param. for 301 */
9499/* --------------------------------------------------------------------- */
9500void XGI_OEM310Setting( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
9501{
9502 if ( pVBInfo->SetFlag & Win9xDOSMode )
9503 return ;
9504
9505 /* GetPart1IO(); */
9506 XGI_SetDelayComp(pVBInfo) ;
9507
9508 if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
9509 XGI_SetLCDCap(pVBInfo) ;
9510
9511 if ( pVBInfo->VBInfo & SetCRT2ToTV )
9512 {
9513 /* GetPart2IO() */
9514 XGI_SetPhaseIncr(pVBInfo) ;
9515 XGI_SetYFilter( ModeNo , ModeIdIndex,pVBInfo ) ;
9516 XGI_SetAntiFlicker( ModeNo , ModeIdIndex,pVBInfo ) ;
9517
9518 if ( pVBInfo->VBType&VB_XGI301)
9519 XGI_SetEdgeEnhance( ModeNo , ModeIdIndex ,pVBInfo) ;
9520 }
9521}
9522
9523
9524/* --------------------------------------------------------------------- */
9525/* Function : XGI_SetDelayComp */
9526/* Input : */
9527/* Output : */
9528/* Description : */
9529/* --------------------------------------------------------------------- */
9530void XGI_SetDelayComp( PVB_DEVICE_INFO pVBInfo )
9531{
9532 USHORT index ;
9533
9534 UCHAR tempah ,
9535 tempbl ,
9536 tempbh ;
9537
9538 if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
9539 {
9540 if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA | SetCRT2ToTV | SetCRT2ToRAMDAC ) )
9541 {
9542 tempbl = 0;
9543 tempbh = 0;
9544
9545 index = XGI_GetTVPtrIndex(pVBInfo ) ; /* Get TV Delay */
9546 tempbl = pVBInfo->XGI_TVDelayList[ index ] ;
9547
9548 if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
9549 tempbl = pVBInfo->XGI_TVDelayList2[ index ] ;
9550
9551 if ( pVBInfo->VBInfo & SetCRT2ToDualEdge )
9552 tempbl = tempbl >> 4 ;
9553/*
9554 if ( pVBInfo->VBInfo & SetCRT2ToRAMDAC )
9555 tempbl = CRT2Delay1 ; // Get CRT2 Delay
9556
9557 if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
9558 tempbl = CRT2Delay2 ;
9559*/
9560 if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) )
9561 {
9562 index = XGI_GetLCDCapPtr(pVBInfo) ; /* Get LCD Delay */
9563 tempbh=pVBInfo->LCDCapList[ index ].LCD_DelayCompensation ;
9564
9565 if ( !( pVBInfo->VBInfo & SetCRT2ToLCDA ) )
9566 tempbl = tempbh ;
9567 }
9568
9569 tempbl &= 0x0F ;
9570 tempbh &= 0xF0 ;
9571 tempah = XGINew_GetReg1( pVBInfo->Part1Port , 0x2D ) ;
9572
9573 if ( pVBInfo->VBInfo & ( SetCRT2ToRAMDAC | SetCRT2ToLCD | SetCRT2ToTV ) ) /* Channel B */
9574 {
9575 tempah &= 0xF0 ;
9576 tempah |= tempbl ;
9577 }
9578
9579 if ( pVBInfo->VBInfo & SetCRT2ToLCDA ) /* Channel A */
9580 {
9581 tempah &= 0x0F ;
9582 tempah |= tempbh ;
9583 }
9584 XGINew_SetReg1(pVBInfo->Part1Port,0x2D,tempah);
9585 }
9586 }
9587 else if ( pVBInfo->IF_DEF_LVDS == 1 )
9588 {
9589 tempbl = 0;
9590 tempbh = 0;
9591 if ( pVBInfo->VBInfo & SetCRT2ToLCD )
9592 {
9593 tempah = pVBInfo->LCDCapList[ XGI_GetLCDCapPtr(pVBInfo) ].LCD_DelayCompensation ; /* / Get LCD Delay */
9594 tempah &= 0x0f ;
9595 tempah = tempah << 4 ;
9596 XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2D , 0x0f , tempah ) ;
9597 }
9598 }
9599}
9600
9601
9602/* --------------------------------------------------------------------- */
9603/* Function : XGI_SetLCDCap */
9604/* Input : */
9605/* Output : */
9606/* Description : */
9607/* --------------------------------------------------------------------- */
9608void XGI_SetLCDCap( PVB_DEVICE_INFO pVBInfo )
9609{
9610 USHORT tempcx ;
9611
9612 tempcx = pVBInfo->LCDCapList[ XGI_GetLCDCapPtr(pVBInfo) ].LCD_Capability ;
9613
9614 if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
9615 {
9616 if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
9617 { /* 301LV/302LV only */
9618 /* Set 301LV Capability */
9619 XGINew_SetReg1( pVBInfo->Part4Port , 0x24 , ( UCHAR )( tempcx & 0x1F ) ) ;
9620 }
9621 /* VB Driving */
9622 XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x0D , ~( ( EnableVBCLKDRVLOW | EnablePLLSPLOW ) >> 8 ) , ( USHORT )( ( tempcx & ( EnableVBCLKDRVLOW | EnablePLLSPLOW ) ) >> 8 ) ) ;
9623 }
9624
9625 if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
9626 {
9627 if ( pVBInfo->VBInfo & SetCRT2ToLCD )
9628 XGI_SetLCDCap_B( tempcx,pVBInfo ) ;
9629 else if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
9630 XGI_SetLCDCap_A( tempcx,pVBInfo ) ;
9631
9632 if ( pVBInfo->VBType & ( VB_XGI302LV | VB_XGI301C ) )
9633 {
9634 if ( tempcx & EnableSpectrum )
9635 SetSpectrum( pVBInfo) ;
9636 }
9637 }
9638 else /* LVDS,CH7017 */
9639 XGI_SetLCDCap_A( tempcx, pVBInfo ) ;
9640}
9641
9642
9643/* --------------------------------------------------------------------- */
9644/* Function : XGI_SetLCDCap_A */
9645/* Input : */
9646/* Output : */
9647/* Description : */
9648/* --------------------------------------------------------------------- */
9649void XGI_SetLCDCap_A(USHORT tempcx,PVB_DEVICE_INFO pVBInfo)
9650{
9651 USHORT temp ;
9652
9653 temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x37 ) ;
9654
9655 if ( temp & LCDRGB18Bit )
9656 {
9657 XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x19 , 0x0F , ( USHORT )( 0x20 | ( tempcx & 0x00C0 ) ) ) ; /* Enable Dither */
9658 XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x1A , 0x7F , 0x80 ) ;
9659 }
9660 else
9661 {
9662 XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x19 , 0x0F , ( USHORT )( 0x30 | ( tempcx & 0x00C0 ) ) ) ;
9663 XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x1A , 0x7F , 0x00 ) ;
9664 }
9665
9666/*
9667 if ( tempcx & EnableLCD24bpp ) // 24bits
9668 {
9669 XGINew_SetRegANDOR(pVBInfo->Part1Port,0x19, 0x0F,(USHORT)(0x30|(tempcx&0x00C0)) );
9670 XGINew_SetRegANDOR(pVBInfo->Part1Port,0x1A,0x7F,0x00);
9671 }
9672 else
9673 {
9674 XGINew_SetRegANDOR(pVBInfo->Part1Port,0x19, 0x0F,(USHORT)(0x20|(tempcx&0x00C0)) );//Enable Dither
9675 XGINew_SetRegANDOR(pVBInfo->Part1Port,0x1A,0x7F,0x80);
9676 }
9677*/
9678}
9679
9680
9681/* --------------------------------------------------------------------- */
9682/* Function : XGI_SetLCDCap_B */
9683/* Input : cx -> LCD Capability */
9684/* Output : */
9685/* Description : */
9686/* --------------------------------------------------------------------- */
9687void XGI_SetLCDCap_B(USHORT tempcx,PVB_DEVICE_INFO pVBInfo)
9688{
9689 if ( tempcx & EnableLCD24bpp ) /* 24bits */
9690 XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x1A , 0xE0 , ( USHORT )( ( ( tempcx & 0x00ff ) >> 6 ) | 0x0c ) ) ;
9691 else
9692 XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x1A , 0xE0 , ( USHORT )( ( ( tempcx & 0x00ff ) >> 6 ) | 0x18 ) ) ; /* Enable Dither */
9693}
9694
9695
9696/* --------------------------------------------------------------------- */
9697/* Function : SetSpectrum */
9698/* Input : */
9699/* Output : */
9700/* Description : */
9701/* --------------------------------------------------------------------- */
9702void SetSpectrum( PVB_DEVICE_INFO pVBInfo )
9703{
9704 USHORT index ;
9705
9706 index = XGI_GetLCDCapPtr(pVBInfo) ;
9707
9708 XGINew_SetRegAND( pVBInfo->Part4Port , 0x30 , 0x8F ) ; /* disable down spectrum D[4] */
9709 XGI_LongWait(pVBInfo) ;
9710 XGINew_SetRegOR( pVBInfo->Part4Port , 0x30 , 0x20 ) ; /* reset spectrum */
9711 XGI_LongWait(pVBInfo) ;
9712
9713 XGINew_SetReg1( pVBInfo->Part4Port , 0x31 , pVBInfo->LCDCapList[ index ].Spectrum_31 ) ;
9714 XGINew_SetReg1( pVBInfo->Part4Port , 0x32 , pVBInfo->LCDCapList[ index ].Spectrum_32 ) ;
9715 XGINew_SetReg1( pVBInfo->Part4Port , 0x33 , pVBInfo->LCDCapList[ index ].Spectrum_33 ) ;
9716 XGINew_SetReg1( pVBInfo->Part4Port , 0x34 , pVBInfo->LCDCapList[ index ].Spectrum_34 ) ;
9717 XGI_LongWait(pVBInfo) ;
9718 XGINew_SetRegOR( pVBInfo->Part4Port , 0x30 , 0x40 ) ; /* enable spectrum */
9719}
9720
9721
9722/* --------------------------------------------------------------------- */
9723/* Function : XGI_SetAntiFlicker */
9724/* Input : */
9725/* Output : */
9726/* Description : Set TV Customized Param. */
9727/* --------------------------------------------------------------------- */
9728void XGI_SetAntiFlicker( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo )
9729{
9730 USHORT tempbx ,
9731 index ;
9732
9733 UCHAR tempah ;
9734
9735 if (pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p ) )
9736 return ;
9737
9738 tempbx = XGI_GetTVPtrIndex(pVBInfo ) ;
9739 tempbx &= 0xFE ;
9740
9741 if ( ModeNo <= 0x13 )
9742 {
9743 index = pVBInfo->SModeIDTable[ ModeIdIndex ].VB_StTVFlickerIndex ;
9744 }
9745 else
9746 {
9747 index = pVBInfo->EModeIDTable[ ModeIdIndex ].VB_ExtTVFlickerIndex ;
9748 }
9749
9750 tempbx += index ;
9751 tempah = TVAntiFlickList[ tempbx ] ;
9752 tempah = tempah << 4 ;
9753
9754 XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x0A , 0x8F , tempah ) ;
9755}
9756
9757
9758/* --------------------------------------------------------------------- */
9759/* Function : XGI_SetEdgeEnhance */
9760/* Input : */
9761/* Output : */
9762/* Description : */
9763/* --------------------------------------------------------------------- */
9764void XGI_SetEdgeEnhance( USHORT ModeNo , USHORT ModeIdIndex , PVB_DEVICE_INFO pVBInfo)
9765{
9766 USHORT tempbx ,
9767 index ;
9768
9769 UCHAR tempah ;
9770
9771
9772 tempbx = XGI_GetTVPtrIndex(pVBInfo ) ;
9773 tempbx &= 0xFE ;
9774
9775 if ( ModeNo <= 0x13 )
9776 {
9777 index = pVBInfo->SModeIDTable[ ModeIdIndex ].VB_StTVEdgeIndex ;
9778 }
9779 else
9780 {
9781 index = pVBInfo->EModeIDTable[ ModeIdIndex ].VB_ExtTVEdgeIndex ;
9782 }
9783
9784 tempbx += index ;
9785 tempah = TVEdgeList[ tempbx ] ;
9786 tempah = tempah << 5 ;
9787
9788 XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x3A , 0x1F , tempah ) ;
9789}
9790
9791
9792/* --------------------------------------------------------------------- */
9793/* Function : XGI_SetPhaseIncr */
9794/* Input : */
9795/* Output : */
9796/* Description : */
9797/* --------------------------------------------------------------------- */
9798void XGI_SetPhaseIncr( PVB_DEVICE_INFO pVBInfo )
9799{
9800 USHORT tempbx ;
9801
9802 UCHAR tempcl ,
9803 tempch ;
9804
9805 ULONG tempData ;
9806
9807 XGI_GetTVPtrIndex2( &tempbx , &tempcl , &tempch, pVBInfo ) ; /* bx, cl, ch */
9808 tempData = TVPhaseList[ tempbx ] ;
9809
9810 XGINew_SetReg1( pVBInfo->Part2Port , 0x31 , ( USHORT )( tempData & 0x000000FF ) ) ;
9811 XGINew_SetReg1( pVBInfo->Part2Port , 0x32 , ( USHORT )( ( tempData & 0x0000FF00 ) >> 8 ) ) ;
9812 XGINew_SetReg1( pVBInfo->Part2Port , 0x33 , ( USHORT )( ( tempData & 0x00FF0000 ) >> 16 ) ) ;
9813 XGINew_SetReg1( pVBInfo->Part2Port , 0x34 , ( USHORT )( ( tempData & 0xFF000000 ) >> 24 ) ) ;
9814}
9815
9816
9817/* --------------------------------------------------------------------- */
9818/* Function : XGI_SetYFilter */
9819/* Input : */
9820/* Output : */
9821/* Description : */
9822/* --------------------------------------------------------------------- */
9823void XGI_SetYFilter( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
9824{
9825 USHORT tempbx ,
9826 index ;
9827
9828 UCHAR tempcl ,
9829 tempch ,
9830 tempal ,
9831 *filterPtr ;
9832
9833 XGI_GetTVPtrIndex2( &tempbx , &tempcl , &tempch, pVBInfo ) ; /* bx, cl, ch */
9834
9835 switch( tempbx )
9836 {
9837 case 0x00:
9838 case 0x04:
9839 filterPtr = NTSCYFilter1 ;
9840 break ;
9841
9842 case 0x01:
9843 filterPtr = PALYFilter1 ;
9844 break ;
9845
9846 case 0x02:
9847 case 0x05:
9848 case 0x0D:
9849 filterPtr = PALMYFilter1 ;
9850 break ;
9851
9852 case 0x03:
9853 filterPtr = PALNYFilter1 ;
9854 break ;
9855
9856 case 0x08:
9857 case 0x0C:
9858 filterPtr = NTSCYFilter2 ;
9859 break ;
9860
9861 case 0x0A:
9862 filterPtr = PALMYFilter2 ;
9863 break ;
9864
9865 case 0x0B:
9866 filterPtr = PALNYFilter2 ;
9867 break ;
9868
9869 case 0x09:
9870 filterPtr = PALYFilter2 ;
9871 break ;
9872
9873 default:
9874 return ;
9875 }
9876
9877 if ( ModeNo <= 0x13 )
9878 tempal = pVBInfo->SModeIDTable[ ModeIdIndex ].VB_StTVYFilterIndex ;
9879 else
9880 tempal = pVBInfo->EModeIDTable[ ModeIdIndex ].VB_ExtTVYFilterIndex ;
9881
9882 if ( tempcl == 0 )
9883 index = tempal * 4;
9884 else
9885 index = tempal * 7;
9886
9887 if ( ( tempcl == 0 ) && ( tempch == 1 ) )
9888 {
9889 XGINew_SetReg1( pVBInfo->Part2Port , 0x35 , 0 ) ;
9890 XGINew_SetReg1( pVBInfo->Part2Port , 0x36 , 0 ) ;
9891 XGINew_SetReg1( pVBInfo->Part2Port , 0x37 , 0 ) ;
9892 XGINew_SetReg1( pVBInfo->Part2Port , 0x38 , filterPtr[ index++ ] ) ;
9893 }
9894 else
9895 {
9896 XGINew_SetReg1( pVBInfo->Part2Port , 0x35 , filterPtr[ index++ ] ) ;
9897 XGINew_SetReg1( pVBInfo->Part2Port , 0x36 , filterPtr[ index++ ] ) ;
9898 XGINew_SetReg1( pVBInfo->Part2Port , 0x37 , filterPtr[ index++ ] ) ;
9899 XGINew_SetReg1( pVBInfo->Part2Port , 0x38 , filterPtr[ index++ ] ) ;
9900 }
9901
9902 if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
9903 {
9904 XGINew_SetReg1( pVBInfo->Part2Port , 0x48 , filterPtr[ index++ ] ) ;
9905 XGINew_SetReg1( pVBInfo->Part2Port , 0x49 , filterPtr[ index++ ] ) ;
9906 XGINew_SetReg1( pVBInfo->Part2Port , 0x4A , filterPtr[ index++ ] ) ;
9907 }
9908}
9909
9910
9911/* --------------------------------------------------------------------- */
9912/* Function : XGI_GetTVPtrIndex2 */
9913/* Input : */
9914/* Output : bx 0 : NTSC */
9915/* 1 : PAL */
9916/* 2 : PALM */
9917/* 3 : PALN */
9918/* 4 : NTSC1024x768 */
9919/* 5 : PAL-M 1024x768 */
9920/* 6-7: reserved */
9921/* cl 0 : YFilter1 */
9922/* 1 : YFilter2 */
9923/* ch 0 : 301A */
9924/* 1 : 301B/302B/301LV/302LV */
9925/* Description : */
9926/* --------------------------------------------------------------------- */
9927void XGI_GetTVPtrIndex2(USHORT* tempbx,UCHAR* tempcl,UCHAR* tempch, PVB_DEVICE_INFO pVBInfo)
9928{
9929 *tempbx = 0 ;
9930 *tempcl = 0 ;
9931 *tempch = 0 ;
9932
9933 if ( pVBInfo->TVInfo & SetPALTV )
9934 *tempbx = 1 ;
9935
9936 if ( pVBInfo->TVInfo & SetPALMTV )
9937 *tempbx = 2 ;
9938
9939 if ( pVBInfo->TVInfo & SetPALNTV )
9940 *tempbx = 3 ;
9941
9942 if ( pVBInfo->TVInfo & NTSC1024x768 )
9943 {
9944 *tempbx = 4 ;
9945 if ( pVBInfo->TVInfo & SetPALMTV )
9946 *tempbx = 5 ;
9947 }
9948
9949 if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
9950 {
9951 if ( ( !( pVBInfo->VBInfo & SetInSlaveMode ) ) || ( pVBInfo->TVInfo & TVSimuMode ) )
9952 {
9953 *tempbx += 8 ;
9954 *tempcl += 1 ;
9955 }
9956 }
9957
9958 if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
9959 (*tempch)++ ;
9960}
9961
9962
9963/* --------------------------------------------------------------------- */
9964/* Function : XGI_SetCRT2ModeRegs */
9965/* Input : */
9966/* Output : */
9967/* Description : Origin code for crt2group */
9968/* --------------------------------------------------------------------- */
9969void XGI_SetCRT2ModeRegs(USHORT ModeNo,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo)
9970{
9971 USHORT tempbl ;
9972 SHORT tempcl ;
9973
9974 UCHAR tempah ;
9975
9976 /* XGINew_SetReg1( pVBInfo->Part1Port , 0x03 , 0x00 ) ; // fix write part1 index 0 BTDRAM bit Bug */
9977 tempah=0;
9978 if ( !( pVBInfo->VBInfo & DisableCRT2Display ) )
9979 {
9980 tempah=XGINew_GetReg1( pVBInfo->Part1Port , 0x00 ) ;
9981 tempah &= ~0x10 ; /* BTRAMDAC */
9982 tempah |= 0x40 ; /* BTRAM */
9983
9984 if ( pVBInfo->VBInfo & ( SetCRT2ToRAMDAC | SetCRT2ToTV | SetCRT2ToLCD ) )
9985 {
9986 tempah=0x40; /* BTDRAM */
9987 if ( ModeNo > 0x13 )
9988 {
9989 tempcl = pVBInfo->ModeType ;
9990 tempcl -= ModeVGA ;
9991 if ( tempcl >= 0 )
9992 {
9993 tempah = ( 0x008 >> tempcl ) ; /* BT Color */
9994 if ( tempah == 0 )
9995 tempah = 1 ;
9996 tempah |= 0x040 ;
9997 }
9998 }
9999 if ( pVBInfo->VBInfo & SetInSlaveMode )
10000 tempah ^= 0x50 ; /* BTDAC */
10001 }
10002 }
10003
10004/* 0210 shampoo
10005 if ( pVBInfo->VBInfo & DisableCRT2Display )
10006 {
10007 tempah = 0 ;
10008 }
10009
10010 XGINew_SetReg1( pVBInfo->Part1Port , 0x00 , tempah ) ;
10011 if ( pVBInfo->VBInfo & ( SetCRT2ToRAMDAC | SetCRT2ToTV | SetCRT2ToLCD ) )
10012 {
10013 tempcl = pVBInfo->ModeType ;
10014 if ( ModeNo > 0x13 )
10015 {
10016 tempcl -= ModeVGA ;
10017 if ( ( tempcl > 0 ) || ( tempcl == 0 ) )
10018 {
10019 tempah=(0x008>>tempcl) ;
10020 if ( tempah == 0 )
10021 tempah = 1 ;
10022 tempah |= 0x040;
10023 }
10024 }
10025 else
10026 {
10027 tempah = 0x040 ;
10028 }
10029
10030 if ( pVBInfo->VBInfo & SetInSlaveMode )
10031 {
10032 tempah = ( tempah ^ 0x050 ) ;
10033 }
10034 }
10035*/
10036
10037 XGINew_SetReg1( pVBInfo->Part1Port , 0x00 , tempah ) ;
10038 tempah = 0x08 ;
10039 tempbl = 0xf0 ;
10040
10041 if ( pVBInfo->VBInfo & DisableCRT2Display )
10042 XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2e , tempbl , tempah ) ;
10043 else
10044 {
10045 tempah = 0x00 ;
10046 tempbl = 0xff ;
10047
10048 if ( pVBInfo->VBInfo & ( SetCRT2ToRAMDAC | SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToLCDA ) )
10049 {
10050 if ( ( pVBInfo->VBInfo & SetCRT2ToLCDA ) && ( !( pVBInfo->VBInfo & SetSimuScanMode ) ) )
10051 {
10052 tempbl &= 0xf7 ;
10053 tempah |= 0x01 ;
10054 XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2e , tempbl , tempah ) ;
10055 }
10056 else
10057 {
10058 if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
10059 {
10060 tempbl &= 0xf7 ;
10061 tempah |= 0x01 ;
10062 }
10063
10064 if ( pVBInfo->VBInfo & ( SetCRT2ToRAMDAC | SetCRT2ToTV | SetCRT2ToLCD ) )
10065 {
10066 tempbl &= 0xf8 ;
10067 tempah = 0x01 ;
10068
10069 if ( !( pVBInfo->VBInfo & SetInSlaveMode ) )
10070 tempah |= 0x02 ;
10071
10072 if ( !( pVBInfo->VBInfo & SetCRT2ToRAMDAC ) )
10073 {
10074 tempah = tempah ^ 0x05 ;
10075 if ( !( pVBInfo->VBInfo & SetCRT2ToLCD ) )
10076 tempah = tempah ^ 0x01 ;
10077 }
10078
10079 if ( !( pVBInfo->VBInfo & SetCRT2ToDualEdge ) )
10080 tempah |= 0x08 ;
10081 XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2e , tempbl , tempah ) ;
10082 }
10083 else
10084 XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2e , tempbl , tempah ) ;
10085 }
10086 }
10087 else
10088 XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2e , tempbl , tempah ) ;
10089 }
10090
10091 if ( pVBInfo->VBInfo & ( SetCRT2ToRAMDAC | SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToLCDA ) )
10092 {
10093 tempah &= ( ~0x08 ) ;
10094 if ( ( pVBInfo->ModeType == ModeVGA ) && ( !( pVBInfo->VBInfo & SetInSlaveMode ) ) )
10095 {
10096 tempah |= 0x010 ;
10097 }
10098 tempah |= 0x080 ;
10099
10100 if ( pVBInfo->VBInfo & SetCRT2ToTV )
10101 {
10102 /* if ( !( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p ) ) ) */
10103 /* { */
10104 tempah |= 0x020 ;
10105 if ( ModeNo > 0x13 )
10106 {
10107 if ( pVBInfo->VBInfo & DriverMode )
10108 tempah = tempah ^ 0x20 ;
10109 }
10110 /* } */
10111 }
10112
10113 XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x0D , ~0x0BF , tempah ) ;
10114 tempah = 0 ;
10115
10116 if ( pVBInfo->LCDInfo & SetLCDDualLink )
10117 tempah |= 0x40 ;
10118
10119 if ( pVBInfo->VBInfo & SetCRT2ToTV )
10120 {
10121 /* if ( ( !( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) ) && ( !( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p ) ) ) ) */
10122 /* { */
10123 if ( pVBInfo->TVInfo & RPLLDIV2XO )
10124 tempah |= 0x40 ;
10125 /* } */
10126 }
10127
10128 if ( ( pVBInfo->LCDResInfo == Panel1280x1024 ) || ( pVBInfo->LCDResInfo == Panel1280x1024x75 ) )
10129 tempah |= 0x80 ;
10130
10131 if ( pVBInfo->LCDResInfo == Panel1280x960 )
10132 tempah |= 0x80 ;
10133
10134 XGINew_SetReg1( pVBInfo->Part4Port , 0x0C , tempah ) ;
10135 }
10136
10137 if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) )
10138 {
10139 tempah = 0 ;
10140 tempbl = 0xfb ;
10141
10142 if ( pVBInfo->VBInfo & SetCRT2ToDualEdge )
10143 {
10144 tempbl=0xff;
10145 if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
10146 tempah |= 0x04 ; /* shampoo 0129 */
10147 }
10148
10149 XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x13 , tempbl , tempah ) ;
10150 tempah = 0x00 ;
10151 tempbl = 0xcf ;
10152 if ( !( pVBInfo->VBInfo & DisableCRT2Display ) )
10153 {
10154 if ( pVBInfo->VBInfo & SetCRT2ToDualEdge )
10155 tempah |= 0x30 ;
10156 }
10157
10158 XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2c , tempbl , tempah ) ;
10159 tempah = 0 ;
10160 tempbl = 0x3f ;
10161
10162 if ( !( pVBInfo->VBInfo & DisableCRT2Display ) )
10163 {
10164 if ( pVBInfo->VBInfo & SetCRT2ToDualEdge )
10165 tempah |= 0xc0 ;
10166 }
10167 XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x21 , tempbl , tempah ) ;
10168 }
10169
10170 tempah = 0 ;
10171 tempbl = 0x7f ;
10172 if ( !( pVBInfo->VBInfo & SetCRT2ToLCDA ) )
10173 {
10174 tempbl = 0xff ;
10175 if ( !( pVBInfo->VBInfo & SetCRT2ToDualEdge ) )
10176 tempah |= 0x80 ;
10177 }
10178
10179 XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x23 , tempbl , tempah ) ;
10180
10181 if ( pVBInfo->VBType & ( VB_XGI302LV | VB_XGI301C ) )
10182 {
10183 if ( pVBInfo->LCDInfo & SetLCDDualLink )
10184 {
10185 XGINew_SetRegOR( pVBInfo->Part4Port , 0x27 , 0x20 ) ;
10186 XGINew_SetRegOR( pVBInfo->Part4Port , 0x34 , 0x10 ) ;
10187 }
10188 }
10189}
10190
10191
10192/* --------------------------------------------------------------------- */
10193/* Function : XGI_CloseCRTC */
10194/* Input : */
10195/* Output : */
10196/* Description : */
10197/* --------------------------------------------------------------------- */
10198void XGI_CloseCRTC( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
10199{
10200 USHORT tempbx ;
10201
10202 tempbx = 0 ;
10203
10204 if ( pVBInfo->VBInfo & SetCRT2ToLCDA )
10205 tempbx = 0x08A0 ;
10206
10207
10208}
10209
10210
10211/* --------------------------------------------------------------------- */
10212/* Function : XGI_OpenCRTC */
10213/* Input : */
10214/* Output : */
10215/* Description : */
10216/* --------------------------------------------------------------------- */
10217void XGI_OpenCRTC( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
10218{
10219 USHORT tempbx ;
10220
10221 tempbx = 0 ;
10222
10223
10224}
10225
10226
10227/* --------------------------------------------------------------------- */
10228/* Function : XGI_GetRAMDAC2DATA */
10229/* Input : */
10230/* Output : */
10231/* Description : */
10232/* --------------------------------------------------------------------- */
10233void XGI_GetRAMDAC2DATA(USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo )
10234{
10235 USHORT tempax ,
10236 tempbx ,
10237 temp1 ,
10238 temp2 ,
10239 modeflag = 0 ,
10240 tempcx ,
10241 StandTableIndex ,
10242 CRT1Index ;
10243
10244 pVBInfo->RVBHCMAX = 1 ;
10245 pVBInfo->RVBHCFACT = 1 ;
10246
10247 if ( ModeNo <= 0x13 )
10248 {
10249 modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
10250 StandTableIndex = XGI_GetModePtr( ModeNo , ModeIdIndex, pVBInfo ) ;
10251 tempax = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 0 ] ;
10252 tempbx = pVBInfo->StandTable[StandTableIndex ].CRTC[ 6 ] ;
10253 temp1 = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 7 ] ;
10254 }
10255 else
10256 {
10257 modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
10258 CRT1Index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC ;
10259 CRT1Index &= IndexMask ;
10260 temp1 = ( USHORT )pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 0 ] ;
10261 temp2 = ( USHORT )pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 5 ] ;
10262 tempax = ( temp1 & 0xFF ) | ( ( temp2 & 0x03 ) << 8 ) ;
10263 tempbx = ( USHORT )pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 8 ] ;
10264 tempcx = ( USHORT )pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 14 ] << 8 ;
10265 tempcx &= 0x0100 ;
10266 tempcx = tempcx << 2 ;
10267 tempbx |= tempcx;
10268 temp1 = ( USHORT )pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 9 ] ;
10269 }
10270
10271 if ( temp1 & 0x01 )
10272 tempbx |= 0x0100 ;
10273
10274 if ( temp1 & 0x20 )
10275 tempbx |= 0x0200 ;
10276 tempax += 5 ;
10277
10278 if ( modeflag & Charx8Dot )
10279 tempax *= 8 ;
10280 else
10281 tempax *= 9 ;
10282
10283 pVBInfo->VGAHT = tempax ;
10284 pVBInfo->HT = tempax ;
10285 tempbx++ ;
10286 pVBInfo->VGAVT = tempbx ;
10287 pVBInfo->VT = tempbx ;
10288}
10289
10290
10291
10292/* --------------------------------------------------------------------- */
10293/* Function : XGI_GetColorDepth */
10294/* Input : */
10295/* Output : */
10296/* Description : */
10297/* --------------------------------------------------------------------- */
10298USHORT XGI_GetColorDepth(USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo)
10299{
10300 USHORT ColorDepth[ 6 ] = { 1 , 2 , 4 , 4 , 6 , 8 } ;
10301 SHORT index ;
10302 USHORT modeflag ;
10303
10304 if ( ModeNo <= 0x13 )
10305 {
10306 modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ;
10307 }
10308 else
10309 {
10310 modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ;
10311 }
10312
10313 index=(modeflag&ModeInfoFlag)-ModeEGA;
10314
10315 if ( index < 0 )
10316 index = 0 ;
10317
10318 return( ColorDepth[ index ] ) ;
10319}
10320
10321
10322
10323/* --------------------------------------------------------------------- */
10324/* Function : XGI_UnLockCRT2 */
10325/* Input : */
10326/* Output : */
10327/* Description : */
10328/* --------------------------------------------------------------------- */
10329void XGI_UnLockCRT2( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
10330{
10331
10332 XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2f , 0xFF , 0x01 ) ;
10333
10334}
10335
10336
10337/* --------------------------------------------------------------------- */
10338/* Function : XGI_LockCRT2 */
10339/* Input : */
10340/* Output : */
10341/* Description : */
10342/* --------------------------------------------------------------------- */
10343void XGI_LockCRT2( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo )
10344{
10345
10346 XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2F , 0xFE , 0x00 ) ;
10347
10348
10349}
10350
10351
10352/* --------------------------------------------------------------------- */
10353/* Function : XGINew_EnableCRT2 */
10354/* Input : */
10355/* Output : */
10356/* Description : */
10357/* --------------------------------------------------------------------- */
10358void XGINew_EnableCRT2( PVB_DEVICE_INFO pVBInfo)
10359{
10360 XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x1E , 0xFF , 0x20 ) ;
10361}
10362
10363
10364
10365/* --------------------------------------------------------------------- */
10366/* Function : */
10367/* Input : */
10368/* Output : */
10369/* Description : */
10370/* --------------------------------------------------------------------- */
10371void XGINew_LCD_Wait_Time(UCHAR DelayTime, PVB_DEVICE_INFO pVBInfo)
10372{
10373 USHORT i ,
10374 j ;
10375
10376 ULONG temp ,
10377 flag ;
10378
10379 flag = 0 ;
10380//printk("XGINew_LCD_Wait_Time");
10381//return;
10382 for( i = 0 ; i < DelayTime ; i++ )
10383 {
10384 for( j = 0 ; j < 66 ; j++ )
10385 {
10386
10387 temp = XGINew_GetReg3( 0x61 ) ;
10388
10389 //temp &= 0x10000000;
10390 temp &= 0x10;
10391 if ( temp == flag )
10392 continue ;
10393
10394 flag = temp ;
10395 }
10396 }
10397}
10398
10399
10400
10401
10402/* --------------------------------------------------------------------- */
10403/* Function : XGI_BridgeIsOn */
10404/* Input : */
10405/* Output : */
10406/* Description : */
10407/* --------------------------------------------------------------------- */
10408BOOLEAN XGI_BridgeIsOn( PVB_DEVICE_INFO pVBInfo )
10409{
10410 USHORT flag ;
10411
10412 if ( pVBInfo->IF_DEF_LVDS == 1 )
10413 {
10414 return( 1 ) ;
10415 }
10416 else
10417 {
10418 flag = XGINew_GetReg1( pVBInfo->Part4Port , 0x00 ) ;
10419 if ( ( flag == 1 ) || ( flag == 2 ) )
10420 return( 1 ) ; /* 301b */
10421 else
10422 return( 0 ) ;
10423 }
10424}
10425
10426
10427
10428/* --------------------------------------------------------------------- */
10429/* Function : XGI_LongWait */
10430/* Input : */
10431/* Output : */
10432/* Description : */
10433/* --------------------------------------------------------------------- */
10434void XGI_LongWait(PVB_DEVICE_INFO pVBInfo)
10435{
10436 USHORT i ;
10437
10438 i = XGINew_GetReg1( pVBInfo->P3c4 , 0x1F ) ;
10439
10440 if ( !( i & 0xC0 ) )
10441 {
10442 for( i = 0 ; i < 0xFFFF ; i++ )
10443 {
10444 if ( !( XGINew_GetReg2( pVBInfo->P3da ) & 0x08 ) )
10445 break ;
10446 }
10447
10448 for( i = 0 ; i < 0xFFFF ; i++ )
10449 {
10450 if ( ( XGINew_GetReg2( pVBInfo->P3da ) & 0x08 ) )
10451 break ;
10452 }
10453 }
10454}
10455
10456
10457/* --------------------------------------------------------------------- */
10458/* Function : XGI_VBLongWait */
10459/* Input : */
10460/* Output : */
10461/* Description : */
10462/* --------------------------------------------------------------------- */
10463void XGI_VBLongWait( PVB_DEVICE_INFO pVBInfo )
10464{
10465 USHORT tempal ,
10466 temp ,
10467 i ,
10468 j ;
10469return ;
10470 if ( !( pVBInfo->VBInfo & SetCRT2ToTV ) )
10471 {
10472 temp = 0 ;
10473 for( i = 0 ; i < 3 ; i++ )
10474 {
10475 for( j = 0 ; j < 100 ; j++ )
10476 {
10477 tempal = XGINew_GetReg2( pVBInfo->P3da ) ;
10478 if ( temp & 0x01 )
10479 { /* VBWaitMode2 */
10480 if ( ( tempal & 0x08 ) )
10481 {
10482 continue ;
10483 }
10484
10485 if ( !( tempal & 0x08 ) )
10486 {
10487 break ;
10488 }
10489 }
10490 else
10491 { /* VBWaitMode1 */
10492 if ( !( tempal & 0x08 ) )
10493 {
10494 continue ;
10495 }
10496
10497 if ( ( tempal & 0x08 ) )
10498 {
10499 break ;
10500 }
10501 }
10502 }
10503 temp = temp ^ 0x01 ;
10504 }
10505 }
10506 else
10507 {
10508 XGI_LongWait(pVBInfo) ;
10509 }
10510 return ;
10511}
10512
10513
10514
10515
10516/* --------------------------------------------------------------------- */
10517/* Function : XGI_GetVGAHT2 */
10518/* Input : */
10519/* Output : */
10520/* Description : */
10521/* --------------------------------------------------------------------- */
10522USHORT XGI_GetVGAHT2( PVB_DEVICE_INFO pVBInfo )
10523{
10524 ULONG tempax ,
10525 tempbx ;
10526
10527 tempbx = ( ( pVBInfo->VGAVT - pVBInfo->VGAVDE ) * pVBInfo->RVBHCMAX ) & 0xFFFF ;
10528 tempax = ( pVBInfo->VT - pVBInfo->VDE ) * pVBInfo->RVBHCFACT ;
10529 tempax = ( tempax * pVBInfo->HT ) /tempbx ;
10530
10531 return( ( USHORT )tempax ) ;
10532}
10533
10534
10535/* --------------------------------------------------------------------- */
10536/* Function : XGI_GetVCLK2Ptr */
10537/* Input : */
10538/* Output : */
10539/* Description : */
10540/* --------------------------------------------------------------------- */
10541USHORT XGI_GetVCLK2Ptr( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension ,PVB_DEVICE_INFO pVBInfo)
10542{
10543 USHORT tempbx ;
10544
10545 USHORT LCDXlat1VCLK[ 4 ] = { VCLK65 + 2 , VCLK65 + 2 , VCLK65 + 2 , VCLK65 + 2 } ;
10546 USHORT LCDXlat2VCLK[ 4 ] = { VCLK108_2 + 5 , VCLK108_2 + 5 , VCLK108_2 + 5 , VCLK108_2 + 5 } ;
10547 USHORT LVDSXlat1VCLK[ 4 ] = { VCLK40 , VCLK40 , VCLK40 , VCLK40 } ;
10548 USHORT LVDSXlat2VCLK[ 4 ] = { VCLK65 + 2 , VCLK65 + 2 , VCLK65 + 2 , VCLK65 + 2 } ;
10549 USHORT LVDSXlat3VCLK[ 4 ] = { VCLK65 + 2 , VCLK65 + 2 , VCLK65 + 2 , VCLK65 + 2 } ;
10550
10551 USHORT CRT2Index , VCLKIndex ;
10552 USHORT modeflag , resinfo ;
10553 UCHAR *CHTVVCLKPtr = NULL ;
10554
10555 if ( ModeNo <= 0x13 )
10556 {
10557 modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; /* si+St_ResInfo */
10558 resinfo = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ResInfo ;
10559 CRT2Index = pVBInfo->SModeIDTable[ ModeIdIndex ].St_CRT2CRTC ;
10560 }
10561 else
10562 {
10563 modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; /* si+Ext_ResInfo */
10564 resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ;
10565 CRT2Index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT2CRTC ;
10566 }
10567
10568 if ( pVBInfo->IF_DEF_LVDS == 0 )
10569 {
10570 CRT2Index = CRT2Index >> 6 ; /* for LCD */
10571 if ( ( ( pVBInfo->VBInfo & SetCRT2ToLCD ) | SetCRT2ToLCDA ) ) /*301b*/
10572 {
10573 if ( pVBInfo->LCDResInfo != Panel1024x768 )
10574 {
10575 VCLKIndex = LCDXlat2VCLK[ CRT2Index ] ;
10576 }
10577 else
10578 {
10579 VCLKIndex = LCDXlat1VCLK[ CRT2Index ] ;
10580 }
10581 }
10582 else /* for TV */
10583 {
10584 if ( pVBInfo->VBInfo & SetCRT2ToTV )
10585 {
10586 if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV )
10587 {
10588 if ( pVBInfo->SetFlag & RPLLDIV2XO )
10589 {
10590 VCLKIndex = HiTVVCLKDIV2 ;
10591
10592
10593 VCLKIndex += 25 ;
10594
10595 }
10596 else
10597 {
10598 VCLKIndex = HiTVVCLK ;
10599
10600
10601 VCLKIndex += 25 ;
10602
10603 }
10604
10605 if ( pVBInfo->SetFlag & TVSimuMode )
10606 {
10607 if( modeflag & Charx8Dot )
10608 {
10609 VCLKIndex = HiTVSimuVCLK ;
10610
10611
10612 VCLKIndex += 25 ;
10613
10614 }
10615 else
10616 {
10617 VCLKIndex = HiTVTextVCLK ;
10618
10619
10620 VCLKIndex += 25 ;
10621
10622 }
10623 }
10624
10625 if ( pVBInfo->VBType & VB_XGI301LV ) /* 301lv */
10626 {
10627 if ( !( pVBInfo->VBExtInfo == VB_YPbPr1080i ) )
10628 {
10629 VCLKIndex = YPbPr750pVCLK ;
10630 if ( !( pVBInfo->VBExtInfo == VB_YPbPr750p ) )
10631 {
10632 VCLKIndex = YPbPr525pVCLK ;
10633 if ( !( pVBInfo->VBExtInfo == VB_YPbPr525p ) )
10634 {
10635 VCLKIndex = YPbPr525iVCLK_2 ;
10636 if ( !( pVBInfo->SetFlag & RPLLDIV2XO ) )
10637 VCLKIndex = YPbPr525iVCLK ;
10638 }
10639 }
10640 }
10641 }
10642 }
10643 else
10644 {
10645 if ( pVBInfo->VBInfo & SetCRT2ToTV )
10646 {
10647 if ( pVBInfo->SetFlag & RPLLDIV2XO )
10648 {
10649 VCLKIndex = TVVCLKDIV2 ;
10650
10651
10652 VCLKIndex += 25 ;
10653
10654 }
10655 else
10656 {
10657 VCLKIndex = TVVCLK ;
10658
10659
10660 VCLKIndex += 25 ;
10661
10662 }
10663 }
10664 }
10665 }
10666 else
10667 { /* for CRT2 */
10668 VCLKIndex = ( UCHAR )XGINew_GetReg2( ( pVBInfo->P3ca + 0x02 ) ) ; /* Port 3cch */
10669 VCLKIndex = ( ( VCLKIndex >> 2 ) & 0x03 ) ;
10670 if ( ModeNo > 0x13 )
10671 {
10672 VCLKIndex = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRTVCLK ; /* di+Ext_CRTVCLK */
10673 VCLKIndex &= IndexMask ;
10674 }
10675 }
10676 }
10677 }
10678 else
10679 { /* LVDS */
10680 if ( ModeNo <= 0x13 )
10681 VCLKIndex = CRT2Index ;
10682 else
10683 VCLKIndex = CRT2Index ;
10684
10685 if ( pVBInfo->IF_DEF_CH7005 == 1 )
10686 {
10687 if ( !( pVBInfo->VBInfo & SetCRT2ToLCD ) )
10688 {
10689 VCLKIndex &= 0x1f ;
10690 tempbx = 0 ;
10691
10692 if ( pVBInfo->VBInfo & SetPALTV )
10693 tempbx += 2 ;
10694
10695 if ( pVBInfo->VBInfo & SetCHTVOverScan )
10696 tempbx += 1 ;
10697
10698 switch( tempbx )
10699 {
10700 case 0:
10701 CHTVVCLKPtr = pVBInfo->CHTVVCLKUNTSC ;
10702 break ;
10703 case 1:
10704 CHTVVCLKPtr = pVBInfo->CHTVVCLKONTSC ;
10705 break;
10706 case 2:
10707 CHTVVCLKPtr = pVBInfo->CHTVVCLKUPAL ;
10708 break ;
10709 case 3:
10710 CHTVVCLKPtr = pVBInfo->CHTVVCLKOPAL ;
10711 break ;
10712 default:
10713 break ;
10714 }
10715
10716 VCLKIndex = CHTVVCLKPtr[ VCLKIndex ] ;
10717 }
10718 }
10719 else
10720 {
10721 VCLKIndex = VCLKIndex >> 6 ;
10722 if ( ( pVBInfo->LCDResInfo == Panel800x600 ) || ( pVBInfo->LCDResInfo == Panel320x480 ) )
10723 VCLKIndex = LVDSXlat1VCLK[ VCLKIndex ] ;
10724 else if ( ( pVBInfo->LCDResInfo == Panel1024x768 ) || ( pVBInfo->LCDResInfo == Panel1024x768x75 ) )
10725 VCLKIndex = LVDSXlat2VCLK[ VCLKIndex ] ;
10726 else
10727 VCLKIndex = LVDSXlat3VCLK[ VCLKIndex ] ;
10728 }
10729 }
10730 /* VCLKIndex = VCLKIndex&IndexMask ; */
10731
10732
10733
10734 return( VCLKIndex ) ;
10735}
10736
diff --git a/drivers/staging/xgifb/vb_setmode.h b/drivers/staging/xgifb/vb_setmode.h
new file mode 100644
index 000000000000..09753d706665
--- /dev/null
+++ b/drivers/staging/xgifb/vb_setmode.h
@@ -0,0 +1,40 @@
1#ifndef _VBSETMODE_
2#define _VBSETMODE_
3
4extern void InitTo330Pointer(UCHAR,PVB_DEVICE_INFO);
5extern void XGI_UnLockCRT2(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
6extern void XGI_LockCRT2(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
7extern void XGI_LongWait( PVB_DEVICE_INFO );
8extern void XGI_SetCRT2ModeRegs(USHORT ModeNo,PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO );
9extern void XGI_DisableBridge(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
10extern void XGI_EnableBridge(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
11extern void XGI_DisplayOff( PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO );
12extern void XGI_DisplayOn( PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO );
13extern void XGI_GetVBType(PVB_DEVICE_INFO);
14extern void XGI_SenseCRT1(PVB_DEVICE_INFO );
15extern void XGI_GetVGAType(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
16extern void XGI_GetVBInfo(USHORT ModeNo,USHORT ModeIdIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
17extern void XGI_GetTVInfo(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO );
18extern void XGI_SetCRT1Offset(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
19extern void XGI_SetLCDAGroup(USHORT ModeNo,USHORT ModeIdIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO );
20extern void XGI_WaitDisply( PVB_DEVICE_INFO );
21extern USHORT XGI_GetResInfo(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo);
22
23extern BOOLEAN XGISetModeNew( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo ) ;
24
25extern BOOLEAN XGI_SearchModeID( USHORT ModeNo,USHORT *ModeIdIndex, PVB_DEVICE_INFO );
26extern BOOLEAN XGI_GetLCDInfo(USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO );
27extern BOOLEAN XGI_BridgeIsOn( PVB_DEVICE_INFO );
28extern BOOLEAN XGI_SetCRT2Group301(USHORT ModeNo, PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO);
29extern USHORT XGI_GetRatePtrCRT2( PXGI_HW_DEVICE_INFO pXGIHWDE, USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO );
30
31extern void XGI_SetXG21FPBits(PVB_DEVICE_INFO pVBInfo);
32extern void XGI_SetXG27FPBits(PVB_DEVICE_INFO pVBInfo);
33extern void XGI_XG21BLSignalVDD(USHORT tempbh,USHORT tempbl, PVB_DEVICE_INFO pVBInfo);
34extern void XGI_XG27BLSignalVDD(USHORT tempbh,USHORT tempbl, PVB_DEVICE_INFO pVBInfo);
35extern void XGI_XG21SetPanelDelay(USHORT tempbl, PVB_DEVICE_INFO pVBInfo);
36extern BOOLEAN XGI_XG21CheckLVDSMode(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo );
37extern void XGI_SetXG21LVDSPara(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo );
38extern USHORT XGI_GetLVDSOEMTableIndex(PVB_DEVICE_INFO pVBInfo);
39
40#endif
diff --git a/drivers/staging/xgifb/vb_struct.h b/drivers/staging/xgifb/vb_struct.h
new file mode 100644
index 000000000000..bb25c0e2785e
--- /dev/null
+++ b/drivers/staging/xgifb/vb_struct.h
@@ -0,0 +1,534 @@
1#ifndef _VB_STRUCT_
2#define _VB_STRUCT_
3
4#ifdef _INITNEW_
5#define EXTERN
6#else
7#define EXTERN extern
8#endif
9
10
11
12
13typedef struct _XGI_PanelDelayTblStruct
14{
15 UCHAR timer[2];
16} XGI_PanelDelayTblStruct;
17
18typedef struct _XGI_LCDDataStruct
19{
20 USHORT RVBHCMAX;
21 USHORT RVBHCFACT;
22 USHORT VGAHT;
23 USHORT VGAVT;
24 USHORT LCDHT;
25 USHORT LCDVT;
26} XGI_LCDDataStruct;
27
28
29typedef struct _XGI_LVDSCRT1HDataStruct
30{
31 UCHAR Reg[8];
32} XGI_LVDSCRT1HDataStruct;
33typedef struct _XGI_LVDSCRT1VDataStruct
34{
35 UCHAR Reg[7];
36} XGI_LVDSCRT1VDataStruct;
37
38
39typedef struct _XGI_TVDataStruct
40{
41 USHORT RVBHCMAX;
42 USHORT RVBHCFACT;
43 USHORT VGAHT;
44 USHORT VGAVT;
45 USHORT TVHDE;
46 USHORT TVVDE;
47 USHORT RVBHRS;
48 UCHAR FlickerMode;
49 USHORT HALFRVBHRS;
50 UCHAR RY1COE;
51 UCHAR RY2COE;
52 UCHAR RY3COE;
53 UCHAR RY4COE;
54} XGI_TVDataStruct;
55
56typedef struct _XGI_LVDSDataStruct
57{
58 USHORT VGAHT;
59 USHORT VGAVT;
60 USHORT LCDHT;
61 USHORT LCDVT;
62} XGI_LVDSDataStruct;
63
64typedef struct _XGI_LVDSDesStruct
65{
66 USHORT LCDHDES;
67 USHORT LCDVDES;
68} XGI_LVDSDesStruct;
69
70typedef struct _XGI_LVDSCRT1DataStruct
71{
72 UCHAR CR[15];
73} XGI_LVDSCRT1DataStruct;
74
75/*add for LCDA*/
76
77
78typedef struct _XGI_StStruct
79{
80 UCHAR St_ModeID;
81 USHORT St_ModeFlag;
82 UCHAR St_StTableIndex;
83 UCHAR St_CRT2CRTC;
84 UCHAR St_CRT2CRTC2;
85 UCHAR St_ResInfo;
86 UCHAR VB_StTVFlickerIndex;
87 UCHAR VB_StTVEdgeIndex;
88 UCHAR VB_StTVYFilterIndex;
89} XGI_StStruct;
90
91typedef struct _XGI_StandTableStruct
92{
93 UCHAR CRT_COLS;
94 UCHAR ROWS;
95 UCHAR CHAR_HEIGHT;
96 USHORT CRT_LEN;
97 UCHAR SR[4];
98 UCHAR MISC;
99 UCHAR CRTC[0x19];
100 UCHAR ATTR[0x14];
101 UCHAR GRC[9];
102} XGI_StandTableStruct;
103
104typedef struct _XGI_ExtStruct
105{
106 UCHAR Ext_ModeID;
107 USHORT Ext_ModeFlag;
108 USHORT Ext_ModeInfo;
109 USHORT Ext_Point;
110 USHORT Ext_VESAID;
111 UCHAR Ext_VESAMEMSize;
112 UCHAR Ext_RESINFO;
113 UCHAR VB_ExtTVFlickerIndex;
114 UCHAR VB_ExtTVEdgeIndex;
115 UCHAR VB_ExtTVYFilterIndex;
116 UCHAR REFindex;
117} XGI_ExtStruct;
118
119typedef struct _XGI_Ext2Struct
120{
121 USHORT Ext_InfoFlag;
122 UCHAR Ext_CRT1CRTC;
123 UCHAR Ext_CRTVCLK;
124 UCHAR Ext_CRT2CRTC;
125 UCHAR Ext_CRT2CRTC2;
126 UCHAR ModeID;
127 USHORT XRes;
128 USHORT YRes;
129 /* USHORT ROM_OFFSET; */
130} XGI_Ext2Struct;
131
132
133typedef struct _XGI_MCLKDataStruct
134{
135 UCHAR SR28,SR29,SR2A;
136 USHORT CLOCK;
137} XGI_MCLKDataStruct;
138
139typedef struct _XGI_ECLKDataStruct
140{
141 UCHAR SR2E,SR2F,SR30;
142 USHORT CLOCK;
143} XGI_ECLKDataStruct;
144
145typedef struct _XGI_VCLKDataStruct
146{
147 UCHAR SR2B,SR2C;
148 USHORT CLOCK;
149} XGI_VCLKDataStruct;
150
151typedef struct _XGI_VBVCLKDataStruct
152{
153 UCHAR Part4_A,Part4_B;
154 USHORT CLOCK;
155} XGI_VBVCLKDataStruct;
156
157typedef struct _XGI_StResInfoStruct
158{
159 USHORT HTotal;
160 USHORT VTotal;
161} XGI_StResInfoStruct;
162
163typedef struct _XGI_ModeResInfoStruct
164{
165 USHORT HTotal;
166 USHORT VTotal;
167 UCHAR XChar;
168 UCHAR YChar;
169} XGI_ModeResInfoStruct;
170
171typedef struct _XGI_LCDNBDesStruct
172{
173 UCHAR NB[12];
174} XGI_LCDNBDesStruct;
175 /*add for new UNIVGABIOS*/
176typedef struct _XGI_LCDDesStruct
177{
178 USHORT LCDHDES;
179 USHORT LCDHRS;
180 USHORT LCDVDES;
181 USHORT LCDVRS;
182} XGI_LCDDesStruct;
183
184typedef struct _XGI_LCDDataTablStruct
185{
186 UCHAR PANELID;
187 USHORT MASK;
188 USHORT CAP;
189 USHORT DATAPTR;
190} XGI_LCDDataTablStruct;
191
192typedef struct _XGI_TVTablDataStruct
193{
194 USHORT MASK;
195 USHORT CAP;
196 USHORT DATAPTR;
197} XGI_TVDataTablStruct;
198
199typedef struct _XGI330_LCDDesDataStruct
200{
201 USHORT LCDHDES;
202 USHORT LCDHRS;
203 USHORT LCDVDES;
204 USHORT LCDVRS;
205} XGI330_LCDDataDesStruct;
206
207
208typedef struct _XGI330_LVDSDataStruct
209{
210 USHORT VGAHT;
211 USHORT VGAVT;
212 USHORT LCDHT;
213 USHORT LCDVT;
214} XGI330_LVDSDataStruct;
215
216typedef struct _XGI330_LCDDesDataStruct2
217{
218 USHORT LCDHDES;
219 USHORT LCDHRS;
220 USHORT LCDVDES;
221 USHORT LCDVRS;
222 USHORT LCDHSync;
223 USHORT LCDVSync;
224} XGI330_LCDDataDesStruct2;
225
226typedef struct _XGI330_LCDDataStruct
227{
228 USHORT RVBHCMAX;
229 USHORT RVBHCFACT;
230 USHORT VGAHT;
231 USHORT VGAVT;
232 USHORT LCDHT;
233 USHORT LCDVT;
234} XGI330_LCDDataStruct;
235
236
237typedef struct _XGI330_TVDataStruct
238{
239 USHORT RVBHCMAX;
240 USHORT RVBHCFACT;
241 USHORT VGAHT;
242 USHORT VGAVT;
243 USHORT TVHDE;
244 USHORT TVVDE;
245 USHORT RVBHRS;
246 UCHAR FlickerMode;
247 USHORT HALFRVBHRS;
248} XGI330_TVDataStruct;
249
250typedef struct _XGI330_LCDDataTablStruct
251{
252 UCHAR PANELID;
253 USHORT MASK;
254 USHORT CAP;
255 USHORT DATAPTR;
256} XGI330_LCDDataTablStruct;
257
258typedef struct _XGI330_TVDataTablStruct
259{
260 USHORT MASK;
261 USHORT CAP;
262 USHORT DATAPTR;
263} XGI330_TVDataTablStruct;
264
265
266typedef struct _XGI330_CHTVDataStruct
267{
268 USHORT VGAHT;
269 USHORT VGAVT;
270 USHORT LCDHT;
271 USHORT LCDVT;
272} XGI330_CHTVDataStruct;
273
274typedef struct _XGI_TimingHStruct
275{
276 UCHAR data[8];
277} XGI_TimingHStruct;
278
279typedef struct _XGI_TimingVStruct
280{
281 UCHAR data[7];
282} XGI_TimingVStruct;
283
284typedef struct _XGI_CH7007TV_TimingHStruct
285{
286 UCHAR data[10];
287} XGI_CH7007TV_TimingHStruct;
288
289typedef struct _XGI_CH7007TV_TimingVStruct
290{
291 UCHAR data[10];
292} XGI_CH7007TV_TimingVStruct;
293
294typedef struct _XGI_XG21CRT1Struct
295{
296 UCHAR ModeID,CR02,CR03,CR15,CR16;
297} XGI_XG21CRT1Struct;
298
299typedef struct _XGI330_CHTVRegDataStruct
300{
301 UCHAR Reg[16];
302} XGI330_CHTVRegDataStruct;
303
304typedef struct _XGI330_LCDCapStruct
305{
306 UCHAR LCD_ID;
307 USHORT LCD_Capability;
308 UCHAR LCD_SetFlag;
309 UCHAR LCD_DelayCompensation;
310 UCHAR LCD_HSyncWidth;
311 UCHAR LCD_VSyncWidth;
312 UCHAR LCD_VCLK;
313 UCHAR LCDA_VCLKData1;
314 UCHAR LCDA_VCLKData2;
315 UCHAR LCUCHAR_VCLKData1;
316 UCHAR LCUCHAR_VCLKData2;
317 UCHAR PSC_S1;
318 UCHAR PSC_S2;
319 UCHAR PSC_S3;
320 UCHAR PSC_S4;
321 UCHAR PSC_S5;
322 UCHAR PWD_2B;
323 UCHAR PWD_2C;
324 UCHAR PWD_2D;
325 UCHAR PWD_2E;
326 UCHAR PWD_2F;
327 UCHAR Spectrum_31;
328 UCHAR Spectrum_32;
329 UCHAR Spectrum_33;
330 UCHAR Spectrum_34;
331} XGI330_LCDCapStruct;
332
333typedef struct _XGI21_LVDSCapStruct
334{
335 USHORT LVDS_Capability;
336 USHORT LVDSHT;
337 USHORT LVDSVT;
338 USHORT LVDSHDE;
339 USHORT LVDSVDE;
340 USHORT LVDSHFP;
341 USHORT LVDSVFP;
342 USHORT LVDSHSYNC;
343 USHORT LVDSVSYNC;
344 UCHAR VCLKData1;
345 UCHAR VCLKData2;
346 UCHAR PSC_S1;
347 UCHAR PSC_S2;
348 UCHAR PSC_S3;
349 UCHAR PSC_S4;
350 UCHAR PSC_S5;
351} XGI21_LVDSCapStruct;
352
353typedef struct _XGI_CRT1TableStruct
354{
355 UCHAR CR[16];
356} XGI_CRT1TableStruct;
357
358
359typedef struct _XGI330_VCLKDataStruct
360{
361 UCHAR SR2B,SR2C;
362 USHORT CLOCK;
363} XGI330_VCLKDataStruct;
364
365typedef struct _XGI301C_Tap4TimingStruct
366{
367 USHORT DE;
368 UCHAR Reg[64]; /* C0-FF */
369} XGI301C_Tap4TimingStruct;
370
371typedef struct _XGI_New_StandTableStruct
372{
373 UCHAR CRT_COLS;
374 UCHAR ROWS;
375 UCHAR CHAR_HEIGHT;
376 USHORT CRT_LEN;
377 UCHAR SR[4];
378 UCHAR MISC;
379 UCHAR CRTC[0x19];
380 UCHAR ATTR[0x14];
381 UCHAR GRC[9];
382} XGI_New_StandTableStruct;
383
384typedef UCHAR DRAM8Type[8];
385typedef UCHAR DRAM4Type[4];
386typedef UCHAR DRAM32Type[32];
387typedef UCHAR DRAM2Type[2];
388
389typedef struct _VB_DEVICE_INFO VB_DEVICE_INFO;
390typedef VB_DEVICE_INFO * PVB_DEVICE_INFO;
391
392struct _VB_DEVICE_INFO
393{
394 BOOLEAN ISXPDOS;
395 ULONG P3c4,P3d4,P3c0,P3ce,P3c2,P3cc;
396 ULONG P3ca,P3c6,P3c7,P3c8,P3c9,P3da;
397 ULONG Part0Port,Part1Port,Part2Port;
398 ULONG Part3Port,Part4Port,Part5Port;
399 USHORT RVBHCFACT,RVBHCMAX,RVBHRS;
400 USHORT VGAVT,VGAHT,VGAVDE,VGAHDE;
401 USHORT VT,HT,VDE,HDE;
402 USHORT LCDHRS,LCDVRS,LCDHDES,LCDVDES;
403
404 USHORT ModeType;
405 USHORT IF_DEF_LVDS,IF_DEF_TRUMPION,IF_DEF_DSTN;/* ,IF_DEF_FSTN; add for dstn */
406 USHORT IF_DEF_CRT2Monitor,IF_DEF_VideoCapture;
407 USHORT IF_DEF_LCDA,IF_DEF_CH7017,IF_DEF_YPbPr,IF_DEF_ScaleLCD,IF_DEF_OEMUtil,IF_DEF_PWD;
408 USHORT IF_DEF_ExpLink;
409 USHORT IF_DEF_CH7005,IF_DEF_HiVision;
410 USHORT IF_DEF_CH7007; /* Billy 2007/05/03 */
411 USHORT LCDResInfo,LCDTypeInfo, VBType;/*301b*/
412 USHORT VBInfo,TVInfo,LCDInfo, Set_VGAType;
413 USHORT VBExtInfo;/*301lv*/
414 USHORT SetFlag;
415 USHORT NewFlickerMode;
416 USHORT SelectCRT2Rate;
417
418 PUCHAR ROMAddr;
419 PUCHAR FBAddr;
420 ULONG BaseAddr;
421 ULONG RelIO;
422
423 DRAM4Type *CR6B;
424 DRAM4Type *CR6E;
425 DRAM32Type *CR6F;
426 DRAM2Type *CR89;
427
428 DRAM8Type *SR15; /* pointer : point to array */
429 DRAM8Type *CR40;
430 UCHAR *pSoftSetting;
431 UCHAR *pOutputSelect;
432
433 USHORT *pRGBSenseData;
434 USHORT *pRGBSenseData2; /*301b*/
435 USHORT *pVideoSenseData;
436 USHORT *pVideoSenseData2;
437 USHORT *pYCSenseData;
438 USHORT *pYCSenseData2;
439
440 UCHAR *pSR07;
441 UCHAR *CR49;
442 UCHAR *pSR1F;
443 UCHAR *AGPReg;
444 UCHAR *SR16;
445 UCHAR *pSR21;
446 UCHAR *pSR22;
447 UCHAR *pSR23;
448 UCHAR *pSR24;
449 UCHAR *SR25;
450 UCHAR *pSR31;
451 UCHAR *pSR32;
452 UCHAR *pSR33;
453 UCHAR *pSR36; /* alan 12/07/2006 */
454 UCHAR *pCRCF;
455 UCHAR *pCRD0; /* alan 12/07/2006 */
456 UCHAR *pCRDE; /* alan 12/07/2006 */
457 UCHAR *pCR8F; /* alan 12/07/2006 */
458 UCHAR *pSR40; /* alan 12/07/2006 */
459 UCHAR *pSR41; /* alan 12/07/2006 */
460 UCHAR *pDVOSetting;
461 UCHAR *pCR2E;
462 UCHAR *pCR2F;
463 UCHAR *pCR46;
464 UCHAR *pCR47;
465 UCHAR *pCRT2Data_1_2;
466 UCHAR *pCRT2Data_4_D;
467 UCHAR *pCRT2Data_4_E;
468 UCHAR *pCRT2Data_4_10;
469 XGI_MCLKDataStruct *MCLKData;
470 XGI_ECLKDataStruct *ECLKData;
471
472 UCHAR *XGI_TVDelayList;
473 UCHAR *XGI_TVDelayList2;
474 UCHAR *CHTVVCLKUNTSC;
475 UCHAR *CHTVVCLKONTSC;
476 UCHAR *CHTVVCLKUPAL;
477 UCHAR *CHTVVCLKOPAL;
478 UCHAR *NTSCTiming;
479 UCHAR *PALTiming;
480 UCHAR *HiTVExtTiming;
481 UCHAR *HiTVSt1Timing;
482 UCHAR *HiTVSt2Timing;
483 UCHAR *HiTVTextTiming;
484 UCHAR *YPbPr750pTiming;
485 UCHAR *YPbPr525pTiming;
486 UCHAR *YPbPr525iTiming;
487 UCHAR *HiTVGroup3Data;
488 UCHAR *HiTVGroup3Simu;
489 UCHAR *HiTVGroup3Text;
490 UCHAR *Ren525pGroup3;
491 UCHAR *Ren750pGroup3;
492 UCHAR *ScreenOffset;
493 UCHAR *pXGINew_DRAMTypeDefinition;
494 UCHAR *pXGINew_I2CDefinition ;
495 UCHAR *pXGINew_CR97 ;
496
497 XGI330_LCDCapStruct *LCDCapList;
498 XGI21_LVDSCapStruct *XG21_LVDSCapList;
499
500 XGI_TimingHStruct *TimingH;
501 XGI_TimingVStruct *TimingV;
502
503 XGI_StStruct *SModeIDTable;
504 XGI_StandTableStruct *StandTable;
505 XGI_ExtStruct *EModeIDTable;
506 XGI_Ext2Struct *RefIndex;
507 /* XGINew_CRT1TableStruct *CRT1Table; */
508 XGI_CRT1TableStruct *XGINEWUB_CRT1Table;
509 XGI_VCLKDataStruct *VCLKData;
510 XGI_VBVCLKDataStruct *VBVCLKData;
511 XGI_StResInfoStruct *StResInfo;
512 XGI_ModeResInfoStruct *ModeResInfo;
513 XGI_XG21CRT1Struct *UpdateCRT1;
514}; /* _VB_DEVICE_INFO */
515
516
517typedef struct
518{
519 USHORT Horizontal_ACTIVE;
520 USHORT Horizontal_FP;
521 USHORT Horizontal_SYNC;
522 USHORT Horizontal_BP;
523 USHORT Vertical_ACTIVE;
524 USHORT Vertical_FP;
525 USHORT Vertical_SYNC;
526 USHORT Vertical_BP;
527 double DCLK;
528 UCHAR FrameRate;
529 UCHAR Interlace;
530 USHORT Margin;
531} TimingInfo;
532
533#define _VB_STRUCT_
534#endif /* _VB_STRUCT_ */
diff --git a/drivers/staging/xgifb/vb_table.h b/drivers/staging/xgifb/vb_table.h
new file mode 100644
index 000000000000..781caefc56b1
--- /dev/null
+++ b/drivers/staging/xgifb/vb_table.h
@@ -0,0 +1,4406 @@
1#define Tap4
2
3
4XGI_MCLKDataStruct XGI330New_MCLKData[]=
5{
6 { 0x5c,0x23,0x01,166},
7 { 0x5c,0x23,0x01,166},
8 { 0x7C,0x08,0x80,200},
9 { 0x79,0x06,0x80,250},
10 { 0x29,0x01,0x81,300},
11 { 0x29,0x01,0x81,300},
12 { 0x29,0x01,0x81,300},
13 { 0x29,0x01,0x81,300}
14};
15//yilin modify for xgi20
16XGI_MCLKDataStruct XGI340New_MCLKData[]=
17{
18 { 0x16,0x01,0x01,166},
19 { 0x19,0x02,0x01,124},
20 { 0x7C,0x08,0x01,200},
21 { 0x79,0x06,0x01,250},
22 { 0x29,0x01,0x81,301},
23 { 0x5c,0x23,0x01,166},
24 { 0x5c,0x23,0x01,166},
25 { 0x5c,0x23,0x01,166}
26};
27
28XGI_MCLKDataStruct XGI27New_MCLKData[]=
29{
30 { 0x5c,0x23,0x01,166},
31 { 0x19,0x02,0x01,124},
32 { 0x7C,0x08,0x80,200},
33 { 0x79,0x06,0x80,250},
34 { 0x29,0x01,0x81,300},
35 { 0x5c,0x23,0x01,166},
36 { 0x5c,0x23,0x01,166},
37 { 0x5c,0x23,0x01,166}
38};
39
40XGI_ECLKDataStruct XGI330_ECLKData[]=
41{
42 { 0x7c,0x08,0x01,200},
43 { 0x7c,0x08,0x01,200},
44 { 0x7C,0x08,0x80,200},
45 { 0x79,0x06,0x80,250},
46 { 0x29,0x01,0x81,300},
47 { 0x29,0x01,0x81,300},
48 { 0x29,0x01,0x81,300},
49 { 0x29,0x01,0x81,300}
50};
51//yilin modify for xgi20
52XGI_ECLKDataStruct XGI340_ECLKData[]=
53{
54 { 0x5c,0x23,0x01,166},
55 { 0x55,0x84,0x01,123},
56 { 0x7C,0x08,0x01,200},
57 { 0x79,0x06,0x01,250},
58 { 0x29,0x01,0x81,301},
59 { 0x5c,0x23,0x01,166},
60 { 0x5c,0x23,0x01,166},
61 { 0x5c,0x23,0x01,166}
62};
63
64
65
66UCHAR XGI340_SR13[4][8]={
67{0x35,0x45,0xb1,0x00,0x00,0x00,0x00,0x00},/* SR13 */
68{0x41,0x51,0x5c,0x00,0x00,0x00,0x00,0x00},/* SR14 */
69{0x31,0x42,0x42,0x00,0x00,0x00,0x00,0x00},/* SR18 */
70{0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00}/* SR1B */
71};
72
73UCHAR XGI340_cr41[24][8]=
74{{0x20,0x50,0x60,0x00,0x00,0x00,0x00,0x00},/* 0 CR41 */
75{0xc4,0x40,0x84,0x00,0x00,0x00,0x00,0x00},/* 1 CR8A */
76{0xc4,0x40,0x84,0x00,0x00,0x00,0x00,0x00},/* 2 CR8B */
77{0xb5,0xa4,0xa4,0x00,0x00,0x00,0x00,0x00},
78{0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0x00},
79{0x90,0x90,0x24,0x00,0x00,0x00,0x00,0x00},/* 5 CR68 */
80{0x77,0x77,0x44,0x00,0x00,0x00,0x00,0x00},/* 6 CR69 */
81{0x77,0x77,0x44,0x00,0x00,0x00,0x00,0x00},/* 7 CR6A */
82{0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00},/* 8 CR6D */
83{0x55,0x55,0x55,0x00,0x00,0x00,0x00,0x00},/* 9 CR80 */
84{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/* 10 CR81 */
85{0x88,0xa8,0x48,0x00,0x00,0x00,0x00,0x00},/* 11 CR82 */
86{0x44,0x44,0x77,0x00,0x00,0x00,0x00,0x00},/* 12 CR85 */
87{0x48,0x48,0x88,0x00,0x00,0x00,0x00,0x00},/* 13 CR86 */
88{0x54,0x54,0x44,0x00,0x00,0x00,0x00,0x00},/* 14 CR90 */
89{0x54,0x54,0x44,0x00,0x00,0x00,0x00,0x00},/* 15 CR91 */
90{0x0a,0x0a,0x07,0x00,0x00,0x00,0x00,0x00},/* 16 CR92 */
91{0x44,0x44,0x44,0x00,0x00,0x00,0x00,0x00},/* 17 CR93 */
92{0x10,0x10,0x0A,0x00,0x00,0x00,0x00,0x00},/* 18 CR94 */
93{0x11,0x11,0x0a,0x00,0x00,0x00,0x00,0x00},/* 19 CR95 */
94{0x05,0x05,0x05,0x00,0x00,0x00,0x00,0x00},/* 20 CR96 */
95{0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0x00},/* 21 CRC3 */
96{0x05,0x00,0x02,0x00,0x00,0x00,0x00,0x00},/* 22 CRC4 */
97{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}/* 23 CRC5 */
98};
99
100
101UCHAR XGI27_cr41[24][8]=
102{
103{0x20,0x40,0x60,0x00,0x00,0x00,0x00,0x00},/* 0 CR41 */
104{0xC4,0x40,0x84,0x00,0x00,0x00,0x00,0x00},/* 1 CR8A */
105{0xC4,0x40,0x84,0x00,0x00,0x00,0x00,0x00},/* 2 CR8B */
106{0xB5,0x13,0xa4,0x00,0x00,0x00,0x00,0x00},/* 3 CR40[7],CR99[2:0],CR45[3:0]*/
107{0xf0,0xf5,0xf0,0x00,0x00,0x00,0x00,0x00},/* 4 CR59 */
108{0x90,0x90,0x24,0x00,0x00,0x00,0x00,0x00},/* 5 CR68 */
109{0x77,0x67,0x44,0x00,0x00,0x00,0x00,0x00},/* 6 CR69 */
110{0x77,0x77,0x44,0x00,0x00,0x00,0x00,0x00},/* 7 CR6A */
111{0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00},/* 8 CR6D */
112{0x55,0x55,0x55,0x00,0x00,0x00,0x00,0x00},/* 9 CR80 */
113{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/* 10 CR81 */
114{0x88,0xcc,0x48,0x00,0x00,0x00,0x00,0x00},/* 11 CR82 */
115{0x44,0x88,0x77,0x00,0x00,0x00,0x00,0x00},/* 12 CR85 */
116{0x48,0x88,0x88,0x00,0x00,0x00,0x00,0x00},/* 13 CR86 */
117{0x54,0x32,0x44,0x00,0x00,0x00,0x00,0x00},/* 14 CR90 */
118{0x54,0x33,0x44,0x00,0x00,0x00,0x00,0x00},/* 15 CR91 */
119{0x0a,0x07,0x07,0x00,0x00,0x00,0x00,0x00},/* 16 CR92 */
120{0x44,0x63,0x44,0x00,0x00,0x00,0x00,0x00},/* 17 CR93 */
121{0x10,0x14,0x0A,0x00,0x00,0x00,0x00,0x00},/* 18 CR94 */
122{0x11,0x0B,0x0C,0x00,0x00,0x00,0x00,0x00},/* 19 CR95 */
123{0x05,0x22,0x05,0x00,0x00,0x00,0x00,0x00},/* 20 CR96 */
124{0xf0,0xf0,0x00,0x00,0x00,0x00,0x00,0x00},/* 21 CRC3 */
125{0x05,0x00,0x02,0x00,0x00,0x00,0x00,0x00},/* 22 CRC4 */
126{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}/* 23 CRC5 */
127};
128
129
130#if 0
131UCHAR XGI27_cr41[24][8]=
132{
133{0x20,0x60,0x60,0x00,0x00,0x00,0x00,0x00},/* 0 CR41 */
134{0x04,0x44,0x84,0x00,0x00,0x00,0x00,0x00},/* 1 CR8A */
135{0x04,0x40,0x84,0x00,0x00,0x00,0x00,0x00},/* 2 CR8B */
136{0xb5,0x03,0xa4,0x00,0x00,0x00,0x00,0x00},/* 3 CR40[7],CR99[2:0],CR45[3:0]*/
137{0xf0,0xf5,0xf0,0x00,0x00,0x00,0x00,0x00},/* 4 CR59 */
138{0xa4,0x1C,0x24,0x00,0x00,0x00,0x00,0x00},/* 5 CR68 */
139{0x77,0x77,0x44,0x00,0x00,0x00,0x00,0x00},/* 6 CR69 */
140{0x77,0x77,0x44,0x00,0x00,0x00,0x00,0x00},/* 7 CR6A */
141{0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00},/* 8 CR6D */
142{0x55,0x55,0x55,0x00,0x00,0x00,0x00,0x00},/* 9 CR80 */
143{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/* 10 CR81 */
144{0x48,0xa8,0x48,0x00,0x00,0x00,0x00,0x00},/* 11 CR82 */
145{0x77,0x88,0x77,0x00,0x00,0x00,0x00,0x00},/* 12 CR85 */
146{0x88,0x88,0x88,0x00,0x00,0x00,0x00,0x00},/* 13 CR86 */
147{0x44,0x32,0x44,0x00,0x00,0x00,0x00,0x00},/* 14 CR90 */
148{0x44,0x33,0x44,0x00,0x00,0x00,0x00,0x00},/* 15 CR91 */
149{0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00},/* 16 CR92 */
150{0x44,0x63,0x44,0x00,0x00,0x00,0x00,0x00},/* 17 CR93 */
151{0x0A,0x14,0x0A,0x00,0x00,0x00,0x00,0x00},/* 18 CR94 */
152{0x0C,0x0B,0x0C,0x00,0x00,0x00,0x00,0x00},/* 19 CR95 */
153{0x05,0x22,0x05,0x00,0x00,0x00,0x00,0x00},/* 20 CR96 */
154{0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0x00},/* 21 CRC3 */
155{0x03,0x00,0x02,0x00,0x00,0x00,0x00,0x00},/* 22 CRC4 */
156{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}/* 23 CRC5 */
157};
158#endif
159UCHAR XGI340_CR6B[8][4]={
160{0xaa,0xaa,0xaa,0xaa},
161{0xaa,0xaa,0xaa,0xaa},
162{0xaa,0xaa,0xaa,0xaa},
163{0x00,0x00,0x00,0x00},
164{0x00,0x00,0x00,0x00},
165{0x00,0x00,0x00,0x00},
166{0x00,0x00,0x00,0x00},
167{0x00,0x00,0x00,0x00}
168};
169
170UCHAR XGI340_CR6E[8][4]={
171{0x00,0x00,0x00,0x00},
172{0x00,0x00,0x00,0x00},
173{0x00,0x00,0x00,0x00},
174{0x00,0x00,0x00,0x00},
175{0x00,0x00,0x00,0x00},
176{0x00,0x00,0x00,0x00},
177{0x00,0x00,0x00,0x00},
178{0x00,0x00,0x00,0x00}
179};
180
181UCHAR XGI340_CR6F[8][32]={
182{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
183{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
184{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
185{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
186{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
187{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
188{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
189{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
190};
191
192UCHAR XGI340_CR89[8][2]={
193{0x00,0x00},
194{0x00,0x00},
195{0x00,0x00},
196{0x00,0x00},
197{0x00,0x00},
198{0x00,0x00},
199{0x00,0x00},
200{0x00,0x00}
201};
202 /* CR47,CR48,CR49,CR4A,CR4B,CR4C,CR70,CR71,CR74,CR75,CR76,CR77 */
203UCHAR XGI340_AGPReg[12]={0x28,0x23,0x00,0x20,0x00,0x20,0x00,0x05,0xd0,0x10,0x10,0x00};
204
205UCHAR XGI340_SR16[4]={0x03,0x83,0x03,0x83};
206
207UCHAR XGI330_SR15_1[8][8]={
208{0x0,0x0,0x00,0x00,0x20,0x20,0x00,0x00},
209{0x5,0x15,0x15,0x15,0x15,0x15,0x00,0x00},
210{0xba,0xba,0xba,0xba,0xBA,0xBA,0x00,0x00},
211{0x55,0x57,0x57,0xAB,0xAB,0xAB,0x00,0x00},
212{0x60,0x34,0x34,0x34,0x34,0x34,0x00,0x00},
213{0x0,0x80,0x80,0x80,0x83,0x83,0x00,0x00},
214{0x50,0x50,0x50,0x3C,0x3C,0x3C,0x00,0x00},
215{0x0,0xa5,0xfb,0xf6,0xF6,0xF6,0x00,0x00}
216};
217
218UCHAR XGI330_cr40_1[15][8]={
219{0x66,0x40,0x40,0x28,0x24,0x24,0x00,0x00},
220{0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
221{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
222{0x00,0x00,0x00,0x00,0x0F,0x0F,0x00,0x00},
223{0x00,0xf0,0xf0,0xf0,0xF0,0xF0,0x00,0x00},
224{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
225{0x10,0x10,0x10,0x10,0x20,0x20,0x00,0x00},
226{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
227{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
228{0x88,0x88,0x88,0xAA,0xAC,0xAC,0x00,0x00},
229{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
230{0x00,0x00,0x00,0x00,0x77,0x77,0x00,0x00},
231{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
232{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
233{0x00,0xA2,0x00,0x00,0xA2,0xA2,0x00,0x00},
234};
235
236UCHAR XGI330_sr25[]={0x00,0x0};
237UCHAR XGI330_sr31=0xc0;
238UCHAR XGI330_sr32=0x11;
239UCHAR XGI330_SR33=0x00;
240UCHAR XG40_CRCF=0x13;
241UCHAR XG40_DRAMTypeDefinition=0xFF ;
242
243XGI_StStruct XGI330_SModeIDTable[]=
244{
245 {0x01,0x9208,0x01,0x00,0x10,0x00,0x00,0x01,0x00},
246 {0x01,0x1210,0x14,0x01,0x00,0x01,0x00,0x01,0x00},
247 {0x01,0x1010,0x17,0x02,0x11,0x00,0x00,0x01,0x01},
248 {0x03,0x8208,0x03,0x00,0x14,0x00,0x00,0x01,0x02},
249 {0x03,0x0210,0x16,0x01,0x04,0x01,0x00,0x01,0x02},
250 {0x03,0x0010,0x18,0x02,0x15,0x00,0x00,0x01,0x03},
251 {0x05,0x9209,0x05,0x00,0x10,0x00,0x00,0x00,0x04},
252 {0x06,0x8209,0x06,0x00,0x14,0x00,0x00,0x00,0x05},
253 {0x07,0x0000,0x07,0x03,0x05,0x03,0x00,0x01,0x03},
254 {0x07,0x0000,0x19,0x02,0x15,0x02,0x00,0x01,0x03},
255 {0x0d,0x920a,0x0d,0x00,0x10,0x00,0x00,0x00,0x04},
256 {0x0e,0x820a,0x0e,0x00,0x14,0x00,0x00,0x00,0x05},
257 {0x0f,0x0202,0x11,0x01,0x04,0x01,0x00,0x00,0x05},
258 {0x10,0x0212,0x12,0x01,0x04,0x01,0x00,0x00,0x05},
259 {0x11,0x0212,0x1a,0x04,0x24,0x04,0x00,0x00,0x05},
260 {0x12,0x0212,0x1b,0x04,0x24,0x04,0x00,0x00,0x05},
261 {0x13,0x021b,0x1c,0x00,0x14,0x00,0x00,0x00,0x04},
262 {0x12,0x0010,0x18,0x02,0x24,0x02,0x00,0x00,0x05},/* St_CRT2CRTC2 not sure */
263 {0x12,0x0210,0x18,0x01,0x24,0x01,0x00,0x00,0x05},/* St_CRT2CRTC2 not sure */
264 {0xff,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
265};
266
267
268XGI_ExtStruct XGI330_EModeIDTable[]=
269{
270 {0x6a,0x2212,0x0407,0x3a81,0x0102,0x08,0x07,0x00,0x00,0x07,0x0e},
271 {0x2e,0x0a1b,0x0306,0x3a57,0x0101,0x08,0x06,0x00,0x00,0x05,0x06},
272 {0x2f,0x0a1b,0x0305,0x3a50,0x0100,0x08,0x05,0x00,0x00,0x05,0x05},
273 {0x30,0x2a1b,0x0407,0x3a81,0x0103,0x08,0x07,0x00,0x00,0x07,0x0e},
274 {0x31,0x0a1b,0x030d,0x3b85,0x0000,0x08,0x0d,0x00,0x00,0x06,0x3d},
275 {0x32,0x0a1b,0x0a0e,0x3b8c,0x0000,0x08,0x0e,0x00,0x00,0x06,0x3e},
276 {0x33,0x0a1d,0x0a0d,0x3b85,0x0000,0x08,0x0d,0x00,0x00,0x06,0x3d},
277 {0x34,0x2a1d,0x0a0e,0x3b8c,0x0000,0x08,0x0e,0x00,0x00,0x06,0x3e},
278 {0x35,0x0a1f,0x0a0d,0x3b85,0x0000,0x08,0x0d,0x00,0x00,0x06,0x3d},
279 {0x36,0x2a1f,0x0a0e,0x3b8c,0x0000,0x08,0x0e,0x00,0x00,0x06,0x3e},
280 {0x37,0x0212,0x0508,0x3aab,0x0104,0x08,0x08,0x00,0x00,0x00,0x16},
281 {0x38,0x0a1b,0x0508,0x3aab,0x0105,0x08,0x08,0x00,0x00,0x00,0x16},
282 {0x3a,0x0e3b,0x0609,0x3adc,0x0107,0x08,0x09,0x00,0x00,0x00,0x1e},
283 {0x3c,0x0e3b,0x070a,0x3af2,0x0130,0x08,0x0a,0x00,0x00,0x00,0x22}, /* mode 1600x1200 add CRT2MODE [2003/10/07] */
284 {0x3d,0x0e7d,0x070a,0x3af2,0x0131,0x08,0x0a,0x00,0x00,0x00,0x22}, /* mode 1600x1200 add CRT2MODE */
285 {0x40,0x9a1c,0x0000,0x3a34,0x010d,0x08,0x00,0x00,0x00,0x04,0x00},
286 {0x41,0x9a1d,0x0000,0x3a34,0x010e,0x08,0x00,0x00,0x00,0x04,0x00}, /* ModeIdIndex = 0x10 */
287 {0x43,0x0a1c,0x0306,0x3a57,0x0110,0x08,0x06,0x00,0x00,0x05,0x06},
288 {0x44,0x0a1d,0x0306,0x3a57,0x0111,0x08,0x06,0x00,0x00,0x05,0x06},
289 {0x46,0x2a1c,0x0407,0x3a81,0x0113,0x08,0x07,0x00,0x00,0x07,0x0e},
290 {0x47,0x2a1d,0x0407,0x3a81,0x0114,0x08,0x07,0x00,0x00,0x07,0x0e},
291 {0x49,0x0a3c,0x0508,0x3aab,0x0116,0x08,0x08,0x00,0x00,0x00,0x16},
292 {0x4a,0x0a3d,0x0508,0x3aab,0x0117,0x08,0x08,0x00,0x00,0x00,0x16},
293 {0x4c,0x0e7c,0x0609,0x3adc,0x0119,0x08,0x09,0x00,0x00,0x00,0x1e},
294 {0x4d,0x0e7d,0x0609,0x3adc,0x011a,0x08,0x09,0x00,0x00,0x00,0x1e},
295 {0x50,0x9a1b,0x0001,0x3a3b,0x0132,0x08,0x01,0x00,0x00,0x04,0x02},
296 {0x51,0xba1b,0x0103,0x3a42,0x0133,0x08,0x03,0x00,0x00,0x07,0x03},
297 {0x52,0x9a1b,0x0204,0x3a49,0x0134,0x08,0x04,0x00,0x00,0x00,0x04},
298 {0x56,0x9a1d,0x0001,0x3a3b,0x0135,0x08,0x01,0x00,0x00,0x04,0x02},
299 {0x57,0xba1d,0x0103,0x3a42,0x0136,0x08,0x03,0x00,0x00,0x07,0x03},
300 {0x58,0x9a1d,0x0204,0x3a49,0x0137,0x08,0x04,0x00,0x00,0x00,0x04},
301 {0x59,0x9a1b,0x0000,0x3a34,0x0138,0x08,0x00,0x00,0x00,0x04,0x00},
302 {0x5A,0x021b,0x0014,0x3b83,0x0138,0x08,0x01,0x00,0x00,0x04,0x3f}, /* ModeIdIndex = 0x20 */
303 {0x5B,0x0a1d,0x0014,0x3b83,0x0135,0x08,0x01,0x00,0x00,0x04,0x3f},
304 {0x5d,0x0a1d,0x0305,0x3a50,0x0139,0x08,0x05,0x00,0x00,0x07,0x05},
305 {0x62,0x0a3f,0x0306,0x3a57,0x013a,0x08,0x06,0x00,0x00,0x05,0x06},
306 {0x63,0x2a3f,0x0407,0x3a81,0x013b,0x08,0x07,0x00,0x00,0x07,0x0e},
307 {0x64,0x0a7f,0x0508,0x3aab,0x013c,0x08,0x08,0x00,0x00,0x00,0x16},
308 {0x65,0x0eff,0x0609,0x3adc,0x013d,0x08,0x09,0x00,0x00,0x00,0x1e},
309 {0x66,0x0eff,0x070a,0x3af2,0x013e,0x08,0x0a,0x00,0x00,0x00,0x22}, /* mode 1600x1200 add CRT2MODE */
310 {0x68,0x067b,0x080b,0x3b17,0x013f,0x08,0x0b,0x00,0x00,0x00,0x29},
311 {0x69,0x06fd,0x080b,0x3b17,0x0140,0x08,0x0b,0x00,0x00,0x00,0x29},
312 {0x6b,0x07ff,0x080b,0x3b17,0x0141,0x10,0x0b,0x00,0x00,0x00,0x29},
313 {0x6c,0x067b,0x090c,0x3b37,0x0000,0x08,0x0c,0x00,0x00,0x00,0x2f},
314 {0x6d,0x06fd,0x090c,0x3b37,0x0000,0x10,0x0c,0x00,0x00,0x00,0x2f},
315 {0x6e,0x07ff,0x090c,0x3b37,0x0000,0x10,0x0c,0x00,0x00,0x00,0x2f},
316 {0x70,0x2a1b,0x0410,0x3b52,0x0000,0x08,0x10,0x00,0x00,0x07,0x34},
317 {0x71,0x0a1b,0x0511,0x3b63,0x0000,0x08,0x11,0x00,0x00,0x00,0x37},
318 {0x74,0x0a1d,0x0511,0x3b63,0x0000,0x08,0x11,0x00,0x00,0x00,0x37}, /* ModeIdIndex = 0x30 */
319 {0x75,0x0a3d,0x0612,0x3b74,0x0000,0x08,0x12,0x00,0x00,0x00,0x3a},
320 {0x76,0x2a1f,0x0410,0x3b52,0x0000,0x08,0x10,0x00,0x00,0x07,0x34},
321 {0x77,0x0a1f,0x0511,0x3b63,0x0000,0x08,0x11,0x00,0x00,0x00,0x37},
322 {0x78,0x0a3f,0x0612,0x3b74,0x0000,0x08,0x12,0x00,0x00,0x00,0x3a},
323 {0x79,0x0a3b,0x0612,0x3b74,0x0000,0x08,0x12,0x00,0x00,0x00,0x3a},
324 {0x7a,0x2a1d,0x0410,0x3b52,0x0000,0x08,0x10,0x00,0x00,0x07,0x34},
325 {0x7b,0x0e3b,0x060f,0x3ad0,0x0000,0x08,0x0f,0x00,0x00,0x00,0x1d},
326 {0x7c,0x0e7d,0x060f,0x3ad0,0x0000,0x08,0x0f,0x00,0x00,0x00,0x1d},
327 {0x7d,0x0eff,0x060f,0x3ad0,0x0000,0x08,0x0f,0x00,0x00,0x00,0x1d},
328 {0x20,0x0e3b,0x0D16,0x49e0,0x0000,0x08,0x16,0x00,0x00,0x00,0x43},
329 {0x21,0x0e7d,0x0D16,0x49e0,0x0000,0x08,0x16,0x00,0x00,0x00,0x43},
330 {0x22,0x0eff,0x0D16,0x49e0,0x0000,0x08,0x16,0x00,0x00,0x00,0x43},
331 {0x23,0x0e3b,0x0614,0x49d5,0x0000,0x08,0x14,0x00,0x00,0x00,0x41},
332 {0x24,0x0e7d,0x0614,0x49d5,0x0000,0x08,0x14,0x00,0x00,0x00,0x41},
333 {0x25,0x0eff,0x0614,0x49d5,0x0000,0x08,0x14,0x00,0x00,0x00,0x41},
334 {0x26,0x063b,0x0c15,0x49dc,0x0000,0x08,0x15,0x00,0x00,0x00,0x42}, /* ModeIdIndex = 0x40 */
335 {0x27,0x067d,0x0c15,0x49dc,0x0000,0x08,0x15,0x00,0x00,0x00,0x42},
336 {0x28,0x06ff,0x0c15,0x49dc,0x0000,0x08,0x15,0x00,0x00,0x00,0x42},
337 {0xff,0x0000,0x0000,0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00}
338};
339
340XGI_StandTableStruct XGI330_StandTable[]=
341{
342/* MD_0_200 */
343 {
344 0x28,0x18,0x08,0x0800,
345 {0x09,0x03,0x00,0x02},
346 0x63,
347 {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
348 0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00,
349 0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3,
350 0xff},
351 {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
352 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
353 0x08,0x00,0x0f,0x00},
354 {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
355 0xff}
356 },
357/* MD_1_200 */
358 {
359 0x28,0x18,0x08,0x0800,
360 {0x09,0x03,0x00,0x02},
361 0x63,
362 {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
363 0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00,
364 0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3,
365 0xff},
366 {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
367 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
368 0x08,0x00,0x0f,0x00},
369 {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
370 0xff}
371 },
372/* MD_2_200 */
373 {
374 0x50,0x18,0x08,0x1000,
375 {0x01,0x03,0x00,0x02},
376 0x63,
377 {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
378 0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00,
379 0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,
380 0xff},
381 {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
382 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
383 0x08,0x00,0x0f,0x00},
384 {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
385 0xff}
386 },
387/* MD_3_200 */
388 {
389 0x50,0x18,0x08,0x1000,
390 {0x01,0x03,0x00,0x02},
391 0x63,
392 {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
393 0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00,
394 0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,
395 0xff},
396 {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
397 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
398 0x08,0x00,0x0f,0x00},
399 {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
400 0xff}
401 },
402/* MD_4 */
403 {
404 0x28,0x18,0x08,0x4000,
405 {0x09,0x03,0x00,0x02},
406 0x63,
407 {0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,
408 0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,
409 0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xa2,
410 0xff},
411 {0x00,0x13,0x15,0x17,0x02,0x04,0x06,0x07,
412 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
413 0x01,0x00,0x03,0x00},
414 {0x00,0x00,0x00,0x00,0x00,0x30,0x0f,0x00,
415 0xff}
416 },
417/* MD_5 */
418 {
419 0x28,0x18,0x08,0x4000,
420 {0x09,0x03,0x00,0x02},
421 0x63,
422 {0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,
423 0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,
424 0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xa2,
425 0xff},
426 {0x00,0x13,0x15,0x17,0x02,0x04,0x06,0x07,
427 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
428 0x01,0x00,0x03,0x00},
429 {0x00,0x00,0x00,0x00,0x00,0x30,0x0f,0x00,
430 0xff}
431 },
432/* MD_6 */
433 {
434 0x50,0x18,0x08,0x4000,
435 {0x01,0x01,0x00,0x06},
436 0x63,
437 {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
438 0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,
439 0x9c,0x8e,0x8f,0x28,0x00,0x96,0xb9,0xc2,
440 0xff},
441 {0x00,0x17,0x17,0x17,0x17,0x17,0x17,0x17,
442 0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,
443 0x01,0x00,0x01,0x00},
444 {0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x00,
445 0xff}
446 },
447/* MD_7 */
448 {
449 0x50,0x18,0x0e,0x1000,
450 {0x00,0x03,0x00,0x03},
451 0xa6,
452 {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
453 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
454 0x83,0x85,0x5d,0x28,0x0d,0x63,0xba,0xa3,
455 0xff},
456 {0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
457 0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
458 0x0e,0x00,0x0f,0x08},
459 {0x00,0x00,0x00,0x00,0x00,0x10,0x0a,0x00,
460 0xff}
461 },
462/* MDA_DAC */
463 {
464 0x00,0x00,0x00,0x0000,
465 {0x00,0x00,0x00,0x15},
466 0x15,
467 {0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
468 0x15,0x15,0x15,0x15,0x15,0x15,0x3f,0x3f,
469 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x00,0x00,
470 0x00},
471 {0x00,0x00,0x00,0x00,0x00,0x15,0x15,0x15,
472 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
473 0x15,0x15,0x15,0x15},
474 {0x15,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
475 0x3f}
476 },
477/* CGA_DAC */
478 {
479 0x00,0x10,0x04,0x0114,
480 {0x11,0x09,0x15,0x00},
481 0x10,
482 {0x04,0x14,0x01,0x11,0x09,0x15,0x2a,0x3a,
483 0x2e,0x3e,0x2b,0x3b,0x2f,0x3f,0x2a,0x3a,
484 0x2e,0x3e,0x2b,0x3b,0x2f,0x3f,0x00,0x10,
485 0x04},
486 {0x14,0x01,0x11,0x09,0x15,0x00,0x10,0x04,
487 0x14,0x01,0x11,0x09,0x15,0x2a,0x3a,0x2e,
488 0x3e,0x2b,0x3b,0x2f},
489 {0x3f,0x2a,0x3a,0x2e,0x3e,0x2b,0x3b,0x2f,
490 0x3f}
491 },
492/* EGA_DAC */
493 {
494 0x00,0x10,0x04,0x0114,
495 {0x11,0x05,0x15,0x20},
496 0x30,
497 {0x24,0x34,0x21,0x31,0x25,0x35,0x08,0x18,
498 0x0c,0x1c,0x09,0x19,0x0d,0x1d,0x28,0x38,
499 0x2c,0x3c,0x29,0x39,0x2d,0x3d,0x02,0x12,
500 0x06},
501 {0x16,0x03,0x13,0x07,0x17,0x22,0x32,0x26,
502 0x36,0x23,0x33,0x27,0x37,0x0a,0x1a,0x0e,
503 0x1e,0x0b,0x1b,0x0f},
504 {0x1f,0x2a,0x3a,0x2e,0x3e,0x2b,0x3b,0x2f,
505 0x3f}
506 },
507/* VGA_DAC */
508 {
509 0x00,0x10,0x04,0x0114,
510 {0x11,0x09,0x15,0x2a},
511 0x3a,
512 {0x2e,0x3e,0x2b,0x3b,0x2f,0x3f,0x00,0x05,
513 0x08,0x0b,0x0e,0x11,0x14,0x18,0x1c,0x20,
514 0x24,0x28,0x2d,0x32,0x38,0x3f,0x00,0x10,
515 0x1f},
516 {0x2f,0x3f,0x1f,0x27,0x2f,0x37,0x3f,0x2d,
517 0x31,0x36,0x3a,0x3f,0x00,0x07,0x0e,0x15,
518 0x1c,0x0e,0x11,0x15},
519 {0x18,0x1c,0x14,0x16,0x18,0x1a,0x1c,0x00,
520 0x04}
521 },
522 {
523 0x08,0x0c,0x10,0x0a08,
524 {0x0c,0x0e,0x10,0x0b},
525 0x0c,
526 {0x0d,0x0f,0x10,0x10,0x01,0x08,0x00,0x00,
527 0x00,0x00,0x01,0x00,0x02,0x02,0x01,0x00,
528 0x04,0x04,0x01,0x00,0x05,0x02,0x05,0x00,
529 0x06},
530 {0x01,0x06,0x05,0x06,0x00,0x08,0x01,0x08,
531 0x00,0x07,0x02,0x07,0x06,0x07,0x00,0x00,
532 0x00,0x00,0x00,0x00},
533 {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
534 0x00}
535 },
536/* MD_D */
537 {
538 0x28,0x18,0x08,0x2000,
539 {0x09,0x0f,0x00,0x06},
540 0x63,
541 {0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,
542 0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
543 0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xe3,
544 0xff},
545 {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
546 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
547 0x01,0x00,0x0f,0x00},
548 {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
549 0xff}
550 },
551/* MD_E */
552 {
553 0x50,0x18,0x08,0x4000,
554 {0x01,0x0f,0x00,0x06},
555 0x63,
556 {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
557 0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
558 0x9c,0x8e,0x8f,0x28,0x00,0x96,0xb9,0xe3,
559 0xff},
560 {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
561 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
562 0x01,0x00,0x0f,0x00},
563 {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
564 0xff}
565 },
566/* ExtVGATable */
567 {
568 0x00,0x00,0x00,0x0000,
569 {0x01,0x0f,0x00,0x0e},
570 0x23,
571 {0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,
572 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
573 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3,
574 0xff},
575 {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
576 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
577 0x01,0x00,0x00,0x00},
578 {0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f,
579 0xff}
580 },
581/* ROM_SAVEPTR */
582 {
583 0x9f,0x3b,0x00,0x00c0,
584 {0x00,0x00,0x00,0x00},
585 0x00,
586 {0x00,0x00,0x00,0x00,0x00,0x00,0xbb,0x3f,
587 0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
588 0x00,0x00,0x1a,0x00,0xac,0x3e,0x00,0xc0,
589 0x00},
590 {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
591 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
592 0x00,0x00,0x00,0x00},
593 {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
594 0x00}
595 },
596/* MD_F */
597 {
598 0x50,0x18,0x0e,0x8000,
599 {0x01,0x0f,0x00,0x06},
600 0xa2,
601 {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
602 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
603 0x82,0x84,0x5d,0x28,0x0f,0x63,0xba,0xe3,
604 0xff},
605 {0x00,0x08,0x00,0x00,0x18,0x18,0x00,0x00,
606 0x00,0x08,0x00,0x00,0x00,0x18,0x00,0x00,
607 0x0b,0x00,0x05,0x00},
608 {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x05,
609 0xff}
610 },
611/* MD_10 */
612 {
613 0x50,0x18,0x0e,0x8000,
614 {0x01,0x0f,0x00,0x06},
615 0xa3,
616 {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
617 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
618 0x82,0x84,0x5d,0x28,0x0f,0x63,0xba,0xe3,
619 0xff},
620 {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
621 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
622 0x01,0x00,0x0f,0x00},
623 {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
624 0xff}
625 },
626/* MD_0_350 */
627 {
628 0x28,0x18,0x0e,0x0800,
629 {0x09,0x03,0x00,0x02},
630 0xa3,
631 {0x2d,0x27,0x28,0x90,0x2b,0xb1,0xbf,0x1f,
632 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
633 0x83,0x85,0x5d,0x14,0x1f,0x63,0xba,0xa3,
634 0xff},
635 {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
636 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
637 0x08,0x00,0x0f,0x00},
638 {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
639 0xff}
640 },
641/* MD_1_350 */
642 {
643 0x28,0x18,0x0e,0x0800,
644 {0x09,0x03,0x00,0x02},
645 0xa3,
646 {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
647 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
648 0x83,0x85,0x5d,0x14,0x1f,0x63,0xba,0xa3,
649 0xff},
650 {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
651 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
652 0x08,0x00,0x0f,0x00},
653 {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
654 0xff}
655 },
656/* MD_2_350 */
657 {
658 0x50,0x18,0x0e,0x1000,
659 {0x01,0x03,0x00,0x02},
660 0xa3,
661 {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
662 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
663 0x83,0x85,0x5d,0x28,0x1f,0x63,0xba,0xa3,
664 0xff},
665 {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
666 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
667 0x08,0x00,0x0f,0x00},
668 {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
669 0xff}
670 },
671/* MD_3_350 */
672 {
673 0x50,0x18,0x0e,0x1000,
674 {0x01,0x03,0x00,0x02},
675 0xa3,
676 {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
677 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
678 0x83,0x85,0x5d,0x28,0x1f,0x63,0xba,0xa3,
679 0xff},
680 {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
681 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
682 0x08,0x00,0x0f,0x00},
683 {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
684 0xff}
685 },
686/* MD_0_1_400 */
687 {
688 0x28,0x18,0x10,0x0800,
689 {0x08,0x03,0x00,0x02},
690 0x67,
691 {0x2d,0x27,0x28,0x90,0x2b,0xb1,0xbf,0x1f,
692 0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,
693 0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3,
694 0xff},
695 {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
696 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
697 0x0c,0x00,0x0f,0x08},
698 {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
699 0xff}
700 },
701/* MD_2_3_400 */
702 {
703 0x50,0x18,0x10,0x1000,
704 {0x00,0x03,0x00,0x02},
705 0x67,
706 {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
707 0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,
708 0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,
709 0xff},
710 {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
711 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
712 0x0c,0x00,0x0f,0x08},
713 {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
714 0xff}
715 },
716/* MD_7_400 */
717 {
718 0x50,0x18,0x10,0x1000,
719 {0x00,0x03,0x00,0x02},
720 0x66,
721 {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
722 0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,
723 0x9c,0x8e,0x8f,0x28,0x0f,0x96,0xb9,0xa3,
724 0xff},
725 {0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
726 0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
727 0x0e,0x00,0x0f,0x08},
728 {0x00,0x00,0x00,0x00,0x00,0x10,0x0a,0x00,
729 0xff}
730 },
731/* MD_11 */
732 {
733 0x50,0x1d,0x10,0xa000,
734 {0x01,0x0f,0x00,0x06},
735 0xe3,
736 {0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e,
737 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
738 0xe9,0x8b,0xdf,0x28,0x00,0xe7,0x04,0xc3,
739 0xff},
740 {0x00,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
741 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
742 0x01,0x00,0x0f,0x00},
743 {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x01,
744 0xff}
745 },
746/* ExtEGATable */
747 {
748 0x50,0x1d,0x10,0xa000,
749 {0x01,0x0f,0x00,0x06},
750 0xe3,
751 {0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e,
752 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
753 0xe9,0x8b,0xdf,0x28,0x00,0xe7,0x04,0xe3,
754 0xff},
755 {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
756 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
757 0x01,0x00,0x0f,0x00},
758 {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
759 0xff}
760 },
761/* MD_13 */
762 {
763 0x28,0x18,0x08,0x2000,
764 {0x01,0x0f,0x00,0x0e},
765 0x63,
766 {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
767 0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,
768 0x9c,0x8e,0x8f,0x28,0x40,0x96,0xb9,0xa3,
769 0xff},
770 {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
771 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
772 0x41,0x00,0x0f,0x00},
773 {0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f,
774 0xff}
775 }
776};
777
778XGI_TimingHStruct XGI_TimingH[]=
779{{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}};
780
781XGI_TimingVStruct XGI_TimingV[]=
782{{{0x00,0x00,0x00,0x00,0x00,0x00,0x00}}};
783
784XGI_XG21CRT1Struct XGI_UpdateCRT1Table[]=
785{
786 {0x01,0x27,0x91,0x8f,0xc0}, /* 00 */
787 {0x03,0x4f,0x83,0x8f,0xc0}, /* 01 */
788 {0x05,0x27,0x91,0x8f,0xc0}, /* 02 */
789 {0x06,0x4f,0x83,0x8f,0xc0}, /* 03 */
790 {0x07,0x4f,0x83,0x8f,0xc0}, /* 04 */
791 {0x0d,0x27,0x91,0x8f,0xc0}, /* 05 */
792 {0x0e,0x4f,0x83,0x8f,0xc0}, /* 06 */
793 {0x0f,0x4f,0x83,0x5d,0xc0}, /* 07 */
794 {0x10,0x4f,0x83,0x5d,0xc0}, /* 08 */
795 {0x11,0x4f,0x83,0xdf,0x0c}, /* 09 */
796 {0x12,0x4f,0x83,0xdf,0x0c}, /* 10 */
797 {0x13,0x4f,0x83,0x8f,0xc0}, /* 11 */
798 {0x2e,0x4f,0x83,0xdf,0x0c}, /* 12 */
799 {0x2e,0x4f,0x87,0xdf,0xc0}, /* 13 */
800 {0x2f,0x4f,0x83,0x8f,0xc0}, /* 14 */
801 {0x50,0x27,0x91,0xdf,0x0c}, /* 15 */
802 {0x59,0x27,0x91,0x8f,0xc0} /* 16 */
803};
804
805XGI_CRT1TableStruct XGI_CRT1Table[]=
806{
807 {{0x2d,0x28,0x90,0x2c,0x90,0x00,0x04,0x00,
808 0xbf,0x1f,0x9c,0x8e,0x96,0xb9,0x30}}, /* 0x0 */
809 {{0x2d,0x28,0x90,0x2c,0x90,0x00,0x04,0x00,
810 0x0b,0x3e,0xe9,0x8b,0xe7,0x04,0x00}}, /* 0x1 */
811 {{0x3D,0x31,0x81,0x37,0x1F,0x00,0x05,0x00,
812 0x72,0xF0,0x58,0x8C,0x57,0x73,0xA0}}, /* 0x2 */
813 {{0x4F,0x3F,0x93,0x45,0x0D,0x00,0x01,0x00,
814 0x24,0xF5,0x02,0x88,0xFF,0x25,0x90}}, /* 0x3 */
815 {{0x5F,0x50,0x82,0x55,0x81,0x00,0x05,0x00,
816 0xBF,0x1F,0x9C,0x8E,0x96,0xB9,0x30}}, /* 0x4 */
817 {{0x5F,0x50,0x82,0x55,0x81,0x00,0x05,0x00,
818 0x0B,0x3E,0xE9,0x8B,0xE7,0x04,0x00}}, /* 0x5 */
819 {{0x63,0x50,0x86,0x56,0x9B,0x00,0x01,0x00,
820 0x06,0x3E,0xE8,0x8B,0xE7,0xFF,0x10}}, /* 0x6 */
821 {{0x64,0x4F,0x88,0x55,0x9D,0x00,0x01,0x00,
822 0xF2,0x1F,0xE0,0x83,0xDF,0xF3,0x10}}, /* 0x7 */
823 {{0x63,0x4F,0x87,0x5A,0x81,0x00,0x05,0x00,
824 0xFB,0x1F,0xE0,0x83,0xDF,0xFC,0x10}}, /* 0x8 */
825 {{0x65,0x4F,0x89,0x58,0x80,0x00,0x05,0x60,
826 0xFB,0x1F,0xE0,0x83,0xDF,0xFC,0x80}}, /* 0x9 */
827 {{0x65,0x4F,0x89,0x58,0x80,0x00,0x05,0x60,
828 0x01,0x3E,0xE0,0x83,0xDF,0x02,0x80}}, /* 0xa */
829 {{0x67,0x4F,0x8B,0x58,0x81,0x00,0x05,0x60,
830 0x0D,0x3E,0xE0,0x83,0xDF,0x0E,0x90}}, /* 0xb */
831 {{0x65,0x4F,0x89,0x57,0x9F,0x00,0x01,0x00,
832 0xFB,0x1F,0xE6,0x8A,0xDF,0xFC,0x10}}, /* 0xc */
833 {{0x7B,0x63,0x9F,0x6A,0x93,0x00,0x05,0x00, /* ; 0D (800x600,56Hz) */
834 0x6F,0xF0,0x58,0x8A,0x57,0x70,0xA0}}, /* ; (VCLK 36.0MHz) */
835 {{0x7F,0x63,0x83,0x6C,0x1C,0x00,0x06,0x00, /* ; 0E (800x600,60Hz) */
836 0x72,0xF0,0x58,0x8C,0x57,0x73,0xA0}}, /* ; (VCLK 40.0MHz) */
837 {{0x7D,0x63,0x81,0x6E,0x1D,0x00,0x06,0x00, /* ; 0F (800x600,72Hz) */
838 0x98,0xF0,0x7C,0x82,0x57,0x99,0x80}}, /* ; (VCLK 50.0MHz) */
839 {{0x7F,0x63,0x83,0x69,0x13,0x00,0x06,0x00, /* ; 10 (800x600,75Hz) */
840 0x6F,0xF0,0x58,0x8B,0x57,0x70,0xA0}}, /* ; (VCLK 49.5MHz) */
841 {{0x7E,0x63,0x82,0x6B,0x13,0x00,0x06,0x00, /* ; 11 (800x600,85Hz) */
842 0x75,0xF0,0x58,0x8B,0x57,0x76,0xA0}}, /* ; (VCLK 56.25MHz) */
843 {{0x81,0x63,0x85,0x6D,0x18,0x00,0x06,0x60, /* ; 12 (800x600,100Hz) */
844 0x7A,0xF0,0x58,0x8B,0x57,0x7B,0xA0}}, /* ; (VCLK 75.8MHz) */
845 {{0x83,0x63,0x87,0x6E,0x19,0x00,0x06,0x60, /* ; 13 (800x600,120Hz) */
846 0x81,0xF0,0x58,0x8B,0x57,0x82,0xA0}}, /* ; (VCLK 79.411MHz) */
847 {{0x85,0x63,0x89,0x6F,0x1A,0x00,0x06,0x60, /* ; 14 (800x600,160Hz) */
848 0x91,0xF0,0x58,0x8B,0x57,0x92,0xA0}}, /* ; (VCLK 105.822MHz) */
849 {{0x99,0x7F,0x9D,0x84,0x1A,0x00,0x02,0x00,
850 0x96,0x1F,0x7F,0x83,0x7F,0x97,0x10}}, /* 0x15 */
851 {{0xA3,0x7F,0x87,0x86,0x97,0x00,0x02,0x00,
852 0x24,0xF5,0x02,0x88,0xFF,0x25,0x90}}, /* 0x16 */
853 {{0xA1,0x7F,0x85,0x86,0x97,0x00,0x02,0x00,
854 0x24,0xF5,0x02,0x88,0xFF,0x25,0x90}}, /* 0x17 */
855 {{0x9F,0x7F,0x83,0x85,0x91,0x00,0x02,0x00,
856 0x1E,0xF5,0x00,0x83,0xFF,0x1F,0x90}}, /* 0x18 */
857 {{0xA7,0x7F,0x8B,0x89,0x95,0x00,0x02,0x00,
858 0x26,0xF5,0x00,0x83,0xFF,0x27,0x90}}, /* 0x19 */
859 {{0xA9,0x7F,0x8D,0x8C,0x9A,0x00,0x02,0x62,
860 0x2C,0xF5,0x00,0x83,0xFF,0x2D,0x14}}, /* 0x1a */
861 {{0xAB,0x7F,0x8F,0x8D,0x9B,0x00,0x02,0x62,
862 0x35,0xF5,0x00,0x83,0xFF,0x36,0x14}}, /* 0x1b */
863 {{0xCF,0x9F,0x93,0xB2,0x01,0x00,0x03,0x00,
864 0x14,0xBA,0x00,0x83,0xFF,0x15,0x00}}, /* 0x1c */
865 {{0xCE,0x9F,0x92,0xA9,0x17,0x00,0x07,0x00,
866 0x28,0x5A,0x00,0x83,0xFF,0x29,0x89}}, /* 0x1d */
867 {{0xCE,0x9F,0x92,0xA5,0x17,0x00,0x07,0x00,
868 0x28,0x5A,0x00,0x83,0xFF,0x29,0x89}}, /* 0x1e */
869 {{0xD3,0x9F,0x97,0xAB,0x1F,0x00,0x07,0x00,
870 0x2E,0x5A,0x00,0x83,0xFF,0x2F,0x89}}, /* 0x1f */
871 {{0x09,0xC7,0x8D,0xD3,0x0B,0x01,0x04,0x00,
872 0xE0,0x10,0xB0,0x83,0xAF,0xE1,0x2F}}, /* 0x20 */
873 {{0x09,0xC7,0x8D,0xD3,0x0B,0x01,0x04,0x00,
874 0xE0,0x10,0xB0,0x83,0xAF,0xE1,0x2F}}, /* 0x21 */
875 {{0x09,0xC7,0x8D,0xD3,0x0B,0x01,0x04,0x00,
876 0xE0,0x10,0xB0,0x83,0xAF,0xE1,0x2F}}, /* 0x22 */
877 {{0x09,0xC7,0x8D,0xD3,0x0B,0x01,0x04,0x00,
878 0xE0,0x10,0xB0,0x83,0xAF,0xE1,0x2F}}, /* 0x23 */
879 {{0x09,0xC7,0x8D,0xD3,0x0B,0x01,0x04,0x00,
880 0xE0,0x10,0xB0,0x83,0xAF,0xE1,0x2F}}, /* 0x24 */
881 {{0x09,0xC7,0x8D,0xD3,0x0B,0x01,0x04,0x00,
882 0xE0,0x10,0xB0,0x83,0xAF,0xE1,0x2F}}, /* 0x25 */
883 {{0x09,0xC7,0x8D,0xD3,0x0B,0x01,0x04,0x00,
884 0xE0,0x10,0xB0,0x83,0xAF,0xE1,0x2F}}, /* 0x26 */
885 {{0x40,0xEF,0x84,0x03,0x1D,0x41,0x01,0x00,
886 0xDA,0x1F,0xA0,0x83,0x9F,0xDB,0x1F}}, /* 0x27 */
887 {{0x43,0xEF,0x87,0x06,0x00,0x41,0x05,0x62,
888 0xD4,0x1F,0xA0,0x83,0x9F,0xD5,0x9F}}, /* 0x28 */
889 {{0x45,0xEF,0x89,0x07,0x01,0x41,0x05,0x62,
890 0xD9,0x1F,0xA0,0x83,0x9F,0xDA,0x9F}}, /* 0x29 */
891 {{0x40,0xEF,0x84,0x03,0x1D,0x41,0x01,0x00,
892 0xDA,0x1F,0xA0,0x83,0x9F,0xDB,0x1F}}, /* 0x2a */
893 {{0x40,0xEF,0x84,0x03,0x1D,0x41,0x01,0x00,
894 0xDA,0x1F,0xA0,0x83,0x9F,0xDB,0x1F}}, /* 0x2b */
895 {{0x40,0xEF,0x84,0x03,0x1D,0x41,0x01,0x00,
896 0xDA,0x1F,0xA0,0x83,0x9F,0xDB,0x1F}}, /* 0x2c */
897 {{0x59,0xFF,0x9D,0x17,0x13,0x41,0x05,0x44,
898 0x33,0xBA,0x00,0x83,0xFF,0x34,0x0F}}, /* 0x2d */
899 {{0x5B,0xFF,0x9F,0x18,0x14,0x41,0x05,0x44,
900 0x38,0xBA,0x00,0x83,0xFF,0x39,0x0F}}, /* 0x2e */
901 {{0x5B,0xFF,0x9F,0x18,0x14,0x41,0x05,0x44,
902 0x3D,0xBA,0x00,0x83,0xFF,0x3E,0x0F}}, /* 0x2f */
903 {{0x5D,0xFF,0x81,0x19,0x95,0x41,0x05,0x44,
904 0x41,0xBA,0x00,0x84,0xFF,0x42,0x0F}}, /* 0x30 */
905 {{0x55,0xFF,0x99,0x0D,0x0C,0x41,0x05,0x00,
906 0x3E,0xBA,0x00,0x84,0xFF,0x3F,0x0F}}, /* 0x31 */
907 {{0x7F,0x63,0x83,0x6C,0x1C,0x00,0x06,0x00,
908 0x72,0xBA,0x27,0x8B,0xDF,0x73,0x80}}, /* 0x32 */
909 {{0x7F,0x63,0x83,0x69,0x13,0x00,0x06,0x00,
910 0x6F,0xBA,0x26,0x89,0xDF,0x6F,0x80}}, /* 0x33 */
911 {{0x7F,0x63,0x82,0x6B,0x13,0x00,0x06,0x00,
912 0x75,0xBA,0x29,0x8C,0xDF,0x75,0x80}}, /* 0x34 */
913 {{0xA3,0x7F,0x87,0x86,0x97,0x00,0x02,0x00,
914 0x24,0xF1,0xAF,0x85,0x3F,0x25,0xB0}}, /* 0x35 */
915 {{0x9F,0x7F,0x83,0x85,0x91,0x00,0x02,0x00,
916 0x1E,0xF1,0xAD,0x81,0x3F,0x1F,0xB0}}, /* 0x36 */
917 {{0xA7,0x7F,0x88,0x89,0x15,0x00,0x02,0x00,
918 0x26,0xF1,0xB1,0x85,0x3F,0x27,0xB0}}, /* 0x37 */
919 {{0xCE,0x9F,0x92,0xA9,0x17,0x00,0x07,0x00,
920 0x28,0xC4,0x7A,0x8E,0xCF,0x29,0xA1}}, /* 0x38 */
921 {{0xCE,0x9F,0x92,0xA5,0x17,0x00,0x07,0x00,
922 0x28,0xD4,0x7A,0x8E,0xCF,0x29,0xA1}}, /* 0x39 */
923 {{0xD3,0x9F,0x97,0xAB,0x1F,0x00,0x07,0x00,
924 0x2E,0xD4,0x7D,0x81,0xCF,0x2F,0xA1}}, /* 0x3a */
925 {{0xDC,0x9F,0x00,0xAB,0x19,0x00,0x07,0x00,
926 0xE6,0xEF,0xC0,0xC3,0xBF,0xE7,0x90}}, /* 0x3b */
927 {{0x6B,0x59,0x8F,0x5E,0x8C,0x00,0x05,0x00,
928 0x0B,0x3E,0xE9,0x8B,0xE7,0x04,0x00}}, /* 0x3c */
929 {{0x7B,0x63,0x9F,0x6A,0x93,0x00,0x05,0x00,
930 0x6F,0xF0,0x58,0x8A,0x57,0x70,0xA0}}, /* 0x3d */
931 {{0x86,0x6A,0x8a,0x74,0x06,0x00,0x02,0x00,
932 0x8c,0x15,0x4f,0x83,0xef,0x8d,0x30}}, /* 0x3e */
933 {{0x81,0x6A,0x85,0x70,0x00,0x00,0x02,0x00,
934 0x0f,0x3e,0xeb,0x8e,0xdf,0x10,0x00}}, /* 0x3f */
935 {{0xCE,0x9F,0x92,0xA9,0x17,0x00,0x07,0x00,
936 0x20,0xF5,0x03,0x88,0xFF,0x21,0x90}}, /* 0x40 */
937 {{0xE6,0xAE,0x8A,0xBD,0x90,0x00,0x03,0x00,
938 0x3D,0x10,0x1A,0x8D,0x19,0x3E,0x2F}}, /* 0x41 */
939 {{0xB9,0x8F,0x9D,0x9B,0x8A,0x00,0x06,0x00,
940 0x7D,0xFF,0x60,0x83,0x5F,0x7E,0x90}}, /* 0x42 */
941 {{0xC3,0x8F,0x87,0x9B,0x0B,0x00,0x07,0x00,
942 0x82,0xFF,0x60,0x83,0x5F,0x83,0x90}}, /* 0x43 */
943 {{0xAD,0x7F,0x91,0x8E,0x9C,0x00,0x02,0x82,
944 0x49,0xF5,0x00,0x83,0xFF,0x4A,0x90}}, /* 0x44 */
945 {{0xCD,0x9F,0x91,0xA7,0x19,0x00,0x07,0x60,
946 0xE6,0xFF,0xC0,0x83,0xBF,0xE7,0x90}}, /* 0x45 */
947 {{0xD3,0x9F,0x97,0xAB,0x1F,0x00,0x07,0x60,
948 0xF1,0xFF,0xC0,0x83,0xBF,0xF2,0x90}}, /* 0x46 */
949 {{0xD7,0x9F,0x9B,0xAC,0x1E,0x00,0x07,0x00,
950 0x03,0xDE,0xC0,0x84,0xBF,0x04,0x90}} /* 0x47 */
951};
952
953XGI330_CHTVRegDataStruct XGI_CHTVRegUNTSC[] = {
954 /* Index:000h,001h,002h,004h,003h,005h,006h,007h,008h,015h,01Fh,00Ch,00Dh,00Eh,00Fh,010h */
955 {{ 0x4A,0x77,0xBB,0x94,0x84,0x48,0xFE,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 00 (640x200,640x400) */
956 {{ 0x4A,0x77,0xBB,0x94,0x84,0x48,0xFE,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 01 (640x350) */
957 {{ 0x4A,0x77,0xBB,0x94,0x84,0x48,0xFE,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 02 (720x400) */
958 {{ 0x4A,0x77,0xBB,0x94,0x84,0x48,0xFE,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 03 (720x350) */
959 {{ 0x6A,0x77,0xBB,0x6E,0x84,0x2E,0x02,0x5A,0x04,0x00,0x80,0x20,0x7E,0x80,0x97,0x00 }},/* 04 (640x480) ;;5/6/02 */
960 {{ 0xCF,0x77,0xB7,0xC8,0x84,0x3B,0x02,0x5A,0x04,0x00,0x80,0x19,0x88,0xAE,0xA3,0x00 }},/* 05 (800x600) ;;1/12/02 */
961 {{ 0xEE,0x77,0xBB,0x66,0x87,0x32,0x01,0x5A,0x04,0x00,0x80,0x1B,0xD4,0x2F,0x6F,0x00 }}/* 06 (1024x768) ;;5/6/02 */
962 };
963
964XGI330_CHTVRegDataStruct XGI_CHTVRegONTSC[]= {
965 /* Index:000h,001h,002h,004h,003h,005h,006h,007h,008h,015h,01Fh,00Ch,00Dh,00Eh,00Fh,010h */
966 {{ 0x49,0x77,0xBB,0x7B,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 00 (640x200,640x400) */
967 {{ 0x49,0x77,0xBB,0x7B,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 01 (640x350) */
968 {{ 0x49,0x77,0xBB,0x7B,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 02 (720x400) */
969 {{ 0x49,0x77,0xBB,0x7B,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 03 (720x350) */
970 {{ 0x69,0x77,0xBB,0x6E,0x84,0x1E,0x00,0x5A,0x04,0x00,0x80,0x25,0x1A,0x80,0x26,0x00 }},/* 04 (640x480) ;;5/6/02 */
971 {{ 0xCE,0x77,0xB7,0xB6,0x83,0x2C,0x02,0x5A,0x04,0x00,0x80,0x1C,0x00,0x82,0x97,0x00 }},/* 05 (800x600) ;;5/6/02 */
972 {{ 0xED,0x77,0xBB,0x66,0x8C,0x21,0x02,0x5A,0x04,0x00,0x80,0x1F,0xA0,0x7E,0x73,0x00 }}/* 06 (1024x768) ;;5/6/02 */
973 };
974
975XGI330_CHTVRegDataStruct XGI_CHTVRegUPAL[]= {
976 /* Index:000h,001h,002h,004h,003h,005h,006h,007h,008h,015h,01Fh,00Ch,00Dh,00Eh,00Fh,010h */
977 {{ 0x41,0x7F,0xB7,0x34,0xAD,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* ; 00 (640x200,640x400) */
978 {{ 0x41,0x7F,0xB7,0x80,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* ; 01 (640x350) */
979 {{ 0x41,0x7F,0xB7,0x34,0xAD,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* ; 02 (720x400) */
980 {{ 0x41,0x7F,0xB7,0x12,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* ; 03 (720x350) */
981 {{ 0x61,0x7F,0xB7,0x99,0x84,0x35,0x04,0x5A,0x05,0x00,0x80,0x26,0x2A,0x55,0x5D,0x00 }},/* ; 04 (640x480) */
982 {{ 0xC3,0x7F,0xB7,0x7A,0x84,0x40,0x02,0x5A,0x05,0x00,0x80,0x1F,0x84,0x3D,0x28,0x00 }},/* ; 05 (800x600) ;;1/12/02 */
983 {{ 0xE5,0x7F,0xB7,0x1D,0xA7,0x3E,0x04,0x5A,0x05,0x00,0x80,0x20,0x3E,0xE4,0x22,0x00 }}/* ; 06 (1024x768) ;;1/12/02 */
984 };
985
986XGI330_CHTVRegDataStruct XGI_CHTVRegOPAL[]={
987 /* Index:000,0x01,0x02,0x04,0x03,0x05,0x06,0x07,0x08,0x15,0x1F,0x0C,0x0D,0x0E,0x0F,0x10h */
988 {{ 0x41,0x7F,0xB7,0x36,0xAD,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 00 (640x200,640x400) */
989 {{ 0x41,0x7F,0xB7,0x86,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 01 (640x350) */
990 {{ 0x41,0x7F,0xB7,0x36,0xAD,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 02 (720x400) */
991 {{ 0x41,0x7F,0xB7,0x86,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 03 (720x350) */
992 {{ 0x61,0x7F,0xB7,0x99,0x84,0x35,0x04,0x5A,0x05,0x00,0x80,0x26,0x2A,0x55,0x5D,0x00 }},/* 04 (640x480) */
993 {{ 0xC1,0x7F,0xB7,0x4D,0x8C,0x1E,0x31,0x5A,0x05,0x00,0x80,0x26,0x78,0x19,0x34,0x00 }},/* 05 (800x600) ;;1/12/02 */
994 {{ 0xE4,0x7F,0xB7,0x1E,0xAF,0x29,0x37,0x5A,0x05,0x00,0x80,0x25,0x8C,0xB2,0x2A,0x00 }}/* 06 (1024x768) ;;1/12/02 */
995 };
996
997UCHAR XGI_CH7017LV1024x768[]={0x60,0x02,0x00,0x07,0x40,0xED,0xA3,
998 0xC8,0xC7,0xAC,0xE0,0x02};
999UCHAR XGI_CH7017LV1400x1050[]={0x60,0x03,0x11,0x00,0x40,0xE3,0xAD,
1000 0xDB,0xF6,0xAC,0xE0,0x02};
1001
1002
1003/*add for new UNIVGABIOS*/
1004XGI330_LCDDataStruct XGI_StLCD1024x768Data[]=
1005{
1006 { 62, 25, 800, 546,1344, 806},
1007 { 32, 15, 930, 546,1344, 806},
1008 { 62, 25, 800, 546,1344, 806}, /* chiawen for dot9 -> dot8 */
1009 { 104, 45, 945, 496,1344, 806},
1010 { 62, 25, 800, 546,1344, 806},
1011 { 31, 18,1008, 624,1344, 806},
1012 { 1, 1,1344, 806,1344, 806}
1013};
1014
1015XGI330_LCDDataStruct XGI_ExtLCD1024x768Data[]=
1016{
1017 { 42, 25,1536, 419,1344, 806}, /* { 12, 5, 896, 512,1344, 806}, // alan 09/12/2003 */
1018 { 48, 25,1536, 369,1344, 806}, /* { 12, 5, 896, 510,1344, 806}, // alan 09/12/2003 */
1019 { 42, 25,1536, 419,1344, 806}, /* { 32, 15,1008, 505,1344, 806}, // alan 09/12/2003 */
1020 { 48, 25,1536, 369,1344, 806}, /* { 32, 15,1008, 514,1344, 806}, // alan 09/12/2003 */
1021 { 12, 5, 896, 500,1344, 806},
1022 { 42, 25,1024, 625,1344, 806},
1023 { 1, 1,1344, 806,1344, 806},
1024 { 12, 5, 896, 500,1344, 806},
1025 { 42, 25,1024, 625,1344, 806},
1026 { 1, 1,1344, 806,1344, 806},
1027 { 12, 5, 896, 500,1344, 806},
1028 { 42, 25,1024, 625,1344, 806},
1029 { 1, 1,1344, 806,1344, 806}
1030};
1031
1032/*XGI330_LCDDataStruct XGI_St2LCD1024x768Data[]=
1033{
1034 { 62, 25, 800, 546,1344, 806},
1035 { 32, 15, 930, 546,1344, 806},
1036 { 62, 25, 800, 546,1344, 806},
1037 { 104, 45, 945, 496,1344, 806},
1038 { 62, 25, 800, 546,1344, 806},
1039 { 31, 18,1008, 624,1344, 806},
1040 { 1, 1,1344, 806,1344, 806}
1041};*/
1042
1043XGI330_LCDDataStruct XGI_CetLCD1024x768Data[]=
1044{
1045 { 1,1,1344,806,1344,806 }, /* ; 00 (320x200,320x400,640x200,640x400) */
1046 { 1,1,1344,806,1344,806 }, /* 01 (320x350,640x350) */
1047 { 1,1,1344,806,1344,806 }, /* 02 (360x400,720x400) */
1048 { 1,1,1344,806,1344,806 }, /* 03 (720x350) */
1049 { 1,1,1344,806,1344,806 }, /* 04 (640x480x60Hz) */
1050 { 1,1,1344,806,1344,806 }, /* 05 (800x600x60Hz) */
1051 { 1,1,1344,806,1344,806 } /* 06 (1024x768x60Hz) */
1052};
1053
1054XGI330_LCDDataStruct XGI_StLCD1280x1024Data[]=
1055{
1056 { 22, 5, 800, 510,1650,1088},
1057 { 22, 5, 800, 510,1650,1088},
1058 { 176, 45, 900, 510,1650,1088},
1059 { 176, 45, 900, 510,1650,1088},
1060 { 22, 5, 800, 510,1650,1088},
1061 { 13, 5,1024, 675,1560,1152},
1062 { 16, 9,1266, 804,1688,1072},
1063 { 1, 1,1688,1066,1688,1066}
1064};
1065
1066XGI330_LCDDataStruct XGI_ExtLCD1280x1024Data[]=
1067{
1068 { 211, 60,1024, 501,1688,1066},
1069 { 211, 60,1024, 508,1688,1066},
1070 { 211, 60,1024, 501,1688,1066},
1071 { 211, 60,1024, 508,1688,1066},
1072 { 211, 60,1024, 500,1688,1066},
1073 { 211, 75,1024, 625,1688,1066},
1074 { 211, 120,1280, 798,1688,1066},
1075 { 1, 1,1688,1066,1688,1066}
1076};
1077
1078XGI330_LCDDataStruct XGI_St2LCD1280x1024Data[]=
1079{
1080 { 22, 5, 800, 510,1650,1088},
1081 { 22, 5, 800, 510,1650,1088},
1082 { 176, 45, 900, 510,1650,1088},
1083 { 176, 45, 900, 510,1650,1088},
1084 { 22, 5, 800, 510,1650,1088},
1085 { 13, 5,1024, 675,1560,1152},
1086 { 16, 9,1266, 804,1688,1072},
1087 { 1, 1,1688,1066,1688,1066}
1088};
1089
1090XGI330_LCDDataStruct XGI_CetLCD1280x1024Data[]=
1091{
1092 { 1,1,1688,1066,1688,1066 }, /* 00 (320x200,320x400,640x200,640x400) */
1093 { 1,1,1688,1066,1688,1066 }, /* 01 (320x350,640x350) */
1094 { 1,1,1688,1066,1688,1066 }, /* 02 (360x400,720x400) */
1095 { 1,1,1688,1066,1688,1066 }, /* 03 (720x350) */
1096 { 1,1,1688,1066,1688,1066 }, /* 04 (640x480x60Hz) */
1097 { 1,1,1688,1066,1688,1066 }, /* 05 (800x600x60Hz) */
1098 { 1,1,1688,1066,1688,1066 }, /* 06 (1024x768x60Hz) */
1099 { 1,1,1688,1066,1688,1066 }, /* 07 (1280x1024x60Hz) */
1100 { 1,1,1688,1066,1688,1066 } /* 08 (1400x1050x60Hz) */
1101};
1102
1103XGI330_LCDDataStruct XGI_StLCD1400x1050Data[]=
1104{
1105 { 211,100,2100,408,1688,1066 }, /* 00 (320x200,320x400,640x200,640x400) */
1106 { 211,64,1536,358,1688,1066 }, /* 01 (320x350,640x350) */
1107 { 211,100,2100,408,1688,1066 }, /* 02 (360x400,720x400) */
1108 { 211,64,1536,358,1688,1066 }, /* 03 (720x350) */
1109 { 211,48,840,488,1688,1066 }, /* 04 (640x480x60Hz) */
1110 { 211,72,1008,609,1688,1066 }, /* 05 (800x600x60Hz) */
1111 { 211,128,1400,776,1688,1066 }, /* 06 (1024x768x60Hz) */
1112 { 1,1,1688,1066,1688,1066 }, /* 07 (1280x1024x60Hz w/o Scaling) */
1113 { 1,1,1688,1066,1688,1066 } /* 08 (1400x1050x60Hz) */
1114};
1115
1116XGI330_LCDDataStruct XGI_ExtLCD1400x1050Data[]=
1117{
1118 { 211,100,2100,408,1688,1066 }, /* 00 (320x200,320x400,640x200,640x400) */
1119 { 211,64,1536,358,1688,1066 }, /* 01 (320x350,640x350) */
1120 { 211,100,2100,408,1688,1066 }, /* 02 (360x400,720x400) */
1121 { 211,64,1536,358,1688,1066 }, /* 03 (720x350) */
1122 { 211,48,840,488,1688,1066 }, /* 04 (640x480x60Hz) */
1123 { 211,72,1008,609,1688,1066 }, /* 05 (800x600x60Hz) */
1124 { 211,128,1400,776,1688,1066 }, /* 06 (1024x768x60Hz) */
1125 { 1,1,1688,1066,1688,1066 }, /* 07 (1280x1024x60Hz w/o Scaling) */
1126 { 1,1,1688,1066,1688,1066 } /* 08 (1400x1050x60Hz) */
1127};
1128
1129XGI330_LCDDataStruct XGI_ExtLCD1600x1200Data[]=
1130{
1131 { 4,1,1620,420,2160,1250 }, /* { 3,1,2160,425,2160,1250 }, // 00 (320x200,320x400,640x200,640x400) // alan 10/14/2003 */
1132 { 27,7,1920,375,2160,1250 }, /* 01 (320x350,640x350) */
1133 { 4,1,1620,420,2160,1250 }, /* { 3,1,2160,425,2160,1250 }, // 02 (360x400,720x400) // alan 10/14/2003 */
1134 { 27,7,1920,375,2160,1250 }, /* 03 (720x350) */
1135 { 27,4,800,500,2160,1250 }, /* 04 (640x480x60Hz) */
1136 { 4,1,1080,625,2160,1250 }, /* 05 (800x600x60Hz) */
1137 { 5,2,1350,800,2160,1250 }, /* 06 (1024x768x60Hz) */
1138 { 27,16,1500,1064,2160,1250 }, /* 07 (1280x1024x60Hz) */
1139 { 9,7,1920,1106,2160,1250 }, /* 08 (1400x1050x60Hz) */
1140 { 1,1,2160,1250,2160,1250 } /* 09 (1600x1200x60Hz) ;302lv */
1141};
1142
1143XGI330_LCDDataStruct XGI_StLCD1600x1200Data[]=
1144{
1145 { 27,4,800,500,2160,1250 },/* 00 (320x200,320x400,640x200,640x400) */
1146 { 27,4,800,500,2160,1250 },/* 01 (320x350,640x350) */
1147 { 27,4,800,500,2160,1250 },/* 02 (360x400,720x400) */
1148 { 27,4,800,500,2160,1250 },/* 03 (720x350) */
1149 { 27,4,800,500,2160,1250 },/* 04 (320x240,640x480) */
1150 { 4,1,1080,625,2160,1250 },/* 05 (400x300,800x600) */
1151 { 5,2,1350,800,2160,1250 },/* 06 (512x384,1024x768) */
1152 { 135,88,1600,1100,2160,1250 },/* 07 (1280x1024) */
1153 { 1,1,1800,1500,2160,1250 },/* 08 (1400x1050) */
1154 { 1,1,2160,1250,2160,1250 } /* 09 (1600x1200) */
1155};
1156
1157XGI330_LCDDataStruct XGI_CetLCD1400x1050Data[]=
1158{
1159 { 1,1,1688,1066,1688,1066 }, /* 00 (320x200,320x400,640x200,640x400) */
1160 { 1,1,1688,1066,1688,1066 }, /* 01 (320x350,640x350) */
1161 { 1,1,1688,1066,1688,1066 }, /* 02 (360x400,720x400) */
1162 { 1,1,1688,1066,1688,1066 }, /* 03 (720x350) */
1163 { 1,1,1688,1066,1688,1066 }, /* 04 (640x480x60Hz) */
1164 { 1,1,1688,1066,1688,1066 }, /* 05 (800x600x60Hz) */
1165 { 1,1,1688,1066,1688,1066 }, /* 06 (1024x768x60Hz) */
1166 { 1,1,1688,1066,1688,1066 }, /* 07 (1280x1024x60Hz) */
1167 { 1,1,1688,1066,1688,1066 } /* 08 (1400x1050x60Hz) */
1168};
1169
1170XGI330_LCDDataStruct XGI_NoScalingData[]=
1171{
1172 { 1, 1, 800, 449, 800, 449},
1173 { 1, 1, 800, 449, 800, 449},
1174 { 1, 1, 900, 449, 900, 449},
1175 { 1, 1, 900, 449, 900, 449},
1176 { 1, 1, 800, 525, 800, 525},
1177 { 1, 1,1056, 628,1056, 628},
1178 { 1, 1,1344, 806,1344, 806},
1179 { 1, 1,1688,1066,1688,1066}
1180};
1181
1182XGI330_LCDDataStruct XGI_ExtLCD1024x768x75Data[]=
1183{
1184 {42,25,1536,419,1344,806 }, /* ; 00 (320x200,320x400,640x200,640x400) */
1185 {48,25,1536,369,1344,806 }, /* ; 01 (320x350,640x350) */
1186 {42,25,1536,419,1344,806 }, /* ; 02 (360x400,720x400) */
1187 {48,25,1536,369,1344,806 }, /* ; 03 (720x350) */
1188 {8,5,1312,500,1312,800 }, /* ; 04 (640x480x75Hz) */
1189 {41,25,1024,625,1312,800 }, /* ; 05 (800x600x75Hz) */
1190 {1,1,1312,800,1312,800 } /* ; 06 (1024x768x75Hz) */
1191};
1192
1193XGI330_LCDDataStruct XGI_StLCD1024x768x75Data[]=
1194{
1195 {42,25,1536,419,1344,806 }, /* ; 00 (320x200,320x400,640x200,640x400) */
1196 {48,25,1536,369,1344,806 }, /* ; 01 (320x350,640x350) */
1197 {42,25,1536,419,1344,806 }, /* ; 02 (360x400,720x400) */
1198 {48,25,1536,369,1344,806 }, /* ; 03 (720x350) */
1199 {8,5,1312,500,1312,800 }, /* ; 04 (640x480x75Hz) */
1200 {41,25,1024,625,1312,800 }, /* ; 05 (800x600x75Hz) */
1201 {1,1,1312,800,1312,800 } /* ; 06 (1024x768x75Hz) */
1202};
1203
1204XGI330_LCDDataStruct XGI_CetLCD1024x768x75Data[]=
1205{
1206 {1,1,1312,800,1312,800}, /* ; 00 (320x200,320x400,640x200,640x400) */
1207 {1,1,1312,800,1312,800}, /* ; 01 (320x350,640x350) */
1208 {1,1,1312,800,1312,800}, /* ; 02 (360x400,720x400) */
1209 {1,1,1312,800,1312,800}, /* ; 03 (720x350) */
1210 {1,1,1312,800,1312,800}, /* ; 04 (640x480x75Hz) */
1211 {1,1,1312,800,1312,800}, /* ; 05 (800x600x75Hz) */
1212 {1,1,1312,800,1312,800} /* ; 06 (1024x768x75Hz) */
1213};
1214
1215XGI330_LCDDataStruct XGI_ExtLCD1280x1024x75Data[]=
1216{
1217 {211,60,1024,501,1688,1066 }, /* ; 00 (320x200,320x400,640x200,640x400) */
1218 {211,60,1024,508,1688,1066 }, /* ; 01 (320x350,640x350) */
1219 {211,60,1024,501,1688,1066 }, /* ; 02 (360x400,720x400) */
1220 {211,60,1024,508,1688,1066 }, /* ; 03 (720x350) */
1221 {211,45,768,498,1688,1066 }, /* ; 04 (640x480x75Hz) */
1222 {211,75,1024,625,1688,1066 }, /* ; 05 (800x600x75Hz) */
1223 {211,120,1280,798,1688,1066 }, /* ; 06 (1024x768x75Hz) */
1224 {1,1,1688,1066,1688,1066 } /* ; 07 (1280x1024x75Hz) */
1225};
1226
1227XGI330_LCDDataStruct XGI_StLCD1280x1024x75Data[]=
1228{
1229 {211,60,1024,501,1688,1066 }, /* ; 00 (320x200,320x400,640x200,640x400) */
1230 {211,60,1024,508,1688,1066 }, /* ; 01 (320x350,640x350) */
1231 {211,60,1024,501,1688,1066 }, /* ; 02 (360x400,720x400) */
1232 {211,60,1024,508,1688,1066 }, /* ; 03 (720x350) */
1233 {211,45,768,498,1688,1066 }, /* ; 04 (640x480x75Hz) */
1234 {211,75,1024,625,1688,1066 }, /* ; 05 (800x600x75Hz) */
1235 {211,120,1280,798,1688,1066}, /* ; 06 (1024x768x75Hz) */
1236 {1,1,1688,1066,1688,1066 } /* ; 07 (1280x1024x75Hz) */
1237};
1238
1239XGI330_LCDDataStruct XGI_CetLCD1280x1024x75Data[]=
1240{
1241 {1,1,1688,1066,1688,1066}, /* ; 00 (320x200,320x400,640x200,640x400) */
1242 {1,1,1688,1066,1688,1066}, /* ; 01 (320x350,640x350) */
1243 {1,1,1688,1066,1688,1066}, /* ; 02 (360x400,720x400) */
1244 {1,1,1688,1066,1688,1066}, /* ; 03 (720x350) */
1245 {1,1,1688,1066,1688,1066}, /* ; 04 (640x480x75Hz) */
1246 {1,1,1688,1066,1688,1066}, /* ; 05 (800x600x75Hz) */
1247 {1,1,1688,1066,1688,1066}, /* ; 06 (1024x768x75Hz) */
1248 {1,1,1688,1066,1688,1066} /* ; 07 (1280x1024x75Hz) */
1249};
1250
1251XGI330_LCDDataStruct XGI_NoScalingDatax75[]=
1252{
1253 {1,1,800,449,800,449 }, /* ; 00 (320x200,320x400,640x200,640x400) */
1254 {1,1,800,449,800,449 }, /* ; 01 (320x350,640x350) */
1255 {1,1,900,449,900,449 }, /* ; 02 (360x400,720x400) */
1256 {1,1,900,449,900,449 }, /* ; 03 (720x350) */
1257 {1,1,840,500,840,500 }, /* ; 04 (640x480x75Hz) */
1258 {1,1,1056,625,1056,625 }, /* ; 05 (800x600x75Hz) */
1259 {1,1,1312,800,1312,800 }, /* ; 06 (1024x768x75Hz) */
1260 {1,1,1688,1066,1688,1066}, /* ; 07 (1280x1024x75Hz) */
1261 {1,1,1688,1066,1688,1066}, /* ; 08 (1400x1050x75Hz) ;;[ycchen] 12/19/02 */
1262 {1,1,2160,1250,2160,1250}, /* ; 09 (1600x1200x75Hz) */
1263 {1,1,1688,806,1688,806 } /* ; 0A (1280x768x75Hz) */
1264};
1265
1266XGI330_LCDDataDesStruct XGI_ExtLCDDes1024x768Data[]=
1267{
1268 { 9,1057,0, 771 }, /* ; 00 (320x200,320x400,640x200,640x400) */
1269 { 9,1057,0, 771 }, /* ; 01 (320x350,640x350) */
1270 { 9,1057,0, 771 }, /* ; 02 (360x400,720x400) */
1271 { 9,1057,0, 771 }, /* ; 03 (720x350) */
1272 { 9,1057,0, 771 }, /* ; 04 (640x480x60Hz) */
1273 { 9,1057,0, 771 }, /* ; 05 (800x600x60Hz) */
1274 { 9,1057,805, 770 } /* ; 06 (1024x768x60Hz) */
1275};
1276
1277XGI330_LCDDataDesStruct XGI_StLCDDes1024x768Data[]=
1278{
1279 { 9,1057,737,703 }, /* ; 00 (320x200,320x400,640x200,640x400) */
1280 { 9,1057,686,651 }, /* ; 01 (320x350,640x350) */
1281 { 9,1057,737,703 }, /* ; 02 (360x400,720x400) */
1282 { 9,1057,686,651 }, /* ; 03 (720x350) */
1283 { 9,1057,776,741 }, /* ; 04 (640x480x60Hz) */
1284 { 9,1057, 0 ,771 }, /* ; 05 (800x600x60Hz) */
1285 { 9,1057,805,770 } /* ; 06 (1024x768x60Hz) */
1286};
1287
1288XGI330_LCDDataDesStruct XGI_CetLCDDes1024x768Data[]=
1289{
1290 { 1152,856,622,587 }, /* ; 00 (320x200,320x400,640x200,640x400) */
1291 { 1152,856,597,562 }, /* ; 01 (320x350,640x350) */
1292 { 1152,856,622,587 }, /* ; 02 (360x400,720x400) */
1293 { 1152,856,597,562 }, /* ; 03 (720x350) */
1294 { 1152,856,662,627 }, /* ; 04 (640x480x60Hz) */
1295 { 1232,936,722,687 }, /* ; 05 (800x600x60Hz) */
1296 { 0,1048,805,770 } /* ; 06 (1024x768x60Hz) */
1297};
1298
1299XGI330_LCDDataDesStruct XGI_ExtLCDDLDes1280x1024Data[]=
1300{
1301 { 18,1346,981,940 },/* 00 (320x200,320x400,640x200,640x400) */
1302 { 18,1346,926,865 },/* 01 (320x350,640x350) */
1303 { 18,1346,981,940 },/* 02 (360x400,720x400) */
1304 { 18,1346,926,865 },/* 03 (720x350) */
1305 { 18,1346,0,1025 },/* 04 (640x480x60Hz) */
1306 { 18,1346,0,1025 },/* 05 (800x600x60Hz) */
1307 { 18,1346,1065,1024 },/* 06 (1024x768x60Hz) */
1308 { 18,1346,1065,1024 }/* 07 (1280x1024x60Hz) */
1309};
1310
1311XGI330_LCDDataDesStruct XGI_StLCDDLDes1280x1024Data[]=
1312{
1313 { 18,1346,970,907 },/* 00 (320x200,320x400,640x200,640x400) */
1314 { 18,1346,917,854 },/* 01 (320x350,640x350) */
1315 { 18,1346,970,907 },/* 02 (360x400,720x400) */
1316 { 18,1346,917,854 },/* 03 (720x350) */
1317 { 18,1346,0,1025 },/* 04 (640x480x60Hz) */
1318 { 18,1346,0,1025 },/* 05 (800x600x60Hz) */
1319 { 18,1346,1065,1024 },/* 06 (1024x768x60Hz) */
1320 { 18,1346,1065,1024 }/* 07 (1280x1024x60Hz) */
1321};
1322
1323XGI330_LCDDataDesStruct XGI_CetLCDDLDes1280x1024Data[]=
1324{
1325 { 1368,1008,752,711 }, /* 00 (320x200,320x400,640x200,640x400) */
1326 { 1368,1008,729,688 }, /* 01 (320x350,640x350) */
1327 { 1368,1008,752,711 }, /* 02 (360x400,720x400) */
1328 { 1368,1008,729,688 }, /* 03 (720x350) */
1329 { 1368,1008,794,753 }, /* 04 (640x480x60Hz) */
1330 { 1448,1068,854,813 }, /* 05 (800x600x60Hz) */
1331 { 1560,1200,938,897 }, /* 06 (1024x768x60Hz) */
1332 { 18,1346,1065,1024 } /* 07 (1280x1024x60Hz) */
1333};
1334
1335XGI330_LCDDataDesStruct XGI_ExtLCDDes1280x1024Data[]=
1336{
1337 { 9,1337,981,940 }, /* ; 00 (320x200,320x400,640x200,640x400) */
1338 { 9,1337,926,884 }, /* ; 01 (320x350,640x350) alan, 2003/09/30 */
1339 { 9,1337,981,940 }, /* ; 02 (360x400,720x400) */
1340 { 9,1337,926,884 }, /* ; 03 (720x350) alan, 2003/09/30 */
1341 { 9,1337,0,1025 }, /* ; 04 (640x480x60Hz) */
1342 { 9,1337,0,1025 }, /* ; 05 (800x600x60Hz) */
1343 { 9,1337,1065,1024 }, /* ; 06 (1024x768x60Hz) */
1344 { 9,1337,1065,1024 } /* ; 07 (1280x1024x60Hz) */
1345};
1346
1347XGI330_LCDDataDesStruct XGI_StLCDDes1280x1024Data[]=
1348{
1349 { 9,1337,970,907 }, /* ; 00 (320x200,320x400,640x200,640x400) */
1350 { 9,1337,917,854 }, /* ; 01 (320x350,640x350) */
1351 { 9,1337,970,907 }, /* ; 02 (360x400,720x400) */
1352 { 9,1337,917,854 }, /* ; 03 (720x350) */
1353 { 9,1337,0,1025 }, /* ; 04 (640x480x60Hz) */
1354 { 9,1337,0,1025 }, /* ; 05 (800x600x60Hz) */
1355 { 9,1337,1065,1024 }, /* ; 06 (1024x768x60Hz) */
1356 { 9,1337,1065,1024 } /* ; 07 (1280x1024x60Hz) */
1357};
1358
1359XGI330_LCDDataDesStruct XGI_CetLCDDes1280x1024Data[]=
1360{
1361 { 1368,1008,752,711 }, /* 00 (320x200,320x400,640x200,640x400) */
1362 { 1368,1008,729,688 }, /* 01 (320x350,640x350) */
1363 { 1368,1008,752,711 }, /* 02 (360x400,720x400) */
1364 { 1368,1008,729,688 }, /* 03 (720x350) */
1365 { 1368,1008,794,753 }, /* 04 (640x480x60Hz) */
1366 { 1448,1068,854,813 }, /* 05 (800x600x60Hz) */
1367 { 1560,1200,938,897 }, /* 06 (1024x768x60Hz) */
1368 { 9,1337,1065,1024 } /* 07 (1280x1024x60Hz) */
1369};
1370
1371XGI330_LCDDataDesStruct XGI_StLCDDLDes1400x1050Data[]=
1372{
1373 { 18,1464,0,1051 }, /* 00 (320x200,320x400,640x200,640x400) */
1374 { 18,1464,0,1051 }, /* 01 (320x350,640x350) */
1375 { 18,1464,0,1051 }, /* 02 (360x400,720x400) */
1376 { 18,1464,0,1051 }, /* 03 (720x350) */
1377 { 18,1464,0,1051 }, /* 04 (640x480x60Hz) */
1378 { 18,1464,0,1051 }, /* 05 (800x600x60Hz) */
1379 { 18,1464,0,1051 }, /* 06 (1024x768x60Hz) */
1380 { 1646,1406,1053,1038 }, /* 07 (1280x1024x60Hz) */
1381 { 18,1464,0,1051 } /* 08 (1400x1050x60Hz) */
1382};
1383
1384XGI330_LCDDataDesStruct XGI_ExtLCDDLDes1400x1050Data[]=
1385{
1386 { 18,1464,0,1051 }, /* 00 (320x200,320x400,640x200,640x400) */
1387 { 18,1464,0,1051 }, /* 01 (320x350,640x350) */
1388 { 18,1464,0,1051 }, /* 02 (360x400,720x400) */
1389 { 18,1464,0,1051 }, /* 03 (720x350) */
1390 { 18,1464,0,1051 }, /* 04 (640x480x60Hz) */
1391 { 18,1464,0,1051 }, /* 05 (800x600x60Hz) */
1392 { 18,1464,0,1051 }, /* 06 (1024x768x60Hz) */
1393 { 1646,1406,1053,1038 }, /* 07 (1280x1024x60Hz) */
1394 { 18,1464,0,1051 } /* 08 (1400x1050x60Hz) */
1395};
1396
1397XGI330_LCDDataDesStruct XGI_StLCDDes1400x1050Data[]=
1398{
1399 { 9,1455,0,1051 },/* 00 (320x200,320x400,640x200,640x400) */
1400 { 9,1455,0,1051 },/* 01 (320x350,640x350) */
1401 { 9,1455,0,1051 },/* 02 (360x400,720x400) */
1402 { 9,1455,0,1051 },/* 03 (720x350) */
1403 { 9,1455,0,1051 },/* 04 (640x480x60Hz) */
1404 { 9,1455,0,1051 },/* 05 (800x600x60Hz) */
1405 { 9,1455,0,1051 },/* 06 (1024x768x60Hz) */
1406 { 1637,1397,1053,1038 },/* 07 (1280x1024x60Hz) */
1407 { 9,1455,0,1051 } /* 08 (1400x1050x60Hz) */
1408};
1409
1410XGI330_LCDDataDesStruct XGI_ExtLCDDes1400x1050Data[]=
1411{
1412 { 9,1455,0,1051 },/* 00 (320x200,320x400,640x200,640x400) */
1413 { 9,1455,0,1051 },/* 01 (320x350,640x350) */
1414 { 9,1455,0,1051 },/* 02 (360x400,720x400) */
1415 { 9,1455,0,1051 },/* 03 (720x350) */
1416 { 9,1455,0,1051 },/* 04 (640x480x60Hz) */
1417 { 9,1455,0,1051 },/* 05 (800x600x60Hz) */
1418 { 9,1455,0,1051 },/* 06 (1024x768x60Hz) */
1419 { 1637,1397,1053,1038 },/* 07 (1280x1024x60Hz) */
1420 { 9,1455,0,1051 } /* 08 (1400x1050x60Hz) */
1421};
1422
1423XGI330_LCDDataDesStruct XGI_CetLCDDes1400x1050Data[]=
1424{
1425 { 1308,1068,781,766 }, /* 00 (320x200,320x400,640x200,640x400) */
1426 { 1308,1068,781,766 }, /* 01 (320x350,640x350) */
1427 { 1308,1068,781,766 }, /* 02 (360x400,720x400) */
1428 { 1308,1068,781,766 }, /* 03 (720x350) */
1429 { 1308,1068,781,766 }, /* 04 (640x480x60Hz) */
1430 { 1388,1148,841,826 }, /* 05 (800x600x60Hz) */
1431 { 1490,1250,925,910 }, /* 06 (1024x768x60Hz) */
1432 { 1646,1406,1053,1038 }, /* 07 (1280x1024x60Hz) */
1433 { 18,1464,0,1051 } /* 08 (1400x1050x60Hz) */
1434};
1435
1436XGI330_LCDDataDesStruct XGI_CetLCDDes1400x1050Data2[]=
1437{
1438 { 0,1448,0,1051 }, /* 00 (320x200,320x400,640x200,640x400) */
1439 { 0,1448,0,1051 }, /* 01 (320x350,640x350) */
1440 { 0,1448,0,1051 }, /* 02 (360x400,720x400) */
1441 { 0,1448,0,1051 }, /* 03 (720x350) */
1442 { 0,1448,0,1051 } /* 04 (640x480x60Hz) */
1443};
1444
1445
1446
1447XGI330_LCDDataDesStruct XGI_ExtLCDDLDes1600x1200Data[]=
1448{
1449 { 18,1682,0,1201 }, /* 00 (320x200,320x400,640x200,640x400) */
1450 { 18,1682,0,1201 }, /* 01 (320x350,640x350) */
1451 { 18,1682,0,1201 }, /* 02 (360x400,720x400) */
1452 { 18,1682,0,1201 }, /* 03 (720x350) */
1453 { 18,1682,0,1201 }, /* 04 (640x480x60Hz) */
1454 { 18,1682,0,1201 }, /* 05 (800x600x60Hz) */
1455 { 18,1682,0,1201 }, /* 06 (1024x768x60Hz) */
1456 { 18,1682,0,1201 }, /* 07 (1280x1024x60Hz) */
1457 { 18,1682,0,1201 }, /* 08 (1400x1050x60Hz) */
1458 { 18,1682,0,1201 } /* 09 (1600x1200x60Hz) */
1459};
1460
1461XGI330_LCDDataDesStruct XGI_StLCDDLDes1600x1200Data[]=
1462{
1463 { 18,1682,1150,1101 }, /* 00 (320x200,320x400,640x200,640x400) */
1464 { 18,1682,1083,1034 }, /* 01 (320x350,640x350) */
1465 { 18,1682,1150,1101 }, /* 02 (360x400,720x400) */
1466 { 18,1682,1083,1034 }, /* 03 (720x350) */
1467 { 18,1682,0,1201 }, /* 04 (640x480x60Hz) */
1468 { 18,1682,0,1201 }, /* 05 (800x600x60Hz) */
1469 { 18,1682,0,1201 }, /* 06 (1024x768x60Hz) */
1470 { 18,1682,1232,1183 }, /* 07 (1280x1024x60Hz) */
1471 { 18,1682,0,1201 }, /* 08 (1400x1050x60Hz) */
1472 { 18,1682,0,1201 } /* 09 (1600x1200x60Hz) */
1473};
1474
1475XGI330_LCDDataDesStruct XGI_ExtLCDDes1600x1200Data[]=
1476{
1477 { 9,1673,0,1201 },/* 00 (320x200,320x400,640x200,640x400) */
1478 { 9,1673,0,1201 },/* 01 (320x350,640x350) */
1479 { 9,1673,0,1201 },/* 02 (360x400,720x400) */
1480 { 9,1673,0,1201 },/* 03 (720x350) */
1481 { 9,1673,0,1201 },/* 04 (640x480x60Hz) */
1482 { 9,1673,0,1201 },/* 05 (800x600x60Hz) */
1483 { 9,1673,0,1201 },/* 06 (1024x768x60Hz) */
1484 { 9,1673,0,1201 },/* 07 (1280x1024x60Hz) */
1485 { 9,1673,0,1201 },/* 08 (1400x1050x60Hz) */
1486 { 9,1673,0,1201 } /* 09 (1600x1200x60Hz) */
1487};
1488
1489XGI330_LCDDataDesStruct XGI_StLCDDes1600x1200Data[]=
1490{
1491 { 9,1673,1150,1101 },/* 00 (320x200,320x400,640x200,640x400) */
1492 { 9,1673,1083,1034 },/* 01 (320x350,640x350) */
1493 { 9,1673,1150,1101 },/* 02 (360x400,720x400) */
1494 { 9,1673,1083,1034 },/* 03 (720x350) */
1495 { 9,1673,0,1201 },/* 04 (640x480x60Hz) */
1496 { 9,1673,0,1201 },/* 05 (800x600x60Hz) */
1497 { 9,1673,0,1201 },/* 06 (1024x768x60Hz) */
1498 { 9,1673,1232,1183 },/* 07 (1280x1024x60Hz) */
1499 { 9,1673,0,1201 },/* 08 (1400x1050x60Hz) */
1500 { 9,1673,0,1201 } /* 09 (1600x1200x60Hz) */
1501};
1502
1503XGI330_LCDDataDesStruct2 XGI_NoScalingDesData[]=
1504{
1505 { 9,657,448,405,96,2 }, /* 00 (320x200,320x400,640x200,640x400) */
1506 { 9,657,448,355,96,2 }, /* 01 (320x350,640x350) */
1507 { 9,657,448,405,96,2 }, /* 02 (360x400,720x400) */
1508 { 9,657,448,355,96,2 }, /* 03 (720x350) */
1509 { 9,657,1,483,96,2 }, /* 04 (640x480x60Hz) */
1510 { 9,849,627,600,128,4 }, /* 05 (800x600x60Hz) */
1511 { 9,1057,805,770,0136,6 }, /* 06 (1024x768x60Hz) */
1512 { 9,1337,0,1025,112,3 }, /* 07 (1280x1024x60Hz) */
1513 { 9,1457,0,1051,112,3 }, /* 08 (1400x1050x60Hz) }, //;[ycchen] 12/19/02 */
1514 { 9,1673,0,1201,192,3 }, /* 09 (1600x1200x60Hz) */
1515 { 9,1337,0,771,112,6 } /* 0A (1280x768x60Hz) */
1516};
1517
1518XGI330_LCDDataDesStruct XGI_ExtLCDDes1024x768x75Data[]= /* ;;1024x768x75Hz */
1519{
1520 {9,1049,0,769}, /* ; 00 (320x200,320x400,640x200,640x400) */
1521 {9,1049,0,769}, /* ; 01 (320x350,640x350) */
1522 {9,1049,0,769}, /* ; 02 (360x400,720x400) */
1523 {9,1049,0,769}, /* ; 03 (720x350) */
1524 {9,1049,0,769}, /* ; 04 (640x480x75Hz) */
1525 {9,1049,0,769}, /* ; 05 (800x600x75Hz) */
1526 {9,1049,0,769} /* ; 06 (1024x768x75Hz) */
1527};
1528
1529XGI330_LCDDataDesStruct XGI_StLCDDes1024x768x75Data[]=
1530{
1531 {9,1049,0,769}, /* ; 00 (320x200,320x400,640x200,640x400) */
1532 {9,1049,0,769}, /* ; 01 (320x350,640x350) */
1533 {9,1049,0,769}, /* ; 02 (360x400,720x400) */
1534 {9,1049,0,769}, /* ; 03 (720x350) */
1535 {9,1049,0,769}, /* ; 04 (640x480x75Hz) */
1536 {9,1049,0,769}, /* ; 05 (800x600x75Hz) */
1537 {9,1049,0,769} /* ; 06 (1024x768x75Hz) */
1538};
1539
1540XGI330_LCDDataDesStruct XGI_CetLCDDes1024x768x75Data[]= /* ;;1024x768x75Hz */
1541{
1542 {1152,856,622,587}, /* ; 00 (320x200,320x400,640x200,640x400) */
1543 {1152,856,597,562}, /* ; 01 (320x350,640x350) */
1544 {1192,896,622,587}, /* ; 02 (360x400,720x400) */
1545 {1192,896,597,562}, /* ; 03 (720x350) */
1546 {1129,857,656,625}, /* ; 04 (640x480x75Hz) */
1547 {1209,937,716,685}, /* ; 05 (800x600x75Hz) */
1548 {9,1049,0,769} /* ; 06 (1024x768x75Hz) */
1549};
1550
1551XGI330_LCDDataDesStruct XGI_ExtLCDDLDes1280x1024x75Data[]= /* ;;1280x1024x75Hz */
1552{
1553 {18,1314,0,1025 },/* ; 00 (320x200,320x400,640x200,640x400) */
1554 {18,1314,0,1025 },/* ; 01 (320x350,640x350) */
1555 {18,1314,0,1025 },/* ; 02 (360x400,720x400) */
1556 {18,1314,0,1025 },/* ; 03 (720x350) */
1557 {18,1314,0,1025 },/* ; 04 (640x480x60Hz) */
1558 {18,1314,0,1025 },/* ; 05 (800x600x60Hz) */
1559 {18,1314,0,1025 },/* ; 06 (1024x768x60Hz) */
1560 {18,1314,0,1025 }/* ; 07 (1280x1024x60Hz) */
1561};
1562
1563XGI330_LCDDataDesStruct XGI_StLCDDLDes1280x1024x75Data[]=
1564{
1565 {18,1314,0,1025 },/* ; 00 (320x200,320x400,640x200,640x400) */
1566 {18,1314,0,1025 },/* ; 01 (320x350,640x350) */
1567 {18,1314,0,1025 },/* ; 02 (360x400,720x400) */
1568 {18,1314,0,1025 },/* ; 03 (720x350) */
1569 {18,1314,0,1025 },/* ; 04 (640x480x60Hz) */
1570 {18,1314,0,1025 },/* ; 05 (800x600x60Hz) */
1571 {18,1314,0,1025 },/* ; 06 (1024x768x60Hz) */
1572 {18,1314,0,1025 }/* ; 07 (1280x1024x60Hz) */
1573};
1574
1575XGI330_LCDDataDesStruct XGI_CetLCDDLDes1280x1024x75Data[]= /* 1280x1024x75Hz */
1576{
1577 {1368,1008,752,711}, /* ; 00 (320x200,320x400,640x200,640x400) */
1578 {1368,1008,729,688}, /* ; 01 (320x350,640x350) */
1579 {1408,1048,752,711}, /* ; 02 (360x400,720x400) */
1580 {1408,1048,729,688}, /* ; 03 (720x350) */
1581 {1377,985,794,753}, /* ; 04 (640x480x75Hz) */
1582 {1457,1065,854,813}, /* ; 05 (800x600x75Hz) */
1583 {1569,1177,938,897}, /* ; 06 (1024x768x75Hz) */
1584 {18,1314,0,1025} /* ; 07 (1280x1024x75Hz) */
1585};
1586
1587XGI330_LCDDataDesStruct XGI_ExtLCDDes1280x1024x75Data[]= /* ;;1280x1024x75Hz */
1588{
1589 {9,1305,0,1025},/* ; 00 (320x200,320x400,640x200,640x400) */
1590 {9,1305,0,1025},/* ; 01 (320x350,640x350) */
1591 {9,1305,0,1025},/* ; 02 (360x400,720x400) */
1592 {9,1305,0,1025},/* ; 03 (720x350) */
1593 {9,1305,0,1025},/* ; 04 (640x480x60Hz) */
1594 {9,1305,0,1025},/* ; 05 (800x600x60Hz) */
1595 {9,1305,0,1025},/* ; 06 (1024x768x60Hz) */
1596 {9,1305,0,1025} /* ; 07 (1280x1024x60Hz) */
1597};
1598
1599XGI330_LCDDataDesStruct XGI_StLCDDes1280x1024x75Data[]=
1600{
1601 {9,1305,0,1025},/* ; 00 (320x200,320x400,640x200,640x400) */
1602 {9,1305,0,1025},/* ; 01 (320x350,640x350) */
1603 {9,1305,0,1025},/* ; 02 (360x400,720x400) */
1604 {9,1305,0,1025},/* ; 03 (720x350) */
1605 {9,1305,0,1025},/* ; 04 (640x480x60Hz) */
1606 {9,1305,0,1025},/* ; 05 (800x600x60Hz) */
1607 {9,1305,0,1025},/* ; 06 (1024x768x60Hz) */
1608 {9,1305,0,1025} /* ; 07 (1280x1024x60Hz) */
1609};
1610
1611XGI330_LCDDataDesStruct XGI_CetLCDDes1280x1024x75Data[]= /* 1280x1024x75Hz */
1612{
1613 {1368,1008,752,711}, /* ; 00 (320x200,320x400,640x200,640x400) */
1614 {1368,1008,729,688}, /* ; 01 (320x350,640x350) */
1615 {1408,1048,752,711}, /* ; 02 (360x400,720x400) */
1616 {1408,1048,729,688}, /* ; 03 (720x350) */
1617 {1377,985,794,753}, /* ; 04 (640x480x75Hz) */
1618 {1457,1065,854,813}, /* ; 05 (800x600x75Hz) */
1619 {1569,1177,938,897}, /* ; 06 (1024x768x75Hz) */
1620 {9,1305,0,1025} /* ; 07 (1280x1024x75Hz) */
1621};
1622
1623XGI330_LCDDataDesStruct2 XGI_NoScalingDesDatax75[]= /* Scaling LCD 75Hz */
1624{
1625 {9,657,448,405,96,2}, /* ; 00 (320x200,320x400,640x200,640x400) */
1626 {9,657,448,355,96,2}, /* ; 01 (320x350,640x350) */
1627 {9,738,448,405,108,2}, /* ; 02 (360x400,720x400) */
1628 {9,738,448,355,108,2}, /* ; 03 (720x350) */
1629 {9,665,0,481,64,3}, /* ; 04 (640x480x75Hz) */
1630 {9,825,0,601,80,3}, /* ; 05 (800x600x75Hz) */
1631 {9,1049,0,769,96,3}, /* ; 06 (1024x768x75Hz) */
1632 {9,1305,0,1025,144,3}, /* ; 07 (1280x1024x75Hz) */
1633 {9,1457,0,1051,112,3}, /* ; 08 (1400x1050x60Hz) ;;[ycchen] 12/19/02 */
1634 {9,1673,0,1201,192,3}, /* ; 09 (1600x1200x75Hz) */
1635 {9,1337,0,771,112,6} /* ; 0A (1280x768x60Hz) */
1636};
1637
1638XGI330_TVDataStruct XGI_StPALData[]=
1639{
1640 { 1, 1, 864, 525,1270, 400, 100, 0, 760},
1641 { 1, 1, 864, 525,1270, 350, 100, 0, 760},
1642 { 1, 1, 864, 525,1270, 400, 0, 0, 720},
1643 { 1, 1, 864, 525,1270, 350, 0, 0, 720},
1644 { 1, 1, 864, 525,1270, 480, 50, 0, 760},
1645 { 1, 1, 864, 525,1270, 600, 50, 0, 0}
1646};
1647
1648XGI330_TVDataStruct XGI_ExtPALData[]=
1649{
1650 { 2, 1,1080, 463,1270, 500, 50, 0, 50},
1651 { 15, 7,1152, 413,1270, 500, 50, 0, 50},
1652 { 2, 1,1080, 463,1270, 500, 50, 0, 50},
1653 { 15, 7,1152, 413,1270, 500, 50, 0, 50},
1654 { 2, 1, 900, 543,1270, 500, 0, 0, 50},
1655 { 4, 3,1080, 663,1270, 500, 438, 0, 438},
1656 { 1, 1,1125, 831,1270, 500, 686, 0, 686}, /*301b*/
1657 { 3, 2,1080, 619,1270, 540, 438, 0, 438}
1658};
1659
1660XGI330_TVDataStruct XGI_StNTSCData[]=
1661{
1662 { 1, 1, 858, 525,1270, 400, 50, 0, 760},
1663 { 1, 1, 858, 525,1270, 350, 50, 0, 640},
1664 { 1, 1, 858, 525,1270, 400, 0, 0, 720},
1665 { 1, 1, 858, 525,1270, 350, 0, 0, 720},
1666 { 1, 1, 858, 525,1270, 480, 0, 0, 760}
1667};
1668
1669XGI330_TVDataStruct XGI_ExtNTSCData[]=
1670{
1671 { 9, 5, 1001, 453,1270, 420, 171, 0, 171},
1672 { 12, 5, 858, 403,1270, 420, 171, 0, 171},
1673 { 9, 5, 1001, 453,1270, 420, 171, 0, 171},
1674 { 12, 5, 858, 403,1270, 420, 171, 0, 171},
1675 { 143, 80, 836, 523,1270, 420, 224, 0, 0},
1676 { 143, 120,1008, 643,1270, 420, 0, 1, 0},
1677 { 1, 1,1120, 821,1516, 420, 0, 1, 0}, /*301b*/
1678 { 2, 1, 858, 503,1584, 480, 0, 1, 0},
1679 { 3, 2,1001, 533,1270, 420, 0, 0, 0}
1680};
1681
1682XGI330_TVDataStruct XGI_St1HiTVData[]=
1683{
1684 { 1,1,892,563,690,800,0,0,0 }, /* 00 (320x200,320x400,640x200,640x400) */
1685 { 1,1,892,563,690,700,0,0,0 }, /* 01 (320x350,640x350) */
1686 { 1,1,1000,563,785,800,0,0,0 }, /* 02 (360x400,720x400) */
1687 { 1,1,1000,563,785,700,0,0,0 }, /* 03 (720x350) */
1688 { 1,1,892,563,690,960,0,0,0 }, /* 04 (320x240,640x480) */
1689 { 8,5,1050,683,1648,960,0x150,1,0 } /* 05 (400x300,800x600) */
1690};
1691
1692XGI330_TVDataStruct XGI_St2HiTVData[]=
1693{
1694 { 3,1,840,483,1648,960,0x032,0,0 }, /* 00 (320x200,320x400,640x200,640x400) */
1695 { 1,1,892,563,690,700,0,0,0 }, /* 01 (320x350,640x350) */
1696 { 3,1,840,483,1648,960,0x032,0,0 }, /* 02 (360x400,720x400) */
1697 { 1,1,1000,563,785,700,0,0,0 }, /* 03 (720x350) */
1698 { 5,2,840,563,1648,960,0x08D,1,0 }, /* 04 (320x240,640x480) */
1699 { 8,5,1050,683,1648,960,0x17C,1,0 } /* 05 (400x300,800x600) */
1700
1701};
1702
1703XGI330_TVDataStruct XGI_ExtHiTVData[]=
1704{
1705 { 6,1,840,563,1632,960,0,0,0 }, /* 00 (320x200,320x400,640x200,640x400) */
1706 { 3,1,960,563,1632,960,0,0,0 }, /* 01 (320x350,640x350) */
1707 { 3,1,840,483,1632,960,0,0,0 }, /* 02 (360x400,720x400) */
1708 { 3,1,960,563,1632,960,0,0,0 }, /* 03 (720x350) */
1709 { 5,1,840,563,1648,960,0x166,1,0 }, /* 04 (320x240,640x480) */
1710 { 16,5,1050,683,1648,960,0x143,1,0 }, /* 05 (400x300,800x600) */
1711 { 25,12,1260,851,1648,960,0x032,0,0 }, /* 06 (512x384,1024x768) */
1712 { 5,4,1575,1124,1648,960,0x128,0,0 }, /* 07 (1280x1024) */
1713 { 4,1,1050,563,1548,960,0x143,1,0 }, /* 08 (800x480) */
1714 { 5,2,1400,659,1648,960,0x032,0,0 }, /* 09 (1024x576) */
1715 { 8,5,1750,803,1648,960,0x128,0,0 } /* 0A (1280x720) */
1716
1717};
1718
1719XGI330_TVDataStruct XGI_ExtYPbPr525iData[]=
1720{
1721 { 9, 5, 1001, 453,1270, 420, 171, 0, 171},
1722 { 12, 5, 858, 403,1270, 420, 171, 0, 171},
1723 { 9, 5, 1001, 453,1270, 420, 171, 0, 171},
1724 { 12, 5, 858, 403,1270, 420, 171, 0, 171},
1725 { 143, 80, 836, 523,1250, 420, 224, 0, 0},
1726 { 143, 120,1008, 643,1250, 420, 0, 1, 0},
1727 { 1, 1,1120, 821,1516, 420, 0, 1, 0}, /*301b*/
1728 { 2, 1, 858, 503,1584, 480, 0, 1, 0},
1729 { 3, 2,1001, 533,1250, 420, 0, 0, 0}
1730};
1731
1732XGI330_TVDataStruct XGI_StYPbPr525iData[]=
1733{
1734 { 1, 1, 858, 525,1270, 400, 50, 0, 760},
1735 { 1, 1, 858, 525,1270, 350, 50, 0, 640},
1736 { 1, 1, 858, 525,1270, 400, 0, 0, 720},
1737 { 1, 1, 858, 525,1270, 350, 0, 0, 720},
1738 { 1, 1, 858, 525,1270, 480, 0, 0, 760},
1739};
1740
1741XGI330_TVDataStruct XGI_ExtYPbPr525pData[]=
1742{
1743 { 9, 5, 1001, 453,1270, 420, 171, 0, 171},
1744 { 12, 5, 858, 403,1270, 420, 171, 0, 171},
1745 { 9, 5, 1001, 453,1270, 420, 171, 0, 171},
1746 { 12, 5, 858, 403,1270, 420, 171, 0, 171},
1747 { 143, 80, 836, 523,1270, 420, 224, 0, 0},
1748 { 143, 120,1008, 643,1270, 420, 0, 1, 0},
1749 { 1, 1,1120, 821,1516, 420, 0, 1, 0}, /*301b*/
1750 { 2, 1, 858, 503,1584, 480, 0, 1, 0},
1751 { 3, 2,1001, 533,1270, 420, 0, 0, 0}
1752 };
1753
1754XGI330_TVDataStruct XGI_StYPbPr525pData[]=
1755{
1756 { 1, 1,1716, 525,1270, 400, 50, 0, 760},
1757 { 1, 1,1716, 525,1270, 350, 50, 0, 640},
1758 { 1, 1,1716, 525,1270, 400, 0, 0, 720},
1759 { 1, 1,1716, 525,1270, 350, 0, 0, 720},
1760 { 1, 1,1716, 525,1270, 480, 0, 0, 760},
1761};
1762
1763XGI330_TVDataStruct XGI_ExtYPbPr750pData[]=
1764{
1765 { 3, 1, 935, 470,1130, 680, 50, 0, 0}, /* 00 (320x200,320x400,640x200,640x400) */
1766 { 24, 7, 935, 420,1130, 680, 50, 0, 0}, /* 01 (320x350,640x350) */
1767 { 3, 1, 935, 470,1130, 680, 50, 0, 0}, /* 02 (360x400,720x400) */
1768 { 24, 7, 935, 420,1130, 680, 50, 0, 0}, /* 03 (720x350) */
1769 { 2, 1,1100, 590,1130, 640, 50, 0, 0}, /* 04 (320x240,640x480) */
1770 { 3, 2,1210, 690,1130, 660, 50, 0, 0}, /* 05 (400x300,800x600) */
1771 { 1, 1,1375, 878,1130, 640, 638, 0, 0}, /* 06 (1024x768) */
1772 { 2, 1, 858, 503,1130, 480, 0, 1, 0}, /* 07 (720x480) */
1773 { 5, 4,1815, 570,1130, 660, 50, 0, 0},
1774 { 5, 3,1100, 686,1130, 640, 50, 1, 0},
1775 { 10, 9,1320, 830,1130, 640, 50, 0, 0}
1776};
1777
1778XGI330_TVDataStruct XGI_StYPbPr750pData[]=
1779{
1780 { 1, 1,1650, 750,1280, 400, 50, 0, 760},
1781 { 1, 1,1650, 750,1280, 350, 50, 0, 640},
1782 { 1, 1,1650, 750,1280, 400, 0, 0, 720},
1783 { 1, 1,1650, 750,1280, 350, 0, 0, 720},
1784 { 1, 1,1650, 750,1280, 480, 0, 0, 760},
1785};
1786
1787UCHAR XGI330_NTSCTiming[] = {
1788 0x17,0x1d,0x03,0x09,0x05,0x06,0x0c,0x0c,
1789 0x94,0x49,0x01,0x0a,0x06,0x0d,0x04,0x0a,
1790 0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x1b,
1791 0x0c,0x50,0x00,0x97,0x00,0xda,0x4a,0x17,
1792 0x7d,0x05,0x4b,0x00,0x00,0xe2,0x00,0x02,
1793 0x03,0x0a,0x65,0x9d,0x08,0x92,0x8f,0x40,
1794 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x50,
1795 0x00,0x40,0x44,0x00,0xdb,0x02,0x3b,0x00};
1796
1797UCHAR XGI330_PALTiming[] = {
1798 0x21,0x5A,0x35,0x6e,0x04,0x38,0x3d,0x70,
1799 0x94,0x49,0x01,0x12,0x06,0x3e,0x35,0x6d,
1800 0x06,0x14,0x3e,0x35,0x6d,0x00,0x45,0x2b,
1801 0x70,0x50,0x00,0x9b,0x00,0xd9,0x5d,0x17,
1802 0x7d,0x05,0x45,0x00,0x00,0xe8,0x00,0x02,
1803 0x0d,0x00,0x68,0xb0,0x0b,0x92,0x8f,0x40,
1804 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x63,
1805 0x00,0x40,0x3e,0x00,0xe1,0x02,0x28,0x00};
1806
1807UCHAR XGI330_HiTVExtTiming[] =
1808{
1809 0x2D,0x60,0x2C,0x5F,0x08,0x31,0x3A,0x64,
1810 0x28,0x02,0x01,0x3D,0x06,0x3E,0x35,0x6D,
1811 0x06,0x14,0x3E,0x35,0x6D,0x00,0xC5,0x3F,
1812 0x64,0x90,0x33,0x8C,0x18,0x36,0x3E,0x13,
1813 0x2A,0xDE,0x2A,0x44,0x40,0x2A,0x44,0x40,
1814 0x8E,0x8E,0x82,0x07,0x0B,
1815 0x92,0x0F,0x40,0x60,0x80,0x14,0x90,0x8C,
1816 0x60,0x14,0x3D,0x63,0x4F,
1817 0x27,0x00,0xfc,0xff,0x6a,0x00
1818
1819};
1820
1821UCHAR XGI330_HiTVSt1Timing[] =
1822{
1823 0x32,0x65,0x2C,0x5F,0x08,0x31,0x3A,0x65,
1824 0x28,0x02,0x01,0x3D,0x06,0x3E,0x35,0x6D,
1825 0x06,0x14,0x3E,0x35,0x6D,0x00,0xC5,0x3F,
1826 0x65,0x90,0x7B,0xA8,0x03,0xF0,0x87,0x03,
1827 0x11,0x15,0x11,0xCF,0x10,0x11,0xCF,0x10,
1828 0x35,0x35,0x3B,0x69,0x1D,
1829 0x92,0x0F,0x40,0x60,0x80,0x14,0x90,0x8C,
1830 0x60,0x04,0x86,0xAF,0x5D,
1831 0x0E,0x00,0xfc,0xff,0x2d,0x00
1832};
1833
1834UCHAR XGI330_HiTVSt2Timing[] =
1835{
1836 0x32,0x65,0x2C,0x5F,0x08,0x31,0x3A,0x64,
1837 0x28,0x02,0x01,0x3D,0x06,0x3E,0x35,0x6D,
1838 0x06,0x14,0x3E,0x35,0x6D,0x00,0xC5,0x3F,
1839 0x64,0x90,0x33,0x8C,0x18,0x36,0x3E,0x13,
1840 0x2A,0xDE,0x2A,0x44,0x40,0x2A,0x44,0x40,
1841 0x8E,0x8E,0x82,0x07,0x0B,
1842 0x92,0x0F,0x40,0x60,0x80,0x14,0x90,0x8C,
1843 0x60,0x14,0x3D,0x63,0x4F,
1844 0x27,0x00,0xFC,0xff,0x6a,0x00
1845};
1846
1847UCHAR XGI330_HiTVTextTiming[] =
1848{
1849 0x32,0x65,0x2C,0x5F,0x08,0x31,0x3A,0x65,
1850 0x28,0x02,0x01,0x3D,0x06,0x3E,0x35,0x6D,
1851 0x06,0x14,0x3E,0x35,0x6D,0x00,0xC5,0x3F,
1852 0x65,0x90,0xE7,0xBC,0x03,0x0C,0x97,0x03,
1853 0x14,0x78,0x14,0x08,0x20,0x14,0x08,0x20,
1854 0xC8,0xC8,0x3B,0xD2,0x26,
1855 0x92,0x0F,0x40,0x60,0x80,0x14,0x90,0x8C,
1856 0x60,0x04,0x96,0x72,0x5C,
1857 0x11,0x00,0xFC,0xFF,0x32,0x00
1858};
1859
1860UCHAR XGI330_YPbPr750pTiming[] =
1861{
1862 0x30,0x1d,0xe8,0x09,0x09,0xed,0x0c,0x0c,
1863 0x98,0x0a,0x01,0x0c,0x06,0x0d,0x04,0x0a,
1864 0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
1865 0xed,0x50,0x70,0x9f,0x16,0x59,0x60,0x13,
1866 0x27,0x0b,0x27,0xfc,0x30,0x27,0x1c,0xb0,
1867 0x4b,0x4b,0x6f,0x2f,0x63,
1868 0x92,0x0F,0x40,0x60,0x80,0x14,0x90,0x8C,
1869 0x60,0x14,0x73,0x00,0x40,
1870 0x11,0x00,0xfc,0xff,0x32,0x00
1871};
1872
1873UCHAR XGI330_YPbPr525pTiming[] =
1874{
1875 0x3E,0x11,0x06,0x09,0x0b,0x0c,0x0c,0x0c,
1876 0x98,0x0a,0x01,0x0d,0x06,0x0d,0x04,0x0a,
1877 0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
1878 0x0c,0x50,0xb2,0x9f,0x16,0x59,0x4f,0x13,
1879 0xad,0x11,0xad,0x1d,0x40,0x8a,0x3d,0xb8,
1880 0x51,0x5e,0x60,0x49,0x7d,
1881 0x92,0x0F,0x40,0x60,0x80,0x14,0x90,0x8C,
1882 0x60,0x14,0x4B,0x43,0x41,
1883 0x11,0x00,0xFC,0xFF,0x32,0x00
1884};
1885
1886UCHAR XGI330_YPbPr525iTiming[] =
1887{
1888 0x1B,0x21,0x03,0x09,0x05,0x06,0x0C,0x0C,
1889 0x94,0x49,0x01,0x0A,0x06,0x0D,0x04,0x0A,
1890 0x06,0x14,0x0D,0x04,0x0A,0x00,0x85,0x1B,
1891 0x0C,0x50,0x00,0x97,0x00,0xDA,0x4A,0x17,
1892 0x7D,0x05,0x4B,0x00,0x00,0xE2,0x00,0x02,
1893 0x03,0x0A,0x65,0x9D,0x08,
1894 0x92,0x8F,0x40,0x60,0x80,0x14,0x90,0x8C,
1895 0x60,0x14,0x4B,0x00,0x40,
1896 0x44,0x00,0xDB,0x02,0x3B,0x00
1897
1898};
1899
1900UCHAR XGI330_HiTVGroup3Data[] =
1901{
1902 0x00,0x1A,0x22,0x63,0x62,0x22,0x08,0x5F,
1903 0x05,0x21,0xB2,0xB2,0x55,0x77,0x2A,0xA6,
1904 0x25,0x2F,0x47,0xFA,0xC8,0xFF,0x8E,0x20,
1905 0x8C,0x6E,0x60,0x2E,0x58,0x48,0x72,0x44,
1906 0x56,0x36,0x4F,0x6E,0x3F,0x80,0x00,0x80,
1907 0x4F,0x7F,0x03,0xA8,0x7D,0x20,0x1A,0xA9,
1908 0x14,0x05,0x03,0x7E,0x64,0x31,0x14,0x75,
1909 0x18,0x05,0x18,0x05,0x4C,0xA8,0x01
1910};
1911
1912UCHAR XGI330_HiTVGroup3Simu[] =
1913{
1914 0x00,0x1A,0x22,0x63,0x62,0x22,0x08,0x95,
1915 0xDB,0x20,0xB8,0xB8,0x55,0x47,0x2A,0xA6,
1916 0x25,0x2F,0x47,0xFA,0xC8,0xFF,0x8E,0x20,
1917 0x8C,0x6E,0x60,0x15,0x26,0xD3,0xE4,0x11,
1918 0x56,0x36,0x4F,0x6E,0x3F,0x80,0x00,0x80,
1919 0x67,0x36,0x01,0x47,0x0E,0x10,0xBE,0xB4,
1920 0x01,0x05,0x03,0x7E,0x65,0x31,0x14,0x75,
1921 0x18,0x05,0x18,0x05,0x4C,0xA8,0x01
1922};
1923
1924UCHAR XGI330_HiTVGroup3Text[] =
1925{
1926 0x00,0x1A,0x22,0x63,0x62,0x22,0x08,0xA7,
1927 0xF5,0x20,0xCE,0xCE,0x55,0x47,0x2A,0xA6,
1928 0x25,0x2F,0x47,0xFA,0xC8,0xFF,0x8E,0x20,
1929 0x8C,0x6E,0x60,0x18,0x2C,0x0C,0x20,0x22,
1930 0x56,0x36,0x4F,0x6E,0x3F,0x80,0x00,0x80,
1931 0x93,0x3C,0x01,0x50,0x2F,0x10,0xF4,0xCA,
1932 0x01,0x05,0x03,0x7E,0x65,0x31,0x14,0x75,
1933 0x18,0x05,0x18,0x05,0x4C,0xA8,0x01
1934};
1935
1936UCHAR XGI330_Ren525pGroup3[] =
1937{
1938 0x00,0x14,0x15,0x25,0x55,0x15,0x0b,0x13,
1939 0xB1,0x41,0x62,0x62,0xFF,0xF4,0x45,0xa6,
1940 0x25,0x2F,0x67,0xF6,0xbf,0xFF,0x8E,0x20,
1941 0xAC,0xDA,0x60,0xFe,0x6A,0x9A,0x06,0x10,
1942 0xd1,0x04,0x18,0x0a,0xFF,0x80,0x00,0x80,
1943 0x3c,0x77,0x00,0xEF,0xE0,0x10,0xB0,0xE0,
1944 0x10,0x4F,0x0F,0x0F,0x05,0x0F,0x08,0x6E,
1945 0x1a,0x1F,0x25,0x2a,0x4C,0xAA,0x01
1946};
1947
1948UCHAR XGI330_Ren750pGroup3[] =
1949{
1950 0x00,0x14,0x15,0x25,0x55,0x15,0x0b,0x7a,
1951 0x54,0x41,0xE7,0xE7,0xFF,0xF4,0x45,0xa6,
1952 0x25,0x2F,0x67,0xF6,0xbf,0xFF,0x8E,0x20,
1953 0xAC,0x6A,0x60,0x2b,0x52,0xCD,0x61,0x10,
1954 0x51,0x04,0x18,0x0a,0x1F,0x80,0x00,0x80,
1955 0xFF,0xA4,0x04,0x2B,0x94,0x21,0x72,0x94,
1956 0x26,0x05,0x01,0x0F,0xed,0x0F,0x0A,0x64,
1957 0x18,0x1D,0x23,0x28,0x4C,0xAA,0x01
1958};
1959
1960XGI_PanelDelayTblStruct XGI330_PanelDelayTbl[]=
1961{
1962{{0x00,0x00}},
1963{{0x00,0x00}},
1964{{0x00,0x00}},
1965{{0x00,0x00}},
1966{{0x00,0x00}},
1967{{0x00,0x00}},
1968{{0x00,0x00}},
1969{{0x00,0x00}},
1970{{0x00,0x00}},
1971{{0x00,0x00}},
1972{{0x00,0x00}},
1973{{0x00,0x00}},
1974{{0x00,0x00}},
1975{{0x00,0x00}},
1976{{0x00,0x00}},
1977{{0x00,0x00}}
1978};
1979
1980XGI330_LVDSDataStruct XGI330_LVDS320x480Data_1[]=
1981{
1982 {848, 433,400,525},
1983 {848, 389,400,525},
1984 {848, 433,400,525},
1985 {848, 389,400,525},
1986 {848, 518,400, 525},
1987 {1056, 628,400,525},
1988 {400, 525,400,525},
1989 {800, 449,1000, 644},
1990 {800, 525,1000, 635}
1991};
1992
1993XGI330_LVDSDataStruct XGI330_LVDS800x600Data_1[]=
1994{
1995 {848, 433,1060, 629},
1996 {848, 389,1060, 629},
1997 {848, 433,1060, 629},
1998 {848, 389,1060, 629},
1999 {848, 518,1060, 629},
2000 {1056, 628,1056, 628},
2001 {1056, 628,1056, 628},
2002 {800, 449,1000, 644},
2003 {800, 525,1000, 635}
2004};
2005
2006XGI330_LVDSDataStruct XGI330_LVDS800x600Data_2[]=
2007{
2008 {1056, 628,1056, 628},
2009 {1056, 628,1056, 628},
2010 {1056, 628,1056, 628},
2011 {1056, 628,1056, 628},
2012 {1056, 628,1056, 628},
2013 {1056, 628,1056, 628},
2014 {1056, 628,1056, 628},
2015 {800, 449,1000, 644},
2016 {800, 525,1000, 635}
2017};
2018
2019XGI330_LVDSDataStruct XGI_LVDS1024x768Data_1[]=
2020{
2021 { 960 , 438 , 1344 , 806 } , /* 00 (320x200,320x400,640x200,640x400) */
2022 { 960 , 388 , 1344 , 806 } , /* 01 (320x350,640x350) */
2023 { 1040, 438 , 1344 , 806 } , /* 02 (360x400,720x400) */
2024 { 1040, 388 , 1344 , 806 } , /* 03 (720x350) */
2025 { 960 , 518 , 1344 , 806 } , /* 04 (320x240,640x480) */
2026 {1120 , 638 , 1344 , 806 } , /* 05 (400x300,800x600) */
2027 {1344 , 806 , 1344 , 806 } /* 06 (512x384,1024x768) */
2028};
2029
2030
2031XGI330_LVDSDataStruct XGI_LVDS1024x768Data_2[]=
2032{
2033 {1344, 806,1344, 806},
2034 {1344, 806,1344, 806},
2035 {1344, 806,1344, 806},
2036 {1344, 806,1344, 806},
2037 {1344, 806,1344, 806},
2038 {1344, 806,1344, 806},
2039 {1344, 806,1344, 806},
2040 {800, 449,1280, 801},
2041 {800, 525,1280, 813}
2042};
2043
2044XGI330_LVDSDataStruct XGI_LVDS1280x1024Data_1[]=
2045{
2046 {1048, 442,1688, 1066},
2047 {1048, 392,1688, 1066},
2048 {1048, 442,1688, 1066},
2049 {1048, 392,1688, 1066},
2050 {1048, 522,1688, 1066},
2051 {1208, 642,1688, 1066},
2052 {1432, 810,1688, 1066},
2053 {1688, 1066,1688, 1066}
2054};
2055
2056XGI330_LVDSDataStruct XGI_LVDS1280x1024Data_2[]=
2057{
2058 {1344, 806,1344, 806},
2059 {1344, 806,1344, 806},
2060 {1344, 806,1344, 806},
2061 {1344, 806,1344, 806},
2062 {1344, 806,1344, 806},
2063 {1344, 806,1344, 806},
2064 {1344, 806,1344, 806},
2065 {800, 449,1280, 801},
2066 {800, 525,1280, 813}
2067};
2068/*
2069XGI330_LVDSDataStruct XGI_LVDS1280x768Data_1[]=
2070{
2071 {768,438,1408,806},
2072 {768,388,1408,806},
2073 {768,438,1408,806},
2074 {768,388,1408,806},
2075 {768,518,1408,806},
2076 {928,638,1408,806},
2077 {1408,806,1408,806},
2078 {1408,806,1408,806},
2079 {1408,806,1408,806}
2080};
2081
2082XGI330_LVDSDataStruct XGI_LVDS1280x768Data_2[]=
2083{
2084 {1408, 806,1408, 806},
2085 {1408, 806,1408, 806},
2086 {1408, 806,1408, 806},
2087 {1408, 806,1408, 806},
2088 {1408, 806,1408, 806},
2089 {1408, 806,1408, 806},
2090 {1408, 806,1408, 806},
2091 {1408, 806,1408, 806},
2092 {1408, 806,1408, 806}
2093};
2094
2095XGI330_LVDSDataStruct XGI_LVDS1280x768NData_1[]=
2096{
2097 {704, 438,1344, 806},
2098 {704, 388,1344, 806},
2099 {704, 438,1344, 806},
2100 {704, 388,1344, 806},
2101 {704, 518,1344, 806},
2102 {864, 638,1344, 806},
2103 {1088, 806,1344, 806},
2104 {1344, 806,1344, 806},
2105 {1344, 806,1344, 806}
2106};
2107
2108XGI330_LVDSDataStruct XGI_LVDS1280x768NData_2[]=
2109{
2110 {1344, 806,1344, 806},
2111 {1344, 806,1344, 806},
2112 {1344, 806,1344, 806},
2113 {1344, 806,1344, 806},
2114 {1344, 806,1344, 806},
2115 {1344, 806,1344, 806},
2116 {1344, 806,1344, 806},
2117 {1344, 806,1344, 806},
2118 {1344, 806,1344, 806}
2119};
2120
2121XGI330_LVDSDataStruct XGI_LVDS1280x768SData_1[]=
2122{
2123 {1048,438,1688,806},
2124 {1048,388,1688,806},
2125 {1148,438,1688,806},
2126 {1148,388,1688,806},
2127 {1048,518,1688,806},
2128 {1208,638,1688,806},
2129 {1432,806,1688,806},
2130 {1688,806,1688,806},
2131 {1688,806,1688,806}
2132};
2133
2134XGI330_LVDSDataStruct XGI_LVDS1280x768SData_2[]=
2135{
2136 {1688,806,1688,806},
2137 {1688,806,1688,806},
2138 {1688,806,1688,806},
2139 {1688,806,1688,806},
2140 {1688,806,1688,806},
2141 {1688,806,1688,806},
2142 {1688,806,1688,806},
2143 {1688,806,1688,806},
2144 {1688,806,1688,806}
2145};
2146*/
2147XGI330_LVDSDataStruct XGI_LVDS1400x1050Data_1[]=
2148{
2149 {928,416,1688,1066},
2150 {928,366,1688,1066},
2151 {928,416,1688,1066},
2152 {928,366,1688,1066},
2153 {928,496,1688,1066},
2154 {1088,616,1688,1066},
2155 {1312,784,1688,1066},
2156 {1568,1040,1688,1066},
2157 {1688,1066,1688,1066}
2158};
2159
2160XGI330_LVDSDataStruct XGI_LVDS1400x1050Data_2[]=
2161{
2162 {1688,1066,1688,1066},
2163 {1688,1066,1688,1066},
2164 {1688,1066,1688,1066},
2165 {1688,1066,1688,1066},
2166 {1688,1066,1688,1066},
2167 {1688,1066,1688,1066},
2168 {1688,1066,1688,1066},
2169 {1688,1066,1688,1066},
2170 {1688,1066,1688,1066}
2171};
2172
2173XGI330_LVDSDataStruct XGI_LVDS1600x1200Data_1[]=
2174{ /* ;;[ycchen] 12/05/02 LCDHTxLCDVT=2048x1320 */
2175 { 1088,520,2048,1320 },/* 00 (320x200,320x400,640x200,640x400) */
2176 { 1088,470,2048,1320 },/* 01 (320x350,640x350) */
2177 { 1088,520,2048,1320 },/* 02 (360x400,720x400) */
2178 { 1088,470,2048,1320 },/* 03 (720x350) */
2179 { 1088,600,2048,1320 },/* 04 (320x240,640x480) */
2180 { 1248,720,2048,1320 },/* 05 (400x300,800x600) */
2181 { 1472,888,2048,1320 },/* 06 (512x384,1024x768) */
2182 { 1728,1144,2048,1320 },/* 07 (640x512,1280x1024) */
2183 { 1848,1170,2048,1320 },/* 08 (1400x1050) */
2184 { 2048,1320,2048,1320 } /* 09 (1600x1200) */
2185};
2186
2187XGI330_LVDSDataStruct XGI_LVDSNoScalingData[]=
2188{
2189 { 800,449,800,449 }, /* 00 (320x200,320x400,640x200,640x400) */
2190 { 800,449,800,449 }, /* 01 (320x350,640x350) */
2191 { 800,449,800,449 }, /* 02 (360x400,720x400) */
2192 { 800,449,800,449 }, /* 03 (720x350) */
2193 { 800,525,800,525 }, /* 04 (640x480x60Hz) */
2194 { 1056,628,1056,628 }, /* 05 (800x600x60Hz) */
2195 { 1344,806,1344,806 }, /* 06 (1024x768x60Hz) */
2196 { 1688,1066,1688,1066 }, /* 07 (1280x1024x60Hz) */
2197 { 1688,1066,1688,1066 }, /* 08 (1400x1050x60Hz) ;;[ycchen] 12/19/02 */
2198 { 2160,1250,2160,1250 }, /* 09 (1600x1200x60Hz) */
2199 { 1688,806,1688,806 } /* 0A (1280x768x60Hz) */
2200};
2201
2202XGI330_LVDSDataStruct XGI_LVDS1024x768Data_1x75[]=
2203{
2204 {960,438,1312,800 }, /* 00 (320x200,320x400,640x200,640x400) */
2205 {960,388,1312,800 }, /* 01 (320x350,640x350) */
2206 {1040,438,1312,800 }, /* 02 (360x400,720x400) */
2207 {1040,388,1312,800 }, /* 03 (720x350) */
2208 {928,512,1312,800 }, /* 04 (320x240,640x480) */
2209 {1088,632,1312,800 }, /* 05 (400x300,800x600) */
2210 {1312,800,1312,800 }, /* 06 (512x384,1024x768) */
2211};
2212
2213
2214XGI330_LVDSDataStruct XGI_LVDS1024x768Data_2x75[]=
2215{
2216 {1312,800,1312,800}, /* ; 00 (320x200,320x400,640x200,640x400) */
2217 {1312,800,1312,800}, /* ; 01 (320x350,640x350) */
2218 {1312,800,1312,800}, /* ; 02 (360x400,720x400) */
2219 {1312,800,1312,800}, /* ; 03 (720x350) */
2220 {1312,800,1312,800}, /* ; 04 (320x240,640x480) */
2221 {1312,800,1312,800}, /* ; 05 (400x300,800x600) */
2222 {1312,800,1312,800}, /* ; 06 (512x384,1024x768) */
2223};
2224
2225XGI330_LVDSDataStruct XGI_LVDS1280x1024Data_1x75[]=
2226{
2227 {1048,442,1688,1066 }, /* ; 00 (320x200,320x400,640x200,640x400) */
2228 {1048,392,1688,1066 }, /* ; 01 (320x350,640x350) */
2229 {1128,442,1688,1066 }, /* ; 02 (360x400,720x400) */
2230 {1128,392,1688,1066 }, /* ; 03 (720x350) */
2231 {1048,522,1688,1066 }, /* ; 04 (320x240,640x480) */
2232 {1208,642,1688,1066 }, /* ; 05 (400x300,800x600) */
2233 {1432,810,1688,1066 }, /* ; 06 (512x384,1024x768) */
2234 {1688,1066,1688,1066 }, /* ; 06; 07 (640x512,1280x1024) */
2235};
2236
2237XGI330_LVDSDataStruct XGI_LVDS1280x1024Data_2x75[]=
2238{
2239 {1688,1066,1688,1066 }, /* ; 00 (320x200,320x400,640x200,640x400) */
2240 {1688,1066,1688,1066 }, /* ; 01 (320x350,640x350) */
2241 {1688,1066,1688,1066 }, /* ; 02 (360x400,720x400) */
2242 {1688,1066,1688,1066 }, /* ; 03 (720x350) */
2243 {1688,1066,1688,1066 }, /* ; 04 (320x240,640x480) */
2244 {1688,1066,1688,1066 }, /* ; 05 (400x300,800x600) */
2245 {1688,1066,1688,1066 }, /* ; 06 (512x384,1024x768) */
2246 {1688,1066,1688,1066 }, /* ; 06; 07 (640x512,1280x1024) */
2247};
2248
2249XGI330_LVDSDataStruct XGI_LVDSNoScalingDatax75[]=
2250{
2251 {800,449,800,449 }, /* ; 00 (320x200,320x400,640x200,640x400) */
2252 {800,449,800,449 }, /* ; 01 (320x350,640x350) */
2253 {900,449,900,449 }, /* ; 02 (360x400,720x400) */
2254 {900,449,900,449 }, /* ; 03 (720x350) */
2255 {800,500,800,500 }, /* ; 04 (640x480x75Hz) */
2256 {1056,625,1056,625 }, /* ; 05 (800x600x75Hz) */
2257 {1312,800,1312,800 }, /* ; 06 (1024x768x75Hz) */
2258 {1688,1066,1688,1066 }, /* ; 07 (1280x1024x75Hz) */
2259 {1688,1066,1688,1066 }, /* ; 08 (1400x1050x75Hz) ;;[ycchen] 12/19/02 */
2260 {2160,1250,2160,1250 }, /* ; 09 (1600x1200x75Hz) */
2261 {1688,806,1688,806 }, /* ; 0A (1280x768x75Hz) */
2262};
2263
2264XGI330_LVDSDataStruct XGI_LVDS1024x768Des_1[]=
2265{
2266 { 0,1048, 0, 771 }, /* 00 (320x200,320x400,640x200,640x400) */
2267 { 0,1048, 0, 771 }, /* 01 (320x350,640x350) */
2268 { 0,1048, 0, 771 }, /* 02 (360x400,720x400) */
2269 { 0,1048, 0, 771 }, /* 03 (720x350) */
2270 { 0,1048, 0, 771 }, /* 04 (640x480x60Hz) */
2271 { 0,1048, 0, 771 }, /* 05 (800x600x60Hz) */
2272 { 0,1048, 805, 770 } /* 06 (1024x768x60Hz) */
2273} ;
2274
2275XGI330_LVDSDataStruct XGI_LVDS1024x768Des_2[]=
2276{
2277 { 1142, 856, 622, 587 }, /* 00 (320x200,320x400,640x200,640x400) */
2278 { 1142, 856, 597, 562 }, /* 01 (320x350,640x350) */
2279 { 1142, 856, 622, 587 }, /* 02 (360x400,720x400) */
2280 { 1142, 856, 597, 562 }, /* 03 (720x350) */
2281 { 1142,1048, 722, 687 }, /* 04 (640x480x60Hz) */
2282 { 1232, 936, 722, 687 }, /* 05 (800x600x60Hz) */
2283 { 0,1048, 805, 771 } /* 06 (1024x768x60Hz) */
2284};
2285
2286XGI330_LVDSDataStruct XGI_LVDS1024x768Des_3[]=
2287{
2288 { 320, 24, 622, 587 }, /* 00 (320x200,320x400,640x200,640x400) */
2289 { 320, 24, 597, 562 }, /* 01 (320x350,640x350) */
2290 { 320, 24, 622, 587 }, /* 02 (360x400,720x400) */
2291 { 320, 24, 597, 562 }, /* 03 (720x350) */
2292 { 320, 24, 722, 687 } /* 04 (640x480x60Hz) */
2293};
2294
2295XGI330_LVDSDataStruct XGI_LVDS1280x1024Des_1[]=
2296{
2297 { 0,1328, 0, 1025 }, /* 00 (320x200,320x400,640x200,640x400) */
2298 { 0,1328, 0, 1025 }, /* 01 (320x350,640x350) */
2299 { 0,1328, 0, 1025 }, /* 02 (360x400,720x400) */
2300 { 0,1328, 0, 1025 }, /* 03 (720x350) */
2301 { 0,1328, 0, 1025 }, /* 04 (640x480x60Hz) */
2302 { 0,1328, 0, 1025 }, /* 05 (800x600x60Hz) */
2303 { 0,1328, 0, 1025 }, /* 06 (1024x768x60Hz) */
2304 { 0,1328, 1065, 1024 } /* 07 (1280x1024x60Hz) */
2305};
2306
2307 /* The Display setting for DE Mode Panel */
2308XGI330_LVDSDataStruct XGI_LVDS1280x1024Des_2[]=
2309{
2310 { 1368,1008,752,711 }, /* 00 (320x200,320x400,640x200,640x400) */
2311 { 1368,1008,729,688 }, /* 01 (320x350,640x350) */
2312 { 1408,1048,752,711 }, /* 02 (360x400,720x400) */
2313 { 1408,1048,729,688 }, /* 03 (720x350) */
2314 { 1368,1008,794,753 }, /* 04 (640x480x60Hz) */
2315 { 1448,1068,854,813 }, /* 05 (800x600x60Hz) */
2316 { 1560,1200,938,897 }, /* 06 (1024x768x60Hz) */
2317 { 0000,1328,0,1025 } /* 07 (1280x1024x60Hz) */
2318};
2319
2320XGI330_LVDSDataStruct XGI_LVDS1400x1050Des_1[]=
2321{
2322 { 0,1448,0,1051 }, /* 00 (320x200,320x400,640x200,640x400) */
2323 { 0,1448,0,1051 }, /* 01 (320x350,640x350) */
2324 { 0,1448,0,1051 }, /* 02 (360x400,720x400) */
2325 { 0,1448,0,1051 }, /* 03 (720x350) */
2326 { 0,1448,0,1051 }, /* 04 (640x480x60Hz) */
2327 { 0,1448,0,1051 }, /* 05 (800x600x60Hz) */
2328 { 0,1448,0,1051 }, /* 06 (1024x768x60Hz) */
2329 { 0,1448,0,1051 }, /* 07 (1280x1024x60Hz) */
2330 { 0,1448,0,1051 } /* 08 (1400x1050x60Hz) */
2331};
2332
2333XGI330_LVDSDataStruct XGI_LVDS1400x1050Des_2[]=
2334{
2335 { 1308,1068, 781, 766 }, /* 00 (320x200,320x400,640x200,640x400) */
2336 { 1308,1068, 781, 766 }, /* 01 (320x350,640x350) */
2337 { 1308,1068, 781, 766 }, /* 02 (360x400,720x400) */
2338 { 1308,1068, 781, 766 }, /* 03 (720x350) */
2339 { 1308,1068, 781, 766 }, /* 04 (640x480x60Hz) */
2340 { 1388,1148, 841, 826 }, /* 05 (800x600x60Hz) */
2341 { 1490,1250, 925, 910 }, /* 06 (1024x768x60Hz) */
2342 { 1608,1368,1053,1038 }, /* 07 (1280x1024x60Hz) */
2343 { 0,1448,0,1051 } /* 08 (1400x1050x60Hz) */
2344};
2345
2346XGI330_LVDSDataStruct XGI_LVDS1600x1200Des_1[]=
2347{
2348 { 0,1664,0,1201 }, /* 00 (320x200,320x400,640x200,640x400) */
2349 { 0,1664,0,1201 }, /* 01 (320x350,640x350) */
2350 { 0,1664,0,1201 }, /* 02 (360x400,720x400) */
2351 { 0,1664,0,1201 }, /* 03 (720x350) */
2352 { 0,1664,0,1201 }, /* 04 (640x480x60Hz) */
2353 { 0,1664,0,1201 }, /* 05 (800x600x60Hz) */
2354 { 0,1664,0,1201 }, /* 06 (1024x768x60Hz) */
2355 { 0,1664,0,1201 }, /* 07 (1280x1024x60Hz) */
2356 { 0,1664,0,1201 }, /* 08 (1400x1050x60Hz) */
2357 { 0,1664,0,1201 } /* 09 (1600x1200x60Hz) */
2358};
2359
2360
2361
2362XGI330_LCDDataDesStruct2 XGI_LVDSNoScalingDesData[]=
2363{
2364 { 0, 648, 448, 405, 96, 2 }, /* 00 (320x200,320x400,640x200,640x400) */
2365 { 0, 648, 448, 355, 96, 2 }, /* 01 (320x350,640x350) */
2366 { 0, 648, 448, 405, 96, 2 }, /* 02 (360x400,720x400) */
2367 { 0, 648, 448, 355, 96, 2 }, /* 03 (720x350) */
2368 { 0, 648, 1, 483, 96, 2 }, /* 04 (640x480x60Hz) */
2369 { 0, 840, 627, 600, 128, 4 }, /* 05 (800x600x60Hz) */
2370 { 0,1048, 805, 770, 136, 6 }, /* 06 (1024x768x60Hz) */
2371 { 0,1328,0,1025, 112, 3 }, /* 07 (1280x1024x60Hz) */
2372 { 0,1438,0,1051, 112, 3 }, /* 08 (1400x1050x60Hz) ;;[ycchen] 12/19/02 */
2373 { 0,1664,0,1201, 192, 3 }, /* 09 (1600x1200x60Hz) */
2374 { 0,1328,0,0771, 112, 6 } /* 0A (1280x768x60Hz) */
2375};
2376
2377XGI330_LVDSDataStruct XGI_LVDS1024x768Des_1x75[]= /* ; 1024x768 Full-screen */
2378{
2379 {0,1040,0,769}, /* ; 00 (320x200,320x400,640x200,640x400) */
2380 {0,1040,0,769}, /* ; 01 (320x350,640x350) */
2381 {0,1040,0,769}, /* ; 02 (360x400,720x400) */
2382 {0,1040,0,769}, /* ; 03 (720x350) */
2383 {0,1040,0,769}, /* ; 04 (640x480x75Hz) */
2384 {0,1040,0,769}, /* ; 05 (800x600x75Hz) */
2385 {0,1040,0,769} /* ; 06 (1024x768x75Hz) */
2386};
2387
2388XGI330_LVDSDataStruct XGI_LVDS1024x768Des_2x75[]= /* ; 1024x768 center-screen (Enh. Mode) */
2389{
2390 {1142, 856,622,587 }, /* 00 (320x200,320x400,640x200,640x400) */
2391 {1142, 856,597,562 }, /* 01 (320x350,640x350) */
2392 {1142, 856,622,587 }, /* 02 (360x400,720x400) */
2393 {1142, 856,597,562 }, /* 03 (720x350) */
2394 {1142,1048,722,687 }, /* 04 (640x480x60Hz) */
2395 {1232, 936,722,687 }, /* 05 (800x600x60Hz) */
2396 { 0,1048,805,771 } /* 06 (1024x768x60Hz) */
2397};
2398
2399XGI330_LVDSDataStruct XGI_LVDS1024x768Des_3x75[]= /* ; 1024x768 center-screen (St.Mode) */
2400{
2401 {320,24,622,587 }, /* ; 00 (320x200,320x400,640x200,640x400) */
2402 {320,24,597,562 }, /* ; 01 (320x350,640x350) */
2403 {320,24,622,587 }, /* ; 02 (360x400,720x400) */
2404 {320,24,597,562 }, /* ; 03 (720x350) */
2405 {320,24,722,687 } /* ; 04 (640x480x60Hz) */
2406};
2407
2408XGI330_LVDSDataStruct XGI_LVDS1280x1024Des_1x75[]=
2409{
2410 {0,1296,0,1025}, /* ; 00 (320x200,320x400,640x200,640x400) */
2411 {0,1296,0,1025}, /* ; 01 (320x350,640x350) */
2412 {0,1296,0,1025}, /* ; 02 (360x400,720x400) */
2413 {0,1296,0,1025}, /* ; 03 (720x350) */
2414 {0,1296,0,1025}, /* ; 04 (640x480x75Hz) */
2415 {0,1296,0,1025}, /* ; 05 (800x600x75Hz) */
2416 {0,1296,0,1025}, /* ; 06 (1024x768x75Hz) */
2417 {0,1296,0,1025} /* ; 07 (1280x1024x75Hz) */
2418};
2419
2420/* The Display setting for DE Mode Panel */
2421XGI330_LVDSDataStruct XGI_LVDS1280x1024Des_2x75[]= /* [ycchen] 02/18/03 Set DE as default */
2422{
2423 {1368,976,752,711 }, /* ; 00 (320x200,320x400,640x200,640x400) */
2424 {1368,976,729,688 }, /* ; 01 (320x350,640x350) */
2425 {1408,976,752,711 }, /* ; 02 (360x400,720x400) */
2426 {1408,976,729,688 }, /* ; 03 (720x350) */
2427 {1368,976,794,753 }, /* ; 04 (640x480x75Hz) */
2428 {1448,1036,854,813}, /* ; 05 (800x600x75Hz) */
2429 {1560,1168,938,897}, /* ; 06 (1024x768x75Hz) */
2430 {0,1296,0,1025 } /* ; 07 (1280x1024x75Hz) */
2431};
2432
2433XGI330_LCDDataDesStruct2 XGI_LVDSNoScalingDesDatax75[]= /* Scaling LCD 75Hz */
2434{
2435 { 0,648,448,405,96,2 }, /* ; 00 (320x200,320x400,640x200,640x400) */
2436 { 0,648,448,355,96,2 }, /* ; 01 (320x350,640x350) */
2437 { 0,729,448,405,108,2 }, /* ; 02 (360x400,720x400) */
2438 { 0,729,448,355,108,2 }, /* ; 03 (720x350) */
2439 { 0,656,0,481,64,3 }, /* ; 04 (640x480x75Hz) */
2440 { 0,816,0,601,80,3 }, /* ; 05 (800x600x75Hz) */
2441 { 0,1040,0,769,96,3 }, /* ; 06 (1024x768x75Hz) */
2442 { 0,1296,0,1025,144,3 }, /* ; 07 (1280x1024x75Hz) */
2443 { 0,1448,0,1051,112,3 }, /* ; 08 (1400x1050x75Hz) ;;[ycchen] 12/19/02 */
2444 { 0,1664,0,1201,192,3 }, /* ; 09 (1600x1200x75Hz) */
2445 { 0,1328,0,771,112,6 } /* ; 0A (1280x768x75Hz) */
2446};
2447
2448XGI330_LVDSDataStruct XGI330_LVDS640x480Data_1[]=
2449{
2450 {800, 449, 800, 449},
2451 {800, 449, 800, 449},
2452 {800, 449, 800, 449},
2453 {800, 449, 800, 449},
2454 {800, 525, 800, 525},
2455 {1056, 628,1056, 628},
2456 {1056, 628,1056, 628},
2457 {1056, 628,1056, 628},
2458 {1056, 628,1056, 628}
2459};
2460
2461XGI330_CHTVDataStruct XGI_CHTVUNTSCData[]=
2462{
2463 {840, 600, 840, 600},
2464 {840, 600, 840, 600},
2465 {840, 600, 840, 600},
2466 {840, 600, 840, 600},
2467 {784, 600, 784, 600},
2468 {1064, 750,1064, 750}
2469};
2470
2471XGI330_CHTVDataStruct XGI_CHTVONTSCData[]=
2472{
2473 {840, 525, 840, 525},
2474 {840, 525, 840, 525},
2475 {840, 525, 840, 525},
2476 {840, 525, 840, 525},
2477 {784, 525, 784, 525},
2478 {1040, 700,1040, 700}
2479};
2480
2481XGI330_CHTVDataStruct XGI_CHTVUPALData[]=
2482{
2483 {1008, 625,1008, 625},
2484 {1008, 625,1008, 625},
2485 {1008, 625,1008, 625},
2486 {1008, 625,1008, 625},
2487 {840, 750, 840, 750},
2488 {936, 836, 936, 836}
2489};
2490
2491XGI330_CHTVDataStruct XGI_CHTVOPALData[]=
2492{
2493 {1008, 625,1008, 625},
2494 {1008, 625,1008, 625},
2495 {1008, 625,1008, 625},
2496 {1008, 625,1008, 625},
2497 {840, 625, 840, 625},
2498 {960, 750, 960, 750}
2499};
2500
2501XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11024x768_1_H[]=
2502{
2503 /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
2504 {{ 0x4B,0x27,0x8F,0x32,0x1B,0x00,0x45,0x00 }}, /* 00 (320x) */
2505 {{ 0x4B,0x27,0x8F,0x2B,0x03,0x00,0x44,0x00 }}, /* 01 (360x) */
2506 {{ 0x55,0x31,0x99,0x46,0x1D,0x00,0x55,0x00 }}, /* 02 (400x) */
2507 {{ 0x63,0x3F,0x87,0x4A,0x93,0x00,0x01,0x00 }}, /* 03 (512x) */
2508 {{ 0x73,0x4F,0x97,0x55,0x86,0x00,0x05,0x00 }}, /* 04 (640x) */
2509 {{ 0x73,0x4F,0x97,0x55,0x86,0x00,0x05,0x00 }}, /* 05 (720x) */
2510 {{ 0x87,0x63,0x8B,0x69,0x1A,0x00,0x26,0x00 }}, /* 06 (800x) */
2511 {{ 0xA3,0x7F,0x87,0x86,0x97,0x00,0x02,0x00 }} /* 07 (1024x) */
2512};
2513
2514XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11280x1024_1_H[]=
2515{
2516 /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
2517 {{ 0x56,0x27,0x9A,0x30,0x1E,0x00,0x05,0x00 }}, /* 00 (320x) */
2518 {{ 0x56,0x27,0x9A,0x30,0x1E,0x00,0x05,0x00 }}, /* 01 (360x) */
2519 {{ 0x60,0x31,0x84,0x3A,0x88,0x00,0x01,0x00 }}, /* 02 (400x) */
2520 {{ 0x6E,0x3F,0x92,0x48,0x96,0x00,0x01,0x00 }}, /* 03 (512x) */
2521 {{ 0x7E,0x4F,0x82,0x58,0x06,0x00,0x06,0x00 }}, /* 04 (640x) */
2522 {{ 0x7E,0x4F,0x82,0x58,0x06,0x00,0x06,0x00 }}, /* 05 (720x) */
2523 {{ 0x92,0x63,0x96,0x6C,0x1A,0x00,0x06,0x00 }}, /* 06 (800x) */
2524 {{ 0xAE,0x7F,0x92,0x88,0x96,0x00,0x02,0x00 }}, /* 07 (1024x) */
2525 {{ 0xCE,0x9F,0x92,0xA8,0x16,0x00,0x07,0x00 }} /* 08 (1280x) */
2526};
2527
2528XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11024x768_2_H[]=
2529{
2530 /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
2531 {{ 0x63,0x27,0x87,0x3B,0x8C,0x00,0x01,0x00 }}, /* 00 (320x) */
2532 {{ 0x63,0x27,0x87,0x3B,0x8C,0x00,0x01,0x00 }}, /* 01 (360x) */
2533 {{ 0x63,0x31,0x87,0x3D,0x8E,0x00,0x01,0x00 }}, /* 02 (400x) */
2534 {{ 0x63,0x3F,0x87,0x45,0x96,0x00,0x01,0x00 }}, /* 03 (512x) */
2535 {{ 0xA3,0x4F,0x87,0x6E,0x9F,0x00,0x06,0x00 }}, /* 04 (640x) */
2536 {{ 0xA3,0x4F,0x87,0x6E,0x9F,0x00,0x06,0x00 }}, /* 05 (720x) */
2537 {{ 0xA3,0x63,0x87,0x78,0x89,0x00,0x02,0x00 }}, /* 06 (800x) */
2538 {{ 0xA3,0x7F,0x87,0x86,0x97,0x00,0x02,0x00 }} /* 07 (1024x) */
2539};
2540
2541XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11280x1024_2_H[]=
2542{
2543 /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
2544 {{ 0x7E,0x3B,0x9A,0x44,0x12,0x00,0x01,0x00 }}, /* 00 (320x) */
2545 {{ 0x7E,0x3B,0x9A,0x44,0x12,0x00,0x01,0x00 }}, /* 01 (360x) */
2546 {{ 0x7E,0x40,0x84,0x49,0x91,0x00,0x01,0x00 }}, /* 02 (400x) */
2547 {{ 0x7E,0x47,0x93,0x50,0x9E,0x00,0x01,0x00 }}, /* 03 (512x) */
2548 {{ 0xCE,0x77,0x8A,0x80,0x8E,0x00,0x02,0x00 }}, /* 04 (640x) */
2549 {{ 0xCE,0x77,0x8A,0x80,0x8E,0x00,0x02,0x00 }}, /* 05 (720x) */
2550 {{ 0xCE,0x81,0x94,0x8A,0x98,0x00,0x02,0x00 }}, /* 06 (800x) */
2551 {{ 0xCE,0x8F,0x82,0x98,0x06,0x00,0x07,0x00 }}, /* 07 (1024x) */
2552 {{ 0xCE,0x9F,0x92,0xA8,0x16,0x00,0x07,0x00 }} /* 08 (1280x) */
2553};
2554
2555XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11400x1050_1_H[]=
2556{ /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
2557 {{ 0x47,0x27,0x8B,0x2C,0x1A,0x00,0x05,0x00 }}, /* 00 (320x) */
2558 {{ 0x47,0x27,0x8B,0x30,0x1E,0x00,0x05,0x00 }}, /* 01 (360x) */
2559 {{ 0x51,0x31,0x95,0x36,0x04,0x00,0x01,0x00 }}, /* 02 (400x) */
2560 {{ 0x5F,0x3F,0x83,0x44,0x92,0x00,0x01,0x00 }}, /* 03 (512x) */
2561 {{ 0x6F,0x4F,0x93,0x54,0x82,0x00,0x05,0x00 }}, /* 04 (640x) */
2562 {{ 0x6F,0x4F,0x93,0x54,0x82,0x00,0x05,0x00 }}, /* 05 (720x) */
2563 {{ 0x83,0x63,0x87,0x68,0x16,0x00,0x06,0x00 }}, /* 06 (800x) */
2564 {{ 0x9F,0x7F,0x83,0x84,0x92,0x00,0x02,0x00 }}, /* 07 (1024x) */
2565 {{ 0xBF,0x9F,0x83,0xA4,0x12,0x00,0x07,0x00 }}, /* 08 (1280x) */
2566 {{ 0xCE,0xAE,0x92,0xB3,0x01,0x00,0x03,0x00 }} /* 09 (1400x) */
2567};
2568
2569XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11400x1050_2_H[]=
2570{ /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
2571 {{ 0x76,0x3F,0x83,0x45,0x8C,0x00,0x41,0x00 }}, /* 00 (320x) */
2572 {{ 0x76,0x3F,0x83,0x45,0x8C,0x00,0x41,0x00 }}, /* 01 (360x) */
2573 {{ 0x76,0x31,0x9A,0x48,0x9F,0x00,0x41,0x00 }}, /* 02 (400x) */
2574 {{ 0x76,0x3F,0x9A,0x4F,0x96,0x00,0x41,0x00 }}, /* 03 (512x) */
2575 {{ 0xCE,0x7E,0x82,0x87,0x9E,0x00,0x02,0x00 }}, /* 04 (640x) */
2576 {{ 0xCE,0x7E,0x82,0x87,0x9E,0x00,0x02,0x00 }}, /* 05 (720x) */
2577 {{ 0xCE,0x63,0x92,0x96,0x04,0x00,0x07,0x00 }}, /* 06 (800x) */
2578 {{ 0xCE,0x7F,0x92,0xA4,0x12,0x00,0x07,0x00 }}, /* 07 (1024x) */
2579 {{ 0xCE,0x9F,0x92,0xB4,0x02,0x00,0x03,0x00 }}, /* 08 (1280x) */
2580 {{ 0xCE,0xAE,0x92,0xBC,0x0A,0x00,0x03,0x00 }} /* 09 (1400x) */
2581};
2582
2583XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11600x1200_1_H[]=
2584/* ;302lv channelA [ycchen] 12/05/02 LCDHT=2048 */
2585{ /* ; CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
2586 {{ 0x5B,0x27,0x9F,0x32,0x0A,0x00,0x01,0x00 }},/* 00 (320x) */
2587 {{ 0x5B,0x27,0x9F,0x32,0x0A,0x00,0x01,0x00 }},/* 01 (360x) */
2588 {{ 0x65,0x31,0x89,0x3C,0x94,0x00,0x01,0x00 }},/* 02 (400x) */
2589 {{ 0x73,0x3F,0x97,0x4A,0x82,0x00,0x05,0x00 }},/* 03 (512x) */
2590 {{ 0x83,0x4F,0x87,0x51,0x09,0x00,0x06,0x00 }},/* 04 (640x) */
2591 {{ 0x83,0x4F,0x87,0x51,0x09,0x00,0x06,0x00 }},/* 05 (720x) */
2592 {{ 0x97,0x63,0x9B,0x65,0x1D,0x00,0x06,0xF0 }},/* 06 (800x) */
2593 {{ 0xB3,0x7F,0x97,0x81,0x99,0x00,0x02,0x00 }},/* 07 (1024x) */
2594 {{ 0xD3,0x9F,0x97,0xA1,0x19,0x00,0x07,0x00 }},/* 08 (1280x) */
2595 {{ 0xE2,0xAE,0x86,0xB9,0x91,0x00,0x03,0x00 }},/* 09 (1400x) */
2596 {{ 0xFB,0xC7,0x9F,0xC9,0x81,0x00,0x07,0x00 }} /* 0A (1600x) */
2597};
2598
2599XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_1_V[]=
2600{ /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A+CR09(5->7) */
2601 {{ 0x97,0x1F,0x60,0x87,0x5D,0x83,0x10 }}, /* 00 (x350) */
2602 {{ 0xB4,0x1F,0x92,0x89,0x8F,0xB5,0x30 }}, /* 01 (x400) */
2603 {{ 0x04,0x3E,0xE2,0x89,0xDF,0x05,0x00 }}, /* 02 (x480) */
2604 {{ 0x7C,0xF0,0x5A,0x8F,0x57,0x7D,0xA0 }}, /* 03 (x600) */
2605 {{ 0x24,0xF5,0x02,0x88,0xFF,0x25,0x90 }} /* 04 (x768) */
2606};
2607
2608XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_2_V[]=
2609{ /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
2610 {{ 0x24,0xBB,0x31,0x87,0x5D,0x25,0x30 }}, /* 00 (x350) */
2611 {{ 0x24,0xBB,0x4A,0x80,0x8F,0x25,0x30 }}, /* 01 (x400) */
2612 {{ 0x24,0xBB,0x72,0x88,0xDF,0x25,0x30 }}, /* 02 (x480) */
2613 {{ 0x24,0xF1,0xAE,0x84,0x57,0x25,0xB0 }}, /* 03 (x600) */
2614 {{ 0x24,0xF5,0x02,0x88,0xFF,0x25,0x90 }} /* 04 (x768) */
2615};
2616
2617XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_1_V[]=
2618{ /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
2619 {{ 0x86,0x1F,0x5E,0x82,0x5D,0x87,0x00 }}, /* 00 (x350) */
2620 {{ 0xB8,0x1F,0x90,0x84,0x8F,0xB9,0x30 }}, /* 01 (x400) */
2621 {{ 0x08,0x3E,0xE0,0x84,0xDF,0x09,0x00 }}, /* 02 (x480) */
2622 {{ 0x80,0xF0,0x58,0x8C,0x57,0x81,0xA0 }}, /* 03 (x600) */
2623 {{ 0x28,0xF5,0x00,0x84,0xFF,0x29,0x90 }}, /* 04 (x768) */
2624 {{ 0x28,0x5A,0x13,0x87,0xFF,0x29,0xA9 }} /* 05 (x1024) */
2625};
2626
2627XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_2_V[]=
2628{ /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
2629 {{ 0x28,0xD2,0xAF,0x83,0xAE,0xD8,0xA1 }}, /* 00 (x350) */
2630 {{ 0x28,0xD2,0xC8,0x8C,0xC7,0xF2,0x81 }}, /* 01 (x400) */
2631 {{ 0x28,0xD2,0xF0,0x84,0xEF,0x1A,0xB1 }}, /* 02 (x480) */
2632 {{ 0x28,0xDE,0x2C,0x8F,0x2B,0x56,0x91 }}, /* 03 (x600) */
2633 {{ 0x28,0xDE,0x80,0x83,0x7F,0xAA,0x91 }}, /* 04 (x768) */
2634 {{ 0x28,0x5A,0x13,0x87,0xFF,0x29,0xA9 }} /* 05 (x1024) */
2635};
2636
2637XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11400x1050_1_V[]=
2638{ /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
2639 {{ 0x6C,0x1F,0x60,0x84,0x5D,0x6D,0x10 }}, /* 00 (x350) */
2640 {{ 0x9E,0x1F,0x93,0x86,0x8F,0x9F,0x30 }}, /* 01 (x400) */
2641 {{ 0xEE,0x1F,0xE2,0x86,0xDF,0xEF,0x10 }}, /* 02 (x480) */
2642 {{ 0x66,0xF0,0x5A,0x8e,0x57,0x67,0xA0 }}, /* 03 (x600) */
2643 {{ 0x0E,0xF5,0x02,0x86,0xFF,0x0F,0x90 }}, /* 04 (x768) */
2644 {{ 0x0E,0x5A,0x02,0x86,0xFF,0x0F,0x89 }}, /* 05 (x1024) */
2645 {{ 0x28,0x10,0x1A,0x80,0x19,0x29,0x0F }} /* 06 (x1050) */
2646};
2647
2648XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11400x1050_2_V[]=
2649{ /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
2650 {{ 0x28,0x92,0xB6,0x83,0xB5,0xCF,0x81 }}, /* 00 (x350) */
2651 {{ 0x28,0x92,0xD5,0x82,0xD4,0xEE,0x81 }}, /* 01 (x400) */
2652 {{ 0x28,0x92,0xFD,0x8A,0xFC,0x16,0xB1 }}, /* 02 (x480) */
2653 {{ 0x28,0xD4,0x39,0x86,0x57,0x29,0x81 }}, /* 03 (x600) */
2654 {{ 0x28,0xD4,0x8D,0x9A,0xFF,0x29,0xA1 }}, /* 04 (x768) */
2655 {{ 0x28,0x5A,0x0D,0x9A,0xFF,0x29,0xA9 }}, /* 05 (x1024) */
2656 {{ 0x28,0x10,0x1A,0x87,0x19,0x29,0x8F }} /* 06 (x1050) */
2657};
2658
2659XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11600x1200_1_V[]=
2660{
2661 /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A+CR09(5->7) */
2662 {{ 0xd4,0x1F,0x81,0x84,0x5D,0xd5,0x10 }}, /* 00 (x350) */
2663 {{ 0x06,0x3e,0xb3,0x86,0x8F,0x07,0x20 }}, /* 01 (x400) */
2664 {{ 0x56,0xba,0x03,0x86,0xDF,0x57,0x00 }}, /* 02 (x480) */
2665 {{ 0xce,0xF0,0x7b,0x8e,0x57,0xcf,0xa0 }}, /* 03 (x600) */
2666 {{ 0x76,0xF5,0x23,0x86,0xFF,0x77,0x90 }}, /* 04 (x768) */
2667 {{ 0x76,0x5A,0x23,0x86,0xFF,0x77,0x89 }}, /* 05 (x1024) */
2668 {{ 0x90,0x10,0x1A,0x8E,0x19,0x91,0x2F }}, /* 06 (x1050) */
2669 {{ 0x26,0x11,0xd3,0x86,0xaF,0x27,0x3f }} /* 07 (x1200) */
2670};
2671
2672XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11024x768_1_Hx75[]=
2673{ /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
2674 {{ 0x4B,0x27,0x8F,0x32,0x1B,0x00,0x45,0x00 }},/* ; 00 (320x) */
2675 {{ 0x4B,0x27,0x8F,0x2B,0x03,0x00,0x44,0x00 }},/* ; 01 (360x) */
2676 {{ 0x55,0x31,0x99,0x46,0x1D,0x00,0x55,0x00 }},/* ; 02 (400x) */
2677 {{ 0x63,0x3F,0x87,0x4A,0x93,0x00,0x01,0x00 }},/* ; 03 (512x) */
2678 {{ 0x6F,0x4F,0x93,0x54,0x80,0x00,0x05,0x00 }},/* ; 04 (640x) */
2679 {{ 0x6F,0x4F,0x93,0x54,0x80,0x00,0x05,0x00 }},/* ; 05 (720x) */
2680 {{ 0x83,0x63,0x87,0x68,0x14,0x00,0x26,0x00 }},/* ; 06 (800x) */
2681 {{ 0x9F,0x7F,0x83,0x85,0x91,0x00,0x02,0x00 }} /* ; 07 (1024x) */
2682};
2683
2684XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_1_Vx75[]=
2685{ /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A+CR09(5->7) */
2686 {{ 0x97,0x1F,0x60,0x87,0x5D,0x83,0x10 }},/* ; 00 (x350) */
2687 {{ 0xB4,0x1F,0x92,0x89,0x8F,0xB5,0x30 }},/* ; 01 (x400) */
2688 {{ 0xFE,0x1F,0xE0,0x84,0xDF,0xFF,0x10 }},/* ; 02 (x480) */
2689 {{ 0x76,0xF0,0x58,0x8C,0x57,0x77,0xA0 }},/* ; 03 (x600) */
2690 {{ 0x1E,0xF5,0x00,0x83,0xFF,0x1F,0x90 }} /* ; 04 (x768) */
2691};
2692
2693XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11024x768_2_Hx75[]=
2694{ /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
2695 {{ 0x63,0x27,0x87,0x3B,0x8C,0x00,0x01,0x00 }},/* ; 00 (320x) */
2696 {{ 0x63,0x27,0x87,0x3B,0x8C,0x00,0x01,0x00 }},/* ; 01 (360x) */
2697 {{ 0x63,0x31,0x87,0x3D,0x8E,0x00,0x01,0x00 }},/* ; 02 (400x) */
2698 {{ 0x63,0x3F,0x87,0x45,0x96,0x00,0x01,0x00 }},/* ; 03 (512x) */
2699 {{ 0xA3,0x4F,0x87,0x6E,0x9F,0x00,0x06,0x00 }},/* ; 04 (640x) */
2700 {{ 0xA3,0x4F,0x87,0x6E,0x9F,0x00,0x06,0x00 }},/* ; 05 (720x) */
2701 {{ 0xA3,0x63,0x87,0x78,0x89,0x00,0x02,0x00 }},/* ; 06 (800x) */
2702 {{ 0xA3,0x7F,0x87,0x86,0x97,0x00,0x02,0x00 }} /* ; 07 (1024x) */
2703};
2704
2705XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_2_Vx75[]=
2706{ /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
2707 {{ 0x24,0xBB,0x31,0x87,0x5D,0x25,0x30 }},/* ; 00 (x350) */
2708 {{ 0x24,0xBB,0x4A,0x80,0x8F,0x25,0x30 }},/* ; 01 (x400) */
2709 {{ 0x24,0xBB,0x72,0x88,0xDF,0x25,0x30 }},/* ; 02 (x480) */
2710 {{ 0x24,0xF1,0xAE,0x84,0x57,0x25,0xB0 }},/* ; 03 (x600) */
2711 {{ 0x24,0xF5,0x02,0x88,0xFF,0x25,0x90 }} /* ; 04 (x768) */
2712};
2713
2714XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11280x1024_1_Hx75[]=
2715{ /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
2716 {{ 0x56,0x27,0x9A,0x30,0x1E,0x00,0x05,0x00 }},/* ; 00 (320x) */
2717 {{ 0x56,0x27,0x9A,0x30,0x1E,0x00,0x05,0x00 }},/* ; 01 (360x) */
2718 {{ 0x60,0x31,0x84,0x3A,0x88,0x00,0x01,0x00 }},/* ; 02 (400x) */
2719 {{ 0x6E,0x3F,0x92,0x48,0x96,0x00,0x01,0x00 }},/* ; 03 (512x) */
2720 {{ 0x7E,0x4F,0x82,0x54,0x06,0x00,0x06,0x00 }},/* ; 04 (640x) */
2721 {{ 0x7E,0x4F,0x82,0x54,0x06,0x00,0x06,0x00 }},/* ; 05 (720x) */
2722 {{ 0x92,0x63,0x96,0x68,0x1A,0x00,0x06,0x00 }},/* ; 06 (800x) */
2723 {{ 0xAE,0x7F,0x92,0x84,0x96,0x00,0x02,0x00 }},/* ; 07 (1024x) */
2724 {{ 0xCE,0x9F,0x92,0xA5,0x17,0x00,0x07,0x00 }} /* ; 08 (1280x) */
2725};
2726
2727XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_1_Vx75[]=
2728{ /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
2729 {{ 0x86,0xD1,0xBC,0x80,0xBB,0xE5,0x00 }},/* ; 00 (x350) */
2730 {{ 0xB8,0x1F,0x90,0x84,0x8F,0xB9,0x30 }},/* ; 01 (x400) */
2731 {{ 0x08,0x3E,0xE0,0x84,0xDF,0x09,0x00 }},/* ; 02 (x480) */
2732 {{ 0x80,0xF0,0x58,0x8C,0x57,0x81,0xA0 }},/* ; 03 (x600) */
2733 {{ 0x28,0xF5,0x00,0x84,0xFF,0x29,0x90 }},/* ; 04 (x768) */
2734 {{ 0x28,0x5A,0x13,0x87,0xFF,0x29,0xA9 }} /* ; 05 (x1024) */
2735};
2736
2737XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11280x1024_2_Hx75[]=
2738{
2739 /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */
2740 {{ 0x7E,0x3B,0x9A,0x44,0x12,0x00,0x01,0x00 }},/* ; 00 (320x) */
2741 {{ 0x7E,0x3B,0x9A,0x44,0x12,0x00,0x01,0x00 }},/* ; 01 (360x) */
2742 {{ 0x7E,0x40,0x84,0x49,0x91,0x00,0x01,0x00 }},/* ; 02 (400x) */
2743 {{ 0x7E,0x47,0x93,0x50,0x9E,0x00,0x01,0x00 }},/* ; 03 (512x) */
2744 {{ 0xCE,0x77,0x8A,0x80,0x8E,0x00,0x02,0x00 }},/* ; 04 (640x) */
2745 {{ 0xCE,0x77,0x8A,0x80,0x8E,0x00,0x02,0x00 }},/* ; 05 (720x) */
2746 {{ 0xCE,0x81,0x94,0x8A,0x98,0x00,0x02,0x00 }},/* ; 06 (800x) */
2747 {{ 0xCE,0x8F,0x82,0x98,0x06,0x00,0x07,0x00 }},/* ; 07 (1024x) */
2748 {{ 0xCE,0x9F,0x92,0xA8,0x16,0x00,0x07,0x00 }} /* ; 08 (1280x) */
2749};
2750
2751XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_2_Vx75[]=
2752{
2753 /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */
2754 {{ 0x28,0xD2,0xAF,0x83,0xAE,0xD8,0xA1 }},/* ; 00 (x350) */
2755 {{ 0x28,0xD2,0xC8,0x8C,0xC7,0xF2,0x81 }},/* ; 01 (x400) */
2756 {{ 0x28,0xD2,0xF0,0x84,0xEF,0x1A,0xB1 }},/* ; 02 (x480) */
2757 {{ 0x28,0xDE,0x2C,0x8F,0x2B,0x56,0x91 }},/* ; 03 (x600) */
2758 {{ 0x28,0xDE,0x80,0x83,0x7F,0xAA,0x91 }},/* ; 04 (x768) */
2759 {{ 0x28,0x5A,0x13,0x87,0xFF,0x29,0xA9 }} /* ; 05 (x1024) */
2760};
2761
2762XGI_LVDSCRT1DataStruct XGI_CHTVCRT1UNTSC[]=
2763{
2764 {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
2765 0xe8,0x84,0x8f,0x57,0x20,0x00,0x01,0x00 }},
2766 {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
2767 0xd0,0x82,0x5d,0x57,0x00,0x00,0x01,0x00 }},
2768 {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
2769 0xe8,0x84,0x8f,0x57,0x20,0x00,0x01,0x00 }},
2770 {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
2771 0xd0,0x82,0x5d,0x57,0x00,0x00,0x01,0x00 }},
2772 {{0x5d,0x4f,0x81,0x53,0x9c,0x56,0xba,
2773 0x18,0x84,0xdf,0x57,0x00,0x00,0x01,0x00 }},
2774 {{0x80,0x63,0x84,0x6c,0x17,0xec,0xf0,
2775 0x90,0x8c,0x57,0xed,0x20,0x00,0x06,0x01 }}
2776};
2777
2778XGI_LVDSCRT1DataStruct XGI_CHTVCRT1ONTSC[]=
2779{
2780 {{0x64,0x4f,0x88,0x5a,0x9f,0x0b,0x3e,
2781 0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01,0x00 }},
2782 {{0x64,0x4f,0x88,0x5a,0x9f,0x0b,0x3e,
2783 0xb0,0x8d,0x5d,0x0c,0x00,0x00,0x01,0x00 }},
2784 {{0x64,0x4f,0x88,0x5a,0x9f,0x0b,0x3e,
2785 0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01,0x00 }},
2786 {{0x64,0x4f,0x88,0x5a,0x9f,0x0b,0x3e,
2787 0xb0,0x8d,0x5d,0x0c,0x00,0x00,0x01,0x00 }},
2788 {{0x5d,0x4f,0x81,0x56,0x9c,0x0b,0x3e,
2789 0xe8,0x84,0xdf,0x0c,0x00,0x00,0x01,0x00 }},
2790 {{0x7d,0x63,0x81,0x6a,0x16,0xba,0xf0,
2791 0x7f,0x86,0x57,0xbb,0x00,0x00,0x06,0x01 }}
2792};
2793
2794XGI_LVDSCRT1DataStruct XGI_CHTVCRT1UPAL[]=
2795{
2796 {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
2797 0xf8,0x83,0x8f,0x70,0x20,0x00,0x05,0x00 }},
2798 {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
2799 0xde,0x81,0x5d,0x70,0x00,0x00,0x05,0x00 }},
2800 {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
2801 0xf8,0x83,0x8f,0x70,0x20,0x00,0x05,0x00 }},
2802 {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
2803 0xde,0x81,0x5d,0x70,0x00,0x00,0x05,0x00 }},
2804 {{0x64,0x4f,0x88,0x55,0x80,0xec,0xba,
2805 0x50,0x84,0xdf,0xed,0x00,0x00,0x05,0x00 }},
2806 {{0x70,0x63,0x94,0x68,0x8d,0x42,0xf1,
2807 0xc8,0x8c,0x57,0xe9,0x20,0x00,0x05,0x01 }}
2808};
2809
2810XGI_LVDSCRT1DataStruct XGI_CHTVCRT1OPAL[]=
2811{
2812 {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
2813 0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,0x00 }},
2814 {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
2815 0xde,0x81,0x5d,0x70,0x00,0x00,0x05,0x00 }},
2816 {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
2817 0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,0x00 }},
2818 {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
2819 0xde,0x81,0x5d,0x70,0x00,0x00,0x05,0x00 }},
2820 {{0x64,0x4f,0x88,0x55,0x80,0x6f,0xba,
2821 0x20,0x83,0xdf,0x70,0x00,0x00,0x05,0x00 }},
2822 {{0x73,0x63,0x97,0x69,0x8e,0xec,0xf0,
2823 0x90,0x8c,0x57,0xed,0x20,0x00,0x05,0x01 }}
2824};
2825
2826/*add for new UNIVGABIOS*/
2827XGI330_LCDDataTablStruct XGI_LCDDataTable[]=
2828{
2829 {Panel1024x768,0x0019,0x0001,0}, /* XGI_ExtLCD1024x768Data */
2830 {Panel1024x768,0x0019,0x0000,1}, /* XGI_StLCD1024x768Data */
2831 {Panel1024x768,0x0018,0x0010,2}, /* XGI_CetLCD1024x768Data */
2832 {Panel1280x1024,0x0019,0x0001,3}, /* XGI_ExtLCD1280x1024Data */
2833 {Panel1280x1024,0x0019,0x0000,4}, /* XGI_StLCD1280x1024Data */
2834 {Panel1280x1024,0x0018,0x0010,5}, /* XGI_CetLCD1280x1024Data */
2835 {Panel1400x1050,0x0019,0x0001,6}, /* XGI_ExtLCD1400x1050Data */
2836 {Panel1400x1050,0x0019,0x0000,7}, /* XGI_StLCD1400x1050Data */
2837 {Panel1400x1050,0x0018,0x0010,8}, /* XGI_CetLCD1400x1050Data */
2838 {Panel1600x1200,0x0019,0x0001,9}, /* XGI_ExtLCD1600x1200Data */
2839 {Panel1600x1200,0x0019,0x0000,10}, /* XGI_StLCD1600x1200Data */
2840 {PanelRef60Hz,0x0008,0x0008,11}, /* XGI_NoScalingData */
2841 {Panel1024x768x75,0x0019,0x0001,12}, /* XGI_ExtLCD1024x768x75Data */
2842 {Panel1024x768x75,0x0019,0x0000,13}, /* XGI_StLCD1024x768x75Data */
2843 {Panel1024x768x75,0x0018,0x0010,14}, /* XGI_CetLCD1024x768x75Data */
2844 {Panel1280x1024x75,0x0019,0x0001,15}, /* XGI_ExtLCD1280x1024x75Data */
2845 {Panel1280x1024x75,0x0019,0x0000,16}, /* XGI_StLCD1280x1024x75Data */
2846 {Panel1280x1024x75,0x0018,0x0010,17}, /* XGI_CetLCD1280x1024x75Data */
2847 {PanelRef75Hz,0x0008,0x0008,18}, /* XGI_NoScalingDatax75 */
2848 {0xFF,0x0000,0x0000,0} /* End of table */
2849};
2850
2851XGI330_LCDDataTablStruct XGI_LCDDesDataTable[]=
2852{
2853 {Panel1024x768,0x0019,0x0001,0}, /* XGI_ExtLCDDes1024x768Data */
2854 {Panel1024x768,0x0019,0x0000,1}, /* XGI_StLCDDes1024x768Data */
2855 {Panel1024x768,0x0018,0x0010,2}, /* XGI_CetLCDDes1024x768Data */
2856 {Panel1280x1024,0x0019,0x0001,3}, /* XGI_ExtLCDDes1280x1024Data */
2857 {Panel1280x1024,0x0019,0x0000,4}, /* XGI_StLCDDes1280x1024Data */
2858 {Panel1280x1024,0x0018,0x0010,5}, /* XGI_CetLCDDes1280x1024Data */
2859 {Panel1400x1050,0x0019,0x0001,6}, /* XGI_ExtLCDDes1400x1050Data */
2860 {Panel1400x1050,0x0019,0x0000,7}, /* XGI_StLCDDes1400x1050Data */
2861 {Panel1400x1050,0x0418,0x0010,8}, /* XGI_CetLCDDes1400x1050Data */
2862 {Panel1400x1050,0x0418,0x0410,9}, /* XGI_CetLCDDes1400x1050Data2 */
2863 {Panel1600x1200,0x0019,0x0001,10}, /* XGI_ExtLCDDes1600x1200Data */
2864 {Panel1600x1200,0x0019,0x0000,11}, /* XGI_StLCDDes1600x1200Data */
2865 {PanelRef60Hz,0x0008,0x0008,12}, /* XGI_NoScalingDesData */
2866 {Panel1024x768x75,0x0019,0x0001,13}, /* XGI_ExtLCDDes1024x768x75Data */
2867 {Panel1024x768x75,0x0019,0x0000,14}, /* XGI_StLCDDes1024x768x75Data */
2868 {Panel1024x768x75,0x0018,0x0010,15}, /* XGI_CetLCDDes1024x768x75Data */
2869 {Panel1280x1024x75,0x0019,0x0001,16}, /* XGI_ExtLCDDes1280x1024x75Data */
2870 {Panel1280x1024x75,0x0019,0x0000,17}, /* XGI_StLCDDes1280x1024x75Data */
2871 {Panel1280x1024x75,0x0018,0x0010,18}, /* XGI_CetLCDDes1280x1024x75Data */
2872 {PanelRef75Hz,0x0008,0x0008,19}, /* XGI_NoScalingDesDatax75 */
2873 {0xFF,0x0000,0x0000,0}
2874};
2875
2876XGI330_LCDDataTablStruct XGI_EPLLCDCRT1Ptr_H[]=
2877{
2878 {Panel1024x768,0x0018,0x0000,0}, /* XGI_LVDSCRT11024x768_1_H */
2879 {Panel1024x768,0x0018,0x0010,1}, /* XGI_LVDSCRT11024x768_2_H */
2880 {Panel1280x1024,0x0018,0x0000,2}, /* XGI_LVDSCRT11280x1024_1_H */
2881 {Panel1280x1024,0x0018,0x0010,3}, /* XGI_LVDSCRT11280x1024_2_H */
2882 {Panel1400x1050,0x0018,0x0000,4}, /* XGI_LVDSCRT11400x1050_1_H */
2883 {Panel1400x1050,0x0018,0x0010,5}, /* XGI_LVDSCRT11400x1050_2_H */
2884 {Panel1600x1200,0x0018,0x0000,6}, /* XGI_LVDSCRT11600x1200_1_H */
2885 {Panel1024x768x75,0x0018,0x0000,7}, /* XGI_LVDSCRT11024x768_1_Hx75 */
2886 {Panel1024x768x75,0x0018,0x0010,8}, /* XGI_LVDSCRT11024x768_2_Hx75 */
2887 {Panel1280x1024x75,0x0018,0x0000,9}, /* XGI_LVDSCRT11280x1024_1_Hx75 */
2888 {Panel1280x1024x75,0x0018,0x0010,10}, /* XGI_LVDSCRT11280x1024_2_Hx75 */
2889 {0xFF,0x0000,0x0000,0}
2890};
2891
2892XGI330_LCDDataTablStruct XGI_EPLLCDCRT1Ptr_V[]=
2893{
2894 {Panel1024x768,0x0018,0x0000,0}, /* XGI_LVDSCRT11024x768_1_V */
2895 {Panel1024x768,0x0018,0x0010,1}, /* XGI_LVDSCRT11024x768_2_V */
2896 {Panel1280x1024,0x0018,0x0000,2}, /* XGI_LVDSCRT11280x1024_1_V */
2897 {Panel1280x1024,0x0018,0x0010,3}, /* XGI_LVDSCRT11280x1024_2_V */
2898 {Panel1400x1050,0x0018,0x0000,4}, /* XGI_LVDSCRT11400x1050_1_V */
2899 {Panel1400x1050,0x0018,0x0010,5}, /* XGI_LVDSCRT11400x1050_2_V */
2900 {Panel1600x1200,0x0018,0x0000,6}, /* XGI_LVDSCRT11600x1200_1_V */
2901 {Panel1024x768x75,0x0018,0x0000,7}, /* XGI_LVDSCRT11024x768_1_Vx75 */
2902 {Panel1024x768x75,0x0018,0x0010,8}, /* XGI_LVDSCRT11024x768_2_Vx75 */
2903 {Panel1280x1024x75,0x0018,0x0000,9}, /* XGI_LVDSCRT11280x1024_1_Vx75 */
2904 {Panel1280x1024x75,0x0018,0x0010,10}, /* XGI_LVDSCRT11280x1024_2_Vx75 */
2905 {0xFF,0x0000,0x0000,0}
2906};
2907
2908XGI330_LCDDataTablStruct XGI_EPLLCDDataPtr[]=
2909{
2910 {Panel1024x768,0x0018,0x0000,0}, /* XGI_LVDS1024x768Data_1 */
2911 {Panel1024x768,0x0018,0x0010,1}, /* XGI_LVDS1024x768Data_2 */
2912 {Panel1280x1024,0x0018,0x0000,2}, /* XGI_LVDS1280x1024Data_1 */
2913 {Panel1280x1024,0x0018,0x0010,3}, /* XGI_LVDS1280x1024Data_2 */
2914 {Panel1400x1050,0x0018,0x0000,4}, /* XGI_LVDS1400x1050Data_1 */
2915 {Panel1400x1050,0x0018,0x0010,5}, /* XGI_LVDS1400x1050Data_2 */
2916 {Panel1600x1200,0x0018,0x0000,6}, /* XGI_LVDS1600x1200Data_1 */
2917 {PanelRef60Hz,0x0008,0x0008,7}, /* XGI_LVDSNoScalingData */
2918 {Panel1024x768x75,0x0018,0x0000,8}, /* XGI_LVDS1024x768Data_1x75 */
2919 {Panel1024x768x75,0x0018,0x0010,9}, /* XGI_LVDS1024x768Data_2x75 */
2920 {Panel1280x1024x75,0x0018,0x0000,10}, /* XGI_LVDS1280x1024Data_1x75 */
2921 {Panel1280x1024x75,0x0018,0x0010,11}, /* XGI_LVDS1280x1024Data_2x75 */
2922 {PanelRef75Hz,0x0008,0x0008,12}, /* XGI_LVDSNoScalingDatax75 */
2923 {0xFF,0x0000,0x0000,0}
2924};
2925
2926XGI330_LCDDataTablStruct XGI_EPLLCDDesDataPtr[]=
2927{
2928 {Panel1024x768,0x0018,0x0000,0}, /* XGI_LVDS1024x768Des_1 */
2929 {Panel1024x768,0x0618,0x0410,1}, /* XGI_LVDS1024x768Des_3 */
2930 {Panel1024x768,0x0018,0x0010,2}, /* XGI_LVDS1024x768Des_2 */
2931 {Panel1280x1024,0x0018,0x0000,3}, /* XGI_LVDS1280x1024Des_1 */
2932 {Panel1280x1024,0x0018,0x0010,4}, /* XGI_LVDS1280x1024Des_2 */
2933 {Panel1400x1050,0x0018,0x0000,5}, /* XGI_LVDS1400x1050Des_1 */
2934 {Panel1400x1050,0x0018,0x0010,6}, /* XGI_LVDS1400x1050Des_2 */
2935 {Panel1600x1200,0x0018,0x0000,7}, /* XGI_LVDS1600x1200Des_1 */
2936 {PanelRef60Hz,0x0008,0x0008,8}, /* XGI_LVDSNoScalingDesData */
2937 {Panel1024x768x75,0x0018,0x0000,9}, /* XGI_LVDS1024x768Des_1x75 */
2938 {Panel1024x768x75,0x0618,0x0410,10}, /* XGI_LVDS1024x768Des_3x75 */
2939 {Panel1024x768x75,0x0018,0x0010,11}, /* XGI_LVDS1024x768Des_2x75 */
2940 {Panel1280x1024x75,0x0018,0x0000,12}, /* XGI_LVDS1280x1024Des_1x75 */
2941 {Panel1280x1024x75,0x0018,0x0010,13}, /* XGI_LVDS1280x1024Des_2x75 */
2942 {PanelRef75Hz,0x0008,0x0008,14}, /* XGI_LVDSNoScalingDesDatax75 */
2943 {0xFF,0x0000,0x0000,0}
2944};
2945
2946XGI330_LCDDataTablStruct XGI_EPLCHLCDRegPtr[]=
2947{
2948 {Panel1024x768,0x0000,0x0000,0}, /* XGI_CH7017LV1024x768 */
2949 {Panel1400x1050,0x0000,0x0000,1}, /* XGI_CH7017LV1400x1050 */
2950 {0xFF,0x0000,0x0000,0}
2951};
2952
2953XGI330_TVDataTablStruct XGI_TVDataTable[]=
2954{
2955 {0x09E1,0x0001,0}, /* XGI_ExtPALData */
2956 {0x09E1,0x0000,1}, /* XGI_ExtNTSCData */
2957 {0x09E1,0x0801,2}, /* XGI_StPALData */
2958 {0x09E1,0x0800,3}, /* XGI_StNTSCData */
2959 {0x49E0,0x0100,4}, /* XGI_ExtHiTVData */
2960 {0x49E0,0x4100,5}, /* XGI_St2HiTVData */
2961 {0x49E0,0x4900,13}, /* XGI_St1HiTVData */
2962 {0x09E0,0x0020,6}, /* XGI_ExtYPbPr525iData */
2963 {0x09E0,0x0040,7}, /* XGI_ExtYPbPr525pData */
2964 {0x09E0,0x0080,8}, /* XGI_ExtYPbPr750pData */
2965 {0x09E0,0x0820,9}, /* XGI_StYPbPr525iData */
2966 {0x09E0,0x0840,10}, /* XGI_StYPbPr525pData */
2967 {0x09E0,0x0880,11}, /* XGI_StYPbPr750pData */
2968 {0xffff,0x0000,12} /* END */
2969};
2970
2971USHORT TVLenList[]=
2972{
2973 LVDSCRT1Len_H,
2974 LVDSCRT1Len_V,
2975 LVDSDataLen,
2976 0,
2977 TVDataLen,
2978 0,
2979 0,
2980 CHTVRegLen
2981} ;
2982
2983/* Chrontel 7017 TV CRT1 Timing List */
2984XGI330_TVDataTablStruct XGI_EPLCHTVCRT1Ptr[]=
2985{
2986 {0x0011,0x0000,0}, /* XGI_CHTVCRT1UNTSC */
2987 {0x0011,0x0010,1}, /* XGI_CHTVCRT1ONTSC */
2988 {0x0011,0x0001,2}, /* XGI_CHTVCRT1UPAL */
2989 {0x0011,0x0011,3}, /* XGI_CHTVCRT1OPAL */
2990 {0xFFFF,0x0000,4}
2991};
2992
2993/* ;;Chrontel 7017 TV Timing List */
2994XGI330_TVDataTablStruct XGI_EPLCHTVDataPtr[]=
2995{
2996 {0x0011,0x0000,0}, /* XGI_CHTVUNTSCData */
2997 {0x0011,0x0010,1}, /* XGI_CHTVONTSCData */
2998 {0x0011,0x0001,2}, /* XGI_CHTVUPALData */
2999 {0x0011,0x0011,3}, /* XGI_CHTVOPALData */
3000 {0xFFFF,0x0000,4}
3001};
3002
3003/* ;;Chrontel 7017 TV Reg. List */
3004XGI330_TVDataTablStruct XGI_EPLCHTVRegPtr[]=
3005{
3006 {0x0011,0x0000,0}, /* XGI_CHTVRegUNTSC */
3007 {0x0011,0x0010,1}, /* XGI_CHTVRegONTSC */
3008 {0x0011,0x0001,2}, /* XGI_CHTVRegUPAL */
3009 {0x0011,0x0011,3}, /* XGI_CHTVRegOPAL */
3010 {0xFFFF,0x0000,4}
3011};
3012
3013USHORT LCDLenList[]=
3014{
3015 LVDSCRT1Len_H,
3016 LVDSCRT1Len_V,
3017 LVDSDataLen,
3018 LCDDesDataLen,
3019 LCDDataLen,
3020 LCDDesDataLen,
3021 0,
3022 LCDDesDataLen,
3023 LCDDesDataLen,
3024 0
3025} ;
3026
3027XGI330_LCDCapStruct XGI660_LCDDLCapList[]= /* 660, Dual link */
3028{
3029/* LCDCap1024x768 */
3030 {Panel1024x768, DefaultLCDCap, 0, 0x014, 0x88, 0x06, VCLK65,
3031 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00,
3032 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10},
3033/* LCDCap1280x1024 */
3034 {Panel1280x1024, LCDDualLink+DefaultLCDCap, StLCDBToA, 0x053, 0x70, 0x03, VCLK108_2,
3035 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00,
3036 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
3037/* LCDCap1400x1050 */
3038 {Panel1400x1050, LCDDualLink+DefaultLCDCap, StLCDBToA, 0x053, 0x70, 0x03, VCLK108_2,
3039 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00,
3040 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
3041/* LCDCap1600x1200 */
3042 {Panel1600x1200, LCDDualLink+DefaultLCDCap, LCDToFull, 0x053, 0xC0, 0x03, VCLK162,
3043 0x43, 0x22, 0x70, 0x24, 0x02, 0x14, 0x0A, 0x02, 0x00,
3044 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
3045/* LCDCap1024x768x75 */
3046 {Panel1024x768x75, DefaultLCDCap, 0, 0x014, 0x60, 0, VCLK78_75,
3047 0x2B, 0x61, 0x2B, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00,
3048 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10},
3049/* LCDCap1280x1024x75 */
3050 {Panel1280x1024x75, LCDDualLink+DefaultLCDCap, StLCDBToA, 0x053, 0x90, 0x03, VCLK135_5,
3051 0x54, 0x42, 0x4A, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00,
3052 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
3053/* LCDCapDefault */
3054 {0xFF, DefaultLCDCap, 0, 0x053, 0x88, 0x06, VCLK65,
3055 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00,
3056 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}
3057};
3058
3059XGI330_LCDCapStruct XGI_LCDDLCapList[]= /* Dual link only */
3060{
3061/* LCDCap1024x768 */
3062 {Panel1024x768, DefaultLCDCap, 0, 0x012, 0x88, 0x06, VCLK65,
3063 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00,
3064 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10},
3065/* LCDCap1280x1024 */
3066 {Panel1280x1024, LCDDualLink+DefaultLCDCap, StLCDBToA, 0x012, 0x70, 0x03, VCLK108_2,
3067 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00,
3068 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
3069/* LCDCap1400x1050 */
3070 {Panel1400x1050, LCDDualLink+DefaultLCDCap, StLCDBToA, 0x012, 0x70, 0x03, VCLK108_2,
3071 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00,
3072 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
3073/* LCDCap1600x1200 */
3074 {Panel1600x1200, LCDDualLink+DefaultLCDCap, LCDToFull, 0x012, 0xC0, 0x03, VCLK162,
3075 0x43, 0x22, 0x70, 0x24, 0x02, 0x14, 0x0A, 0x02, 0x00,
3076 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
3077/* LCDCap1024x768x75 */
3078 {Panel1024x768x75, DefaultLCDCap, 0, 0x012, 0x60, 0, VCLK78_75,
3079 0x2B, 0x61, 0x2B, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00,
3080 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10},
3081/* LCDCap1280x1024x75 */
3082 {Panel1280x1024x75, LCDDualLink+DefaultLCDCap, StLCDBToA, 0x012, 0x90, 0x03, VCLK135_5,
3083 0x54, 0x42, 0x4A, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00,
3084 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
3085/* LCDCapDefault */
3086 {0xFF, DefaultLCDCap, 0, 0x012, 0x88, 0x06, VCLK65,
3087 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00,
3088 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}
3089};
3090
3091XGI330_LCDCapStruct XGI660_LCDCapList[]=
3092{
3093/* LCDCap1024x768 */
3094 {Panel1024x768, DefaultLCDCap, 0, 0x014, 0x88, 0x06, VCLK65,
3095 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00,
3096 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10},
3097/* LCDCap1280x1024 */
3098 {Panel1280x1024, DefaultLCDCap, StLCDBToA, 0x053, 0x70, 0x03, VCLK108_2,
3099 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00,
3100 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
3101/* LCDCap1400x1050 */
3102 {Panel1400x1050, DefaultLCDCap, StLCDBToA, 0x053, 0x70, 0x03, VCLK108_2,
3103 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00,
3104 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
3105/* LCDCap1600x1200 */
3106 {Panel1600x1200, DefaultLCDCap, LCDToFull, 0x053, 0xC0, 0x03, VCLK162,
3107 0x5A, 0x23, 0x5A, 0x23, 0x02, 0x14, 0x0A, 0x02, 0x00,
3108 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
3109/* LCDCap1024x768x75 */
3110 {Panel1024x768x75, DefaultLCDCap, 0, 0x014, 0x60, 0, VCLK78_75,
3111 0x2B, 0x61, 0x2B, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00,
3112 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10},
3113/* LCDCap1280x1024x75 */
3114 {Panel1280x1024x75,+DefaultLCDCap, StLCDBToA, 0x053, 0x90, 0x03, VCLK135_5,
3115 0x54, 0x42, 0x4A, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00,
3116 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
3117/* LCDCapDefault */
3118 {0xFF, DefaultLCDCap, 0, 0x053, 0x88, 0x06, VCLK65,
3119 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00,
3120 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}
3121};
3122
3123XGI330_LCDCapStruct XGI_LCDCapList[]=
3124{
3125/* LCDCap1024x768 */
3126 {Panel1024x768, DefaultLCDCap, 0, 0x012, 0x88, 0x06, VCLK65,
3127 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00,
3128 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10},
3129/* LCDCap1280x1024 */
3130 {Panel1280x1024, DefaultLCDCap, StLCDBToA, 0x012, 0x70, 0x03, VCLK108_2,
3131 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00,
3132 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
3133/* LCDCap1400x1050 */
3134 {Panel1400x1050, DefaultLCDCap, StLCDBToA, 0x012, 0x70, 0x03, VCLK108_2,
3135 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00,
3136 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
3137/* LCDCap1600x1200 */
3138 {Panel1600x1200, DefaultLCDCap, LCDToFull, 0x012, 0xC0, 0x03, VCLK162,
3139 0x5A, 0x23, 0x5A, 0x23, 0x02, 0x14, 0x0A, 0x02, 0x00,
3140 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
3141/* LCDCap1024x768x75 */
3142 {Panel1024x768x75, DefaultLCDCap, 0, 0x012, 0x60, 0, VCLK78_75,
3143 0x2B, 0x61, 0x2B, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00,
3144 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10},
3145/* LCDCap1280x1024x75 */
3146 {Panel1280x1024x75, DefaultLCDCap, StLCDBToA, 0x012, 0x90, 0x03, VCLK135_5,
3147 0x54, 0x42, 0x4A, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00,
3148 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10},
3149/* LCDCapDefault */
3150 {0xFF, DefaultLCDCap, 0, 0x012, 0x88, 0x06, VCLK65,
3151 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00,
3152 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}
3153};
3154
3155XGI21_LVDSCapStruct XGI21_LCDCapList[]=
3156{
3157 {DisableLCD24bpp + LCDPolarity,
3158 2160,1250,1600,1200, 64, 1, 192, 3,
3159 0x70,0x24,0x20,0x04,0x0A,0x02,0xC8
3160 },
3161 {DisableLCD24bpp + LCDPolarity,
3162 1688,1066,1280,1024, 48, 1, 112, 3,
3163 0x70,0x44,0x20,0x04,0x0A,0x02,0xC8
3164 },
3165 {DisableLCD24bpp + LCDPolarity + (LCDPolarity << 8),
3166 1344, 806,1024, 768, 24, 3, 136, 6,
3167 0x6C,0x65,0x20,0x04,0x0A,0x02,0xC8
3168 },
3169 {DisableLCD24bpp + LCDPolarity,
3170 1056, 628, 800, 600, 40, 1, 128, 4,
3171 0x42,0xE2,0x20,0x14,0x0A,0x02,0x00
3172 },
3173 {DisableLCD24bpp + LCDPolarity,
3174 928, 525, 800, 480, 40, 13, 48, 3,
3175 0x52,0xC5,0x20,0x14,0x0A,0x02,0x00
3176 },
3177 {DisableLCD24bpp + LCDPolarity + (LCDPolarity << 8),
3178 800, 525, 640, 480, 16, 10, 96, 2,
3179 0x1B,0xE1,0x20,0x04,0x0A,0x02,0xC8
3180 }
3181
3182};
3183
3184XGI_Ext2Struct XGI330_RefIndex[]=
3185{
3186{Support32Bpp + SupportAllCRT2 + SyncPN, RES320x200, VCLK25_175, 0x00,0x10,0x59, 320, 200},/* 00 */
3187{Support32Bpp + SupportAllCRT2 + SyncPN, RES320x200, VCLK25_175, 0x00,0x10,0x00, 320, 400},/* 01 */
3188{Support32Bpp + SupportAllCRT2 + SyncNN, RES320x240, VCLK25_175, 0x04,0x20,0x50, 320, 240},/* 02 */
3189{Support32Bpp + SupportAllCRT2 + SyncPP, RES400x300, VCLK40, 0x05,0x32,0x51, 400, 300},/* 03 */
3190{Support32Bpp + NoSupportTV + SyncNN + SupportTV1024, RES512x384, VCLK65, 0x06,0x43,0x52, 512, 384},/* 04 */
3191{Support32Bpp + SupportAllCRT2 + SyncPN, RES640x400, VCLK25_175, 0x00,0x14,0x2f, 640, 400},/* 05 */
3192{Support32Bpp + SupportAllCRT2 + SyncNN, RES640x480x60, VCLK25_175, 0x04,0x24,0x2e, 640, 480},/* 06 640x480x60Hz (LCD 640x480x60z) */
3193{Support32Bpp + NoSupportHiVisionTV + SyncNN, RES640x480x72, VCLK31_5, 0x04,0x24,0x2e, 640, 480},/* 07 640x480x72Hz (LCD 640x480x70Hz) */
3194{Support32Bpp + NoSupportHiVisionTV + SyncNN, RES640x480x75, VCLK31_5, 0x47,0x24,0x2e, 640, 480},/* 08 640x480x75Hz (LCD 640x480x75Hz) */
3195{Support32Bpp + SupportRAMDAC2 + SyncNN, RES640x480x85, VCLK36, 0x8A,0x24,0x2e, 640, 480},/* 09 640x480x85Hz */
3196{Support32Bpp + SupportRAMDAC2 + SyncPN, RES640x480x100, VCLK43_163, 0x00,0x24,0x2e, 640, 480},/* 0a 640x480x100Hz */
3197{Support32Bpp + SupportRAMDAC2 + SyncPN, RES640x480x120, VCLK52_406, 0x00,0x24,0x2e, 640, 480},/* 0b 640x480x120Hz */
3198{Support32Bpp + SupportRAMDAC2 + SyncPN, RES640x480x160, VCLK72_852, 0x00,0x24,0x2e, 640, 480},/* 0c 640x480x160Hz */
3199{Support32Bpp + SupportRAMDAC2 + SyncNN, RES640x480x200, VCLK86_6, 0x00,0x24,0x2e, 640, 480},/* 0d 640x480x200Hz */
3200{Support32Bpp + NoSupportLCD + SyncPP, RES800x600x56, VCLK36, 0x05,0x36,0x6a, 800, 600},/* 0e 800x600x56Hz */
3201{Support32Bpp + NoSupportTV + SyncPP, RES800x600x60, VCLK40, 0x05,0x36,0x6a, 800, 600},/* 0f 800x600x60Hz (LCD 800x600x60Hz) */
3202{Support32Bpp + NoSupportHiVisionTV + SyncPP, RES800x600x72, VCLK50, 0x48,0x36,0x6a, 800, 600},/* 10 800x600x72Hz (LCD 800x600x70Hz) */
3203{Support32Bpp + NoSupportHiVisionTV + SyncPP, RES800x600x75, VCLK49_5, 0x8B,0x36,0x6a, 800, 600},/* 11 800x600x75Hz (LCD 800x600x75Hz) */
3204{Support32Bpp + SupportRAMDAC2 + SyncPP, RES800x600x85, VCLK56_25, 0x00,0x36,0x6a, 800, 600},/* 12 800x600x85Hz */
3205{Support32Bpp + SupportRAMDAC2 + SyncPN, RES800x600x100, VCLK68_179, 0x00,0x36,0x6a, 800, 600},/* 13 800x600x100Hz */
3206{Support32Bpp + SupportRAMDAC2 + SyncPN, RES800x600x120, VCLK83_95, 0x00,0x36,0x6a, 800, 600},/* 14 800x600x120Hz */
3207{Support32Bpp + SupportRAMDAC2 + SyncPN, RES800x600x160, VCLK116_406,0x00,0x36,0x6a, 800, 600},/* 15 800x600x160Hz */
3208{Support32Bpp + InterlaceMode + SyncPP, RES1024x768x43, VCLK44_9, 0x00,0x47,0x37,1024, 768},/* 16 1024x768x43Hz */
3209{Support32Bpp + NoSupportTV + SyncNN + SupportTV1024, RES1024x768x60, VCLK65, 0x06,0x47,0x37,1024, 768},/* 17 1024x768x60Hz (LCD 1024x768x60Hz) */
3210{Support32Bpp + NoSupportHiVisionTV + SyncNN, RES1024x768x70, VCLK75, 0x49,0x47,0x37,1024, 768},/* 18 1024x768x70Hz (LCD 1024x768x70Hz) */
3211{Support32Bpp + NoSupportHiVisionTV + SyncPP, RES1024x768x75, VCLK78_75, 0x00,0x47,0x37,1024, 768},/* 19 1024x768x75Hz (LCD 1024x768x75Hz) */
3212{Support32Bpp + SupportRAMDAC2 + SyncPP, RES1024x768x85, VCLK94_5, 0x8C,0x47,0x37,1024, 768},/* 1a 1024x768x85Hz */
3213{Support32Bpp + SupportRAMDAC2 + SyncPN, RES1024x768x100, VCLK113_309,0x00,0x47,0x37,1024, 768},/* 1b 1024x768x100Hz */
3214{Support32Bpp + SupportRAMDAC2 + SyncPN, RES1024x768x120, VCLK139_054,0x00,0x47,0x37,1024, 768},/* 1c 1024x768x120Hz */
3215{Support32Bpp + SupportLCD + SyncPP, RES1280x960x60, VCLK108_2, 0x08,0x58,0x7b,1280, 960},/* 1d 1280x960x60Hz */
3216{Support32Bpp + InterlaceMode + SyncPP, RES1280x1024x43, VCLK78_75, 0x00,0x58,0x3a,1280,1024},/* 1e 1280x1024x43Hz */
3217{Support32Bpp + NoSupportTV + SyncPP, RES1280x1024x60, VCLK108_2, 0x07,0x58,0x3a,1280,1024},/* 1f 1280x1024x60Hz (LCD 1280x1024x60Hz) */
3218{Support32Bpp + NoSupportTV + SyncPP, RES1280x1024x75, VCLK135_5, 0x00,0x58,0x3a,1280,1024},/* 20 1280x1024x75Hz (LCD 1280x1024x75Hz) */
3219{Support32Bpp + SyncPP, RES1280x1024x85, VCLK157_5, 0x00,0x58,0x3a,1280,1024},/* 21 1280x1024x85Hz */
3220{Support32Bpp + SupportLCD + SyncPP + SupportCRT2in301C, RES1600x1200x60, VCLK162, 0x09,0x7A,0x3c,1600,1200},/* 22 1600x1200x60Hz */
3221{Support32Bpp + SyncPP + SupportCRT2in301C, RES1600x1200x65, VCLK175, 0x00,0x69,0x3c,1600,1200},/* 23 1600x1200x65Hz */
3222{Support32Bpp + SyncPP + SupportCRT2in301C, RES1600x1200x70, VCLK189, 0x00,0x69,0x3c,1600,1200},/* 24 1600x1200x70Hz */
3223{Support32Bpp + SyncPP + SupportCRT2in301C, RES1600x1200x75, VCLK202_5, 0x00,0x69,0x3c,1600,1200},/* 25 1600x1200x75Hz */
3224{Support32Bpp + SyncPP, RES1600x1200x85, VCLK229_5, 0x00,0x69,0x3c,1600,1200},/* 26 1600x1200x85Hz */
3225{Support32Bpp + SyncPP, RES1600x1200x100,VCLK269_655,0x00,0x69,0x3c,1600,1200},/* 27 1600x1200x100Hz */
3226{Support32Bpp + SyncPP, RES1600x1200x120,VCLK323_586,0x00,0x69,0x3c,1600,1200},/* 28 1600x1200x120Hz */
3227{Support32Bpp + SupportLCD + SyncNP, RES1920x1440x60, VCLK234, 0x00,0x00,0x68,1920,1440},/* 29 1920x1440x60Hz */
3228{Support32Bpp + SyncPN, RES1920x1440x65, VCLK254_817,0x00,0x00,0x68,1920,1440},/* 2a 1920x1440x65Hz */
3229{Support32Bpp + SyncPN, RES1920x1440x70, VCLK277_015,0x00,0x00,0x68,1920,1440},/* 2b 1920x1440x70Hz */
3230{Support32Bpp + SyncPN, RES1920x1440x75, VCLK291_132,0x00,0x00,0x68,1920,1440},/* 2c 1920x1440x75Hz */
3231{Support32Bpp + SyncPN, RES1920x1440x85, VCLK330_615,0x00,0x00,0x68,1920,1440},/* 2d 1920x1440x85Hz */
3232{Support16Bpp + SyncPN, RES1920x1440x100,VCLK388_631,0x00,0x00,0x68,1920,1440},/* 2e 1920x1440x100Hz */
3233{Support32Bpp + SupportLCD + SyncPN, RES2048x1536x60, VCLK266_952,0x00,0x00,0x6c,2048,1536},/* 2f 2048x1536x60Hz */
3234{Support32Bpp + SyncPN, RES2048x1536x65, VCLK291_766,0x00,0x00,0x6c,2048,1536},/* 30 2048x1536x65Hz */
3235{Support32Bpp + SyncPN, RES2048x1536x70, VCLK315_195,0x00,0x00,0x6c,2048,1536},/* 31 2048x1536x70Hz */
3236{Support32Bpp + SyncPN, RES2048x1536x75, VCLK340_477,0x00,0x00,0x6c,2048,1536},/* 32 2048x1536x75Hz */
3237{Support16Bpp + SyncPN, RES2048x1536x85, VCLK375_847,0x00,0x00,0x6c,2048,1536},/* 33 2048x1536x85Hz */
3238{Support32Bpp + SupportHiVisionTV + SupportRAMDAC2 + SyncPP + SupportYPbPr, RES800x480x60, VCLK39_77, 0x08,0x00,0x70, 800, 480},/* 34 800x480x60Hz */
3239{Support32Bpp + SupportRAMDAC2 + SyncPP, RES800x480x75, VCLK49_5, 0x08,0x00,0x70, 800, 480},/* 35 800x480x75Hz */
3240{Support32Bpp + SupportRAMDAC2 + SyncPP, RES800x480x85, VCLK56_25, 0x08,0x00,0x70, 800, 480},/* 36 800x480x85Hz */
3241{Support32Bpp + SupportHiVisionTV + SupportRAMDAC2 + SyncPP + SupportYPbPr, RES1024x576x60, VCLK65, 0x09,0x00,0x71,1024, 576},/* 37 1024x576x60Hz */
3242{Support32Bpp + SupportRAMDAC2 + SyncPP, RES1024x576x75, VCLK78_75, 0x09,0x00,0x71,1024, 576},/* 38 1024x576x75Hz */
3243{Support32Bpp + SupportRAMDAC2 + SyncPP, RES1024x576x85, VCLK94_5, 0x09,0x00,0x71,1024, 576},/* 39 1024x576x85Hz */
3244{Support32Bpp + SupportHiVisionTV + SupportRAMDAC2 + SyncPP + SupportYPbPr, RES1280x720x60, VCLK108_2, 0x0A,0x00,0x75,1280, 720},/* 3a 1280x720x60Hz */
3245{Support32Bpp + SupportRAMDAC2 + SyncPP, RES1280x720x75, VCLK135_5, 0x0A,0x00,0x75,1280, 720},/* 3b 1280x720x75Hz */
3246{Support32Bpp + SupportRAMDAC2 + SyncPP, RES1280x720x85, VCLK157_5, 0x0A,0x00,0x75,1280, 720},/* 3c 1280x720x85Hz */
3247{Support32Bpp + SupportTV + SyncNN, RES720x480x60, VCLK28_322, 0x06,0x00,0x31, 720, 480},/* 3d 720x480x60Hz */
3248{Support32Bpp + SupportTV + SyncPP, RES720x576x56, VCLK36, 0x06,0x00,0x32, 720, 576},/* 3e 720x576x56Hz */
3249{Support32Bpp + InterlaceMode + NoSupportLCD + SyncPP, RES856x480x79I, VCLK35_2, 0x00,0x00,0x00, 856, 480},/* 3f 856x480x79I */
3250{Support32Bpp + NoSupportLCD + SyncNN, RES856x480x60, VCLK35_2, 0x00,0x00,0x00, 856, 480},/* 40 856x480x60Hz */
3251{Support32Bpp + NoSupportHiVisionTV + SyncPP, RES1280x768x60, VCLK79_411, 0x08,0x48,0x23,1280, 768},/* 41 1280x768x60Hz */
3252{Support32Bpp + NoSupportHiVisionTV + SyncPP, RES1400x1050x60, VCLK122_61, 0x08,0x69,0x26,1400,1050},/* 42 1400x1050x60Hz */
3253{Support32Bpp + SupportRAMDAC2 + SyncPP, RES1152x864x60, VCLK80_350, 0x37,0x00,0x20,1152, 864},/* 43 1152x864x60Hz */
3254{Support32Bpp + SupportRAMDAC2 + SyncPP, RES1152x864x75, VCLK107_385,0x37,0x00,0x20,1152, 864},/* 44 1152x864x75Hz */
3255{Support32Bpp + SupportLCD + SupportRAMDAC2 + SyncPP, RES1280x960x75, VCLK125_999,0x3A,0x88,0x7b,1280, 960},/* 45 1280x960x75Hz */
3256{Support32Bpp + SupportLCD + SupportRAMDAC2 + SyncPP, RES1280x960x85, VCLK148_5, 0x0A,0x88,0x7b,1280, 960},/* 46 1280x960x85Hz */
3257{Support32Bpp + SupportLCD + SupportRAMDAC2 + SyncPP, RES1280x960x120, VCLK217_325,0x3A,0x88,0x7b,1280, 960},/* 47 1280x960x120Hz */
3258{Support32Bpp + SupportRAMDAC2 + SyncPN, RES1024x768x160, VCLK139_054,0x30,0x47,0x37,1024, 768},/* 48 1024x768x160Hz */
3259};
3260
3261
3262
3263XGI330_VCLKDataStruct XGI330_VCLKData[]=
3264{
3265 { 0x1b,0xe1, 25}, /* 0x0 */
3266 { 0x4e,0xe4, 28}, /* 0x1 */
3267 { 0x57,0xe4, 31}, /* 0x2 */
3268 { 0xc3,0xc8, 36}, /* 0x3 */
3269 { 0x42,0xe2, 40}, /* 0x4 */
3270 { 0xfe,0xcd, 43}, /* 0x5 */
3271 { 0x5d,0xc4, 44}, /* 0x6 */
3272 { 0x52,0xe2, 49}, /* 0x7 */
3273 { 0x53,0xe2, 50}, /* 0x8 */
3274 { 0x74,0x67, 52}, /* 0x9 */
3275 { 0x6d,0x66, 56}, /* 0xa */
3276 { 0x6c,0xc3, 65}, /* 0xb */
3277 { 0x46,0x44, 67}, /* 0xc */
3278 { 0xb1,0x46, 68}, /* 0xd */
3279 { 0xd3,0x4a, 72}, /* 0xe */
3280 { 0x29,0x61, 75}, /* 0xf */
3281 { 0x6e,0x46, 76}, /* 0x10 */
3282 { 0x2b,0x61, 78}, /* 0x11 */
3283 { 0x31,0x42, 79}, /* 0x12 */
3284 { 0xab,0x44, 83}, /* 0x13 */
3285 { 0x46,0x25, 84}, /* 0x14 */
3286 { 0x78,0x29, 86}, /* 0x15 */
3287 { 0x62,0x44, 94}, /* 0x16 */
3288 { 0x2b,0x41,104}, /* 0x17 */
3289 { 0x3a,0x23,105}, /* 0x18 */
3290 { 0x70,0x44,108}, /* 0x19 */
3291 { 0x3c,0x23,109}, /* 0x1a */
3292 { 0x5e,0x43,113}, /* 0x1b */
3293 { 0xbc,0x44,116}, /* 0x1c */
3294 { 0xe0,0x46,132}, /* 0x1d */
3295 { 0x54,0x42,135}, /* 0x1e */
3296 { 0xea,0x2a,139}, /* 0x1f */
3297 { 0x41,0x22,157}, /* 0x20 */
3298 { 0x70,0x24,162}, /* 0x21 */
3299 { 0x30,0x21,175}, /* 0x22 */
3300 { 0x4e,0x22,189}, /* 0x23 */
3301 { 0xde,0x26,194}, /* 0x24 */
3302 { 0x62,0x06,202}, /* 0x25 */
3303 { 0x3f,0x03,229}, /* 0x26 */
3304 { 0xb8,0x06,234}, /* 0x27 */
3305 { 0x34,0x02,253}, /* 0x28 */
3306 { 0x58,0x04,255}, /* 0x29 */
3307 { 0x24,0x01,265}, /* 0x2a */
3308 { 0x9b,0x02,267}, /* 0x2b */
3309 { 0x70,0x05,270}, /* 0x2c */
3310 { 0x25,0x01,272}, /* 0x2d */
3311 { 0x9c,0x02,277}, /* 0x2e */
3312 { 0x27,0x01,286}, /* 0x2f */
3313 { 0x3c,0x02,291}, /* 0x30 */
3314 { 0xef,0x0a,292}, /* 0x31 */
3315 { 0xf6,0x0a,310}, /* 0x32 */
3316 { 0x95,0x01,315}, /* 0x33 */
3317 { 0xf0,0x09,324}, /* 0x34 */
3318 { 0xfe,0x0a,331}, /* 0x35 */
3319 { 0xf3,0x09,332}, /* 0x36 */
3320 { 0xea,0x08,340}, /* 0x37 */
3321 { 0xe8,0x07,376}, /* 0x38 */
3322 { 0xde,0x06,389}, /* 0x39 */
3323 { 0x52,0x2a, 54}, /* 0x3a */
3324 { 0x52,0x6a, 27}, /* 0x3b */
3325 { 0x62,0x24, 70}, /* 0x3c */
3326 { 0x62,0x64, 70}, /* 0x3d */
3327 { 0xa8,0x4c, 30}, /* 0x3e */
3328 { 0x20,0x26, 33}, /* 0x3f */
3329 { 0x31,0xc2, 39}, /* 0x40 */
3330 { 0x60,0x36, 30}, /* 0x41 */
3331 { 0x40,0x4A, 28}, /* 0x42 */
3332 { 0x9F,0x46, 44}, /* 0x43 */
3333 { 0x97,0x2C, 26}, /* 0x44 */
3334 { 0x44,0xE4, 25}, /* 0x45 */
3335 { 0x7E,0x32, 47}, /* 0x46 */
3336 { 0x08,0x24, 31}, /* 0x47 */
3337 { 0x97,0x2c, 26}, /* 0x48 */
3338 { 0xCE,0x3c, 39}, /* 0x49 */
3339 { 0x52,0x4A, 36}, /* 0x4a */
3340 { 0x2C,0x61, 95}, /* 0x4b */
3341 { 0x78,0x27,108}, /* 0x4c */
3342 { 0x66,0x43,123}, /* 0x4d */
3343 { 0x2c,0x61, 80}, /* 0x4e */
3344 { 0x3b,0x61,108} /* 0x4f */
3345};
3346
3347XGI_VBVCLKDataStruct XGI330_VBVCLKData[]=
3348{
3349 { 0x1b,0xe1, 25}, /* 0x0 */
3350 { 0x4e,0xe4, 28}, /* 0x1 */
3351 { 0x57,0xe4, 31}, /* 0x2 */
3352 { 0xc3,0xc8, 36}, /* 0x3 */
3353 { 0x42,0x47, 40}, /* 0x4 */
3354 { 0xfe,0xcd, 43}, /* 0x5 */
3355 { 0x5d,0xc4, 44}, /* 0x6 */
3356 { 0x52,0x47, 49}, /* 0x7 */
3357 { 0x53,0x47, 50}, /* 0x8 */
3358 { 0x74,0x67, 52}, /* 0x9 */
3359 { 0x6d,0x66, 56}, /* 0xa */
3360 { 0x5a,0x64, 65}, /* 0xb */
3361 { 0x46,0x44, 67}, /* 0xc */
3362 { 0xb1,0x46, 68}, /* 0xd */
3363 { 0xd3,0x4a, 72}, /* 0xe */
3364 { 0x29,0x61, 75}, /* 0xf */
3365 { 0x6d,0x46, 75}, /* 0x10 */
3366 { 0x41,0x43, 78}, /* 0x11 */
3367 { 0x31,0x42, 79}, /* 0x12 */
3368 { 0xab,0x44, 83}, /* 0x13 */
3369 { 0x46,0x25, 84}, /* 0x14 */
3370 { 0x78,0x29, 86}, /* 0x15 */
3371 { 0x62,0x44, 94}, /* 0x16 */
3372 { 0x2b,0x22,104}, /* 0x17 */
3373 { 0x49,0x24,105}, /* 0x18 */
3374 { 0xf8,0x2f,108}, /* 0x19 */
3375 { 0x3c,0x23,109}, /* 0x1a */
3376 { 0x5e,0x43,113}, /* 0x1b */
3377 { 0xbc,0x44,116}, /* 0x1c */
3378 { 0xe0,0x46,132}, /* 0x1d */
3379 { 0xd4,0x28,135}, /* 0x1e */
3380 { 0xea,0x2a,139}, /* 0x1f */
3381 { 0x41,0x22,157}, /* 0x20 */
3382 { 0x70,0x24,162}, /* 0x21 */
3383 { 0x30,0x21,175}, /* 0x22 */
3384 { 0x4e,0x22,189}, /* 0x23 */
3385 { 0xde,0x26,194}, /* 0x24 */
3386 { 0x70,0x07,202}, /* 0x25 */
3387 { 0x3f,0x03,229}, /* 0x26 */
3388 { 0xb8,0x06,234}, /* 0x27 */
3389 { 0x34,0x02,253}, /* 0x28 */
3390 { 0x58,0x04,255}, /* 0x29 */
3391 { 0x24,0x01,265}, /* 0x2a */
3392 { 0x9b,0x02,267}, /* 0x2b */
3393 { 0x70,0x05,270}, /* 0x2c */
3394 { 0x25,0x01,272}, /* 0x2d */
3395 { 0x9c,0x02,277}, /* 0x2e */
3396 { 0x27,0x01,286}, /* 0x2f */
3397 { 0x3c,0x02,291}, /* 0x30 */
3398 { 0xef,0x0a,292}, /* 0x31 */
3399 { 0xf6,0x0a,310}, /* 0x32 */
3400 { 0x95,0x01,315}, /* 0x33 */
3401 { 0xf0,0x09,324}, /* 0x34 */
3402 { 0xfe,0x0a,331}, /* 0x35 */
3403 { 0xf3,0x09,332}, /* 0x36 */
3404 { 0xea,0x08,340}, /* 0x37 */
3405 { 0xe8,0x07,376}, /* 0x38 */
3406 { 0xde,0x06,389}, /* 0x39 */
3407 { 0x52,0x2a, 54}, /* 0x3a */
3408 { 0x52,0x6a, 27}, /* 0x3b */
3409 { 0x62,0x24, 70}, /* 0x3c */
3410 { 0x62,0x64, 70}, /* 0x3d */
3411 { 0xa8,0x4c, 30}, /* 0x3e */
3412 { 0x20,0x26, 33}, /* 0x3f */
3413 { 0x31,0xc2, 39}, /* 0x40 */
3414 { 0x2e,0x48, 25}, /* 0x41 */
3415 { 0x24,0x46, 25}, /* 0x42 */
3416 { 0x26,0x64, 28}, /* 0x43 */
3417 { 0x37,0x64, 40}, /* 0x44 */
3418 { 0xa1,0x42,108}, /* 0x45 */
3419 { 0x37,0x61,100}, /* 0x46 */
3420 { 0x78,0x27,108}, /* 0x47 */
3421 { 0x5e,0x64,68}, /* 0x48 chiawen for fuj1280x768*/
3422 { 0x70,0x44,108}, /* 0x49 chiawen for 1400x1050*/
3423};
3424
3425UCHAR XGI330_ScreenOffset[]={ 0x14,0x19,0x20,0x28,0x32,0x40,0x50,0x64,0x78,0x80,0x2d,0x35,0x57,0x48 };
3426
3427XGI_StResInfoStruct XGI330_StResInfo[]=
3428{
3429 { 640,400},
3430 { 640,350},
3431 { 720,400},
3432 { 720,350},
3433 { 640,480}
3434};
3435
3436XGI_ModeResInfoStruct XGI330_ModeResInfo[]=
3437{
3438 { 320, 200, 8, 8},
3439 { 320, 240, 8, 8},
3440 { 320, 400, 8, 8},
3441 { 400, 300, 8, 8},
3442 { 512, 384, 8, 8},
3443 { 640, 400, 8,16},
3444 { 640, 480, 8,16},
3445 { 800, 600, 8,16},
3446 { 1024, 768, 8,16},
3447 { 1280,1024, 8,16},
3448 { 1600,1200, 8,16},
3449 { 1920,1440, 8,16},
3450 { 2048,1536, 8,16},
3451 { 720, 480, 8,16},
3452 { 720, 576, 8,16},
3453 { 1280, 960, 8,16},
3454 { 800, 480, 8,16},
3455 { 1024, 576, 8,16},
3456 { 1280, 720, 8,16},
3457 { 856, 480, 8,16},
3458 { 1280, 768, 8,16},
3459 { 1400,1050, 8,16},
3460 { 1152, 864, 8,16}
3461};
3462
3463UCHAR XGI330_OutputSelect =0x40;
3464UCHAR XGI330_SoftSetting = 0x30;
3465UCHAR XGI330_SR07=0x18;
3466UCHAR XGI330New_SR15[8][8]={
3467{0x0,0x4,0x60,0x60},
3468{0xf,0xf,0xf,0xf},
3469{0xba,0xba,0xba,0xba},
3470{0xa9,0xa9,0xac,0xac},
3471{0xa0,0xa0,0xa0,0xa8},
3472{0x0,0x0,0x2,0x2},
3473{0x30,0x30,0x40,0x40},
3474{0x0,0xa5,0xfb,0xf6}
3475};
3476
3477UCHAR XGI330New_CR40[5][8]={
3478{0x77,0x77,0x44,0x44},
3479{0x77,0x77,0x44,0x44},
3480{0x0,0x0,0x0,0x0},
3481{0x5b,0x5b,0xab,0xab},
3482{0x0,0x0,0xf0,0xf8}
3483};
3484
3485UCHAR XGI330_CR49[]={0xaa,0x88};
3486UCHAR XGI330_SR1F=0x0;
3487UCHAR XGI330_SR21=0xa3;
3488UCHAR XGI330_650_SR21=0xa7;
3489UCHAR XGI330_SR22=0xfb;
3490UCHAR XGI330_SR23=0xf6;
3491UCHAR XGI330_SR24=0xd;
3492
3493UCHAR XGI660_SR21=0xa3;/* 2003.0312 */
3494UCHAR XGI660_SR22=0xf3;/* 2003.0312 */
3495
3496UCHAR XGI330_LVDS_SR32=0x00; /* ynlai for 650 LVDS */
3497UCHAR XGI330_LVDS_SR33=0x00; /* chiawen for 650 LVDS */
3498UCHAR XGI330_650_SR31=0x40;
3499UCHAR XGI330_650_SR33=0x04;
3500UCHAR XGI330_CRT2Data_1_2 = 0x0;
3501UCHAR XGI330_CRT2Data_4_D = 0x0;
3502UCHAR XGI330_CRT2Data_4_E = 0x0;
3503UCHAR XGI330_CRT2Data_4_10 = 0x80;
3504USHORT XGI330_RGBSenseData = 0xd1;
3505USHORT XGI330_VideoSenseData = 0xb9;
3506USHORT XGI330_YCSenseData = 0xb3;
3507USHORT XGI330_RGBSenseData2 = 0x0190; /*301b*/
3508USHORT XGI330_VideoSenseData2 = 0x0110;
3509USHORT XGI330_YCSenseData2 = 0x016B;
3510UCHAR XGI330_NTSCPhase[] = {0x21,0xed,0x8a,0x8};
3511UCHAR XGI330_PALPhase[] = {0x2a,0x5,0xd3,0x0};
3512UCHAR XGI330_NTSCPhase2[] = {0x21,0xF0,0x7B,0xD6};/*301b*/
3513UCHAR XGI330_PALPhase2[] = {0x2a,0x09,0x86,0xe9};
3514UCHAR XGI330_PALMPhase[] = {0x21,0xE4,0x2E,0x9B}; /*palmn*/
3515UCHAR XGI330_PALNPhase[] = {0x21,0xF4,0x3E,0xBA};
3516UCHAR XG40_I2CDefinition = 0x00 ;
3517UCHAR XG20_CR97 = 0x10 ;
3518
3519UCHAR XG21_DVOSetting = 0x00 ;
3520UCHAR XG21_CR2E = 0x00 ;
3521UCHAR XG21_CR2F = 0x00 ;
3522UCHAR XG21_CR46 = 0x00 ;
3523UCHAR XG21_CR47 = 0x00 ;
3524
3525UCHAR XG27_CR97 = 0xC1 ;
3526UCHAR XG27_SR36 = 0x30 ;
3527UCHAR XG27_CR8F = 0x0C ;
3528UCHAR XG27_CRD0[] = {0,0,0,0,0,0,0,0x82,0x00,0x66,0x01,0x00} ;
3529UCHAR XG27_CRDE[] = {0,0} ;
3530UCHAR XG27_SR40 = 0x04 ;
3531UCHAR XG27_SR41 = 0x00 ;
3532
3533UCHAR XGI330_CHTVVCLKUNTSC[]={0x00 };
3534
3535UCHAR XGI330_CHTVVCLKONTSC[]={0x00 };
3536
3537UCHAR XGI330_CHTVVCLKUPAL[]={0x00 };
3538
3539UCHAR XGI330_CHTVVCLKOPAL[]={0x00 };
3540
3541UCHAR XGI7007_CHTVVCLKUNTSC[]={CH7007TVVCLK30_2,
3542 CH7007TVVCLK30_2,
3543 CH7007TVVCLK30_2,
3544 CH7007TVVCLK30_2,
3545 CH7007TVVCLK28_1,
3546 CH7007TVVCLK47_8
3547 };
3548
3549UCHAR XGI7007_CHTVVCLKONTSC[]={CH7007TVVCLK26_4,
3550 CH7007TVVCLK26_4,
3551 CH7007TVVCLK26_4,
3552 CH7007TVVCLK26_4,
3553 CH7007TVVCLK24_6,
3554 CH7007TVVCLK43_6
3555 };
3556
3557UCHAR XGI7007_CHTVVCLKUPAL[]={CH7007TVVCLK31_5,
3558 CH7007TVVCLK31_5,
3559 CH7007TVVCLK31_5,
3560 CH7007TVVCLK31_5,
3561 CH7007TVVCLK26_2,
3562 CH7007TVVCLK39
3563 };
3564
3565UCHAR XGI7007_CHTVVCLKOPAL[]={CH7007TVVCLK31_5,
3566 CH7007TVVCLK31_5,
3567 CH7007TVVCLK31_5,
3568 CH7007TVVCLK31_5,
3569 CH7007TVVCLK26_2,
3570 CH7007TVVCLK36
3571 };
3572
3573XGI330_VCLKDataStruct XGI_CH7007VCLKData[]=
3574{
3575 { 0x60,0x36,30}, /* 0 30.2 MHZ */
3576 { 0x40,0x4A,28}, /* 1 28.19 MHZ */
3577 { 0x9F,0x46,44}, /* 2 43.6 MHZ */
3578 { 0x97,0x2C,26}, /* 3 26.4 MHZ */
3579 { 0x44,0xE4,25}, /* 4 24.6 MHZ */
3580 { 0x7E,0x32,47}, /* 5 47.832 MHZ */
3581 { 0x8A,0x24,31}, /* 6 31.5 MHZ */
3582 { 0x97,0x2C,26}, /* 7 26.2 MHZ */
3583 { 0xCE,0x3C,39}, /* 8 39 MHZ */
3584 { 0x52,0x4A,36}, /* 9 36 MHZ */
3585 { 0xFF,0x00,0 } /* End mark */
3586};
3587
3588XGI330_VCLKDataStruct XGI_VCLKData[]=
3589{
3590 /* SR2B,SR2C,SR2D */
3591 { 0x1B,0xE1,25 },/* 00 (25.175MHz) */
3592
3593 { 0x4E,0xE4,28 },/* 01 (28.322MHz) */
3594
3595 { 0x57,0xE4,31 },/* 02 (31.500MHz) */
3596
3597 { 0xC3,0xC8,36 },/* 03 (36.000MHz) */
3598
3599 { 0x42,0xE2,40 },/* 04 (40.000MHz) */
3600
3601 { 0xFE,0xCD,43 },/* 05 (43.163MHz) */
3602
3603 { 0x5D,0xC4,44 },/* 06 (44.900MHz) */
3604
3605 { 0x52,0xE2,49 },/* 07 (49.500MHz) */
3606
3607 { 0x53,0xE2,50 },/* 08 (50.000MHz) */
3608
3609 { 0x74,0x67,52 },/* 09 (52.406MHz) */
3610
3611 { 0x6D,0x66,56 },/* 0A (56.250MHz) */
3612
3613 { 0x6C,0xC3,65 },/* 0B (65.000MHz) */
3614
3615 { 0x46,0x44,67 },/* 0C (67.765MHz) */
3616
3617 { 0xB1,0x46,68 },/* 0D (68.179MHz) */
3618
3619 { 0xD3,0x4A,72 },/* 0E (72.852MHz) */
3620
3621 { 0x29,0x61,75 },/* 0F (75.000MHz) */
3622
3623 { 0x6E,0x46,76 },/* 10 (75.800MHz) */
3624
3625 { 0x2B,0x61,78 },/* 11 (78.750MHz) */
3626
3627 { 0x31,0x42,79 },/* 12 (79.411MHz) */
3628
3629 { 0xAB,0x44,83 },/* 13 (83.950MHz) */
3630
3631 { 0x46,0x25,84 },/* 14 (84.800MHz) */
3632
3633 { 0x78,0x29,86 },/* 15 (86.600MHz) */
3634
3635 { 0x62,0x44,94 },/* 16 (94.500MHz) */
3636
3637 { 0x2B,0x41,104 },/* 17 (104.998MHz) */
3638
3639 { 0x3A,0x23,105 },/* 18 (105.882MHz) */
3640
3641 { 0x70,0x44,108 },/* 19 (107.862MHz) */
3642
3643 { 0x3C,0x23,109 },/* 1A (109.175MHz) */
3644
3645 { 0x5E,0x43,113 },/* 1B (113.309MHz) */
3646
3647 { 0xBC,0x44,116 },/* 1C (116.406MHz) */
3648
3649 { 0xE0,0x46,132 },/* 1D (132.258MHz) */
3650
3651 { 0x54,0x42,135 },/* 1E (135.500MHz) */
3652
3653 { 0x9C,0x22,139 },/* 1F (139.275MHz) */
3654
3655 { 0x41,0x22,157 },/* 20 (157.500MHz) */
3656
3657 { 0x70,0x24,162 },/* 21 (161.793MHz) */
3658
3659 { 0x30,0x21,175 },/* 22 (175.000MHz) */
3660
3661 { 0x4E,0x22,189 },/* 23 (188.520MHz) */
3662
3663 { 0xDE,0x26,194 },/* 24 (194.400MHz) */
3664
3665 { 0x62,0x06,202 },/* 25 (202.500MHz) */
3666
3667 { 0x3F,0x03,229 },/* 26 (229.500MHz) */
3668
3669 { 0xB8,0x06,234 },/* 27 (233.178MHz) */
3670
3671 { 0x34,0x02,253 },/* 28 (252.699MHz) */
3672
3673 { 0x58,0x04,255 },/* 29 (254.817MHz) */
3674
3675 { 0x24,0x01,265 },/* 2A (265.728MHz) */
3676
3677 { 0x9B,0x02,267 },/* 2B (266.952MHz) */
3678
3679 { 0x70,0x05,270 },/* 2C (269.65567MHz) */
3680
3681 { 0x25,0x01,272 },/* 2D (272.04199MHz) */
3682
3683 { 0x9C,0x02,277 },/* 2E (277.015MHz) */
3684
3685 { 0x27,0x01,286 },/* 2F (286.359985MHz) */
3686
3687 { 0xB3,0x04,291 },/* 30 (291.13266MHz) */
3688
3689 { 0xBC,0x05,292 },/* 31 (291.766MHz) */
3690
3691 { 0xF6,0x0A,310 },/* 32 (309.789459MHz) */
3692
3693 { 0x95,0x01,315 },/* 33 (315.195MHz) */
3694
3695 { 0xF0,0x09,324 },/* 34 (323.586792MHz) */
3696
3697 { 0xFE,0x0A,331 },/* 35 (330.615631MHz) */
3698
3699 { 0xF3,0x09,332 },/* 36 (332.177612MHz) */
3700
3701 { 0x5E,0x03,340 },/* 37 (340.477MHz) */
3702
3703 { 0xE8,0x07,376 },/* 38 (375.847504MHz) */
3704
3705 { 0xDE, 0x06,389 },/* 39 (388.631439MHz) */
3706
3707 { 0x52,0x2A,54 },/* 3A (54.000MHz) */
3708
3709 { 0x52,0x6A,27 },/* 3B (27.000MHz) */
3710
3711 { 0x62,0x24,70 },/* 3C (70.874991MHz) */
3712
3713 { 0x62,0x64,70 },/* 3D (70.1048912MHz) */
3714
3715 { 0xA8,0x4C,30 },/* 3E (30.1048912MHz) */
3716
3717 { 0x20,0x26,33 },/* 3F (33.7499957MHz) */
3718
3719 { 0x31,0xc2,39 },/* 40 (39.77MHz) */
3720
3721 { 0x11,0x21,30 },/* 41 (30MHz) }// NTSC 1024X768 */
3722
3723 { 0x2E,0x48,25 },/* 42 (25.175MHz) }// ScaleLCD */
3724
3725 { 0x24,0x46,25 },/* 43 (25.175MHz) */
3726
3727 { 0x26,0x64,28 },/* 44 (28.322MHz) */
3728
3729 { 0x37,0x64,40 },/* 45 (40.000MHz) */
3730
3731 { 0xA1,0x42,108 },/* 46 (95.000MHz) }// QVGA */
3732
3733 { 0x37,0x61,100 },/* 47 (100.00MHz) */
3734
3735 { 0x78,0x27,108 },/* 48 (108.200MHz) */
3736
3737 { 0xBF,0xC8,35 },/* 49 (35.2MHz) */
3738
3739 { 0x66,0x43,123 },/* 4A (122.61Mhz) */
3740
3741 { 0x2C,0x61,80 },/* 4B (80.350Mhz) */
3742
3743 { 0x3B,0x61,108 },/* 4C (107.385Mhz) */
3744
3745
3746/* { 0x60,0x36,30 },// 4D (30.200MHz) }// No use
3747
3748 { 0x60,0x36,30 },// 4E (30.200MHz) }// No use
3749
3750 { 0x60,0x36,30 },// 4F (30.200MHz) }// No use
3751
3752 { 0x60,0x36,30 },// 50 (30.200MHz) }// CHTV
3753
3754 { 0x40,0x4A,28 },// 51 (28.190MHz)
3755
3756 { 0x9F,0x46,44 },// 52 (43.600MHz)
3757
3758 { 0x97,0x2C,26 },// 53 (26.400MHz)
3759
3760 { 0x44,0xE4,25 },// 54 (24.600MHz)
3761
3762 { 0x7E,0x32,47 },// 55 (47.832MHz)
3763
3764 { 0x8A,0x24,31 },// 56 (31.500MHz)
3765
3766 { 0x97,0x2C,26 },// 57 (26.200MHz)
3767
3768 { 0xCE,0x3C,39 },// 58 (39.000MHz)
3769
3770 { 0x52,0x4A,36 },// 59 (36.000MHz)
3771
3772*/
3773 { 0x69,0x61,191 }, /* 4D (190.96MHz ) */
3774 { 0x4F,0x22,192 }, /* 4E (192.069MHz) */
3775 { 0x28,0x26,322 }, /* 4F (322.273MHz) */
3776 { 0x5C,0x6B,27 }, /* 50 (27.74HMz) */
3777 { 0x57,0x24,126 }, /* 51 (125.999MHz) */
3778 { 0x5C,0x42,148 }, /* 52 (148.5MHz) */
3779 { 0x42,0x61,120 }, /* 53 (120.839MHz) */
3780 { 0x62,0x61,178 }, /* 54 (178.992MHz) */
3781 { 0x59,0x22,217 }, /* 55 (217.325MHz) */
3782 { 0x29,0x01,300 }, /* 56 (299.505Mhz) */
3783 { 0x52,0x63,74 }, /* 57 (74.25MHz) */
3784
3785
3786 { 0xFF,0x00,0 }/* End mark */
3787 } ;
3788
3789XGI330_VCLKDataStruct XGI_VBVCLKData[]=
3790{
3791 { 0x1B,0xE1,25 },/* 00 (25.175MHz) */
3792
3793 { 0x4E,0xE4,28 },/* 01 (28.322MHz) */
3794
3795 { 0x57,0xE4,31 },/* 02 (31.500MHz) */
3796
3797 { 0xC3,0xC8,36 },/* 03 (36.000MHz) */
3798
3799 { 0x42,0x47,40 },/* 04 (40.000MHz) */
3800
3801 { 0xFE,0xCD,43 },/* 05 (43.163MHz) */
3802
3803 { 0x5D,0xC4,44 },/* 06 (44.900MHz) */
3804
3805 { 0x52,0x47,49 },/* 07 (49.500MHz) */
3806
3807 { 0x53,0x47,50 },/* 08 (50.000MHz) */
3808
3809 { 0x74,0x67,52 },/* 09 (52.406MHz) */
3810
3811 { 0x6D,0x66,56 },/* 0A (56.250MHz) */
3812
3813 { 0x35,0x62,65 },/* 0B (65.000MHz) */
3814
3815 { 0x46,0x44,67 },/* 0C (67.765MHz) */
3816
3817 { 0xB1,0x46,68 },/* 0D (68.179MHz) */
3818
3819 { 0xD3,0x4A,72 },/* 0E (72.852MHz) */
3820
3821 { 0x29,0x61,75 },/* 0F (75.000MHz) */
3822
3823 { 0x6D,0x46,75 },/* 10 (75.800MHz) */
3824
3825 { 0x41,0x43,78 },/* 11 (78.750MHz) */
3826
3827 { 0x31,0x42,79 },/* 12 (79.411MHz) */
3828
3829 { 0xAB,0x44,83 },/* 13 (83.950MHz) */
3830
3831 { 0x46,0x25,84 },/* 14 (84.800MHz) */
3832
3833 { 0x78,0x29,86 },/* 15 (86.600MHz) */
3834
3835 { 0x62,0x44,94 },/* 16 (94.500MHz) */
3836
3837 { 0x2B,0x22,104 },/* 17 (104.998MHz) */
3838
3839 { 0x49,0x24,105 },/* 18 (105.882MHz) */
3840
3841 { 0xF8,0x2F,108 },/* 19 (108.279MHz) */
3842
3843 { 0x3C,0x23,109 },/* 1A (109.175MHz) */
3844
3845 { 0x5E,0x43,113 },/* 1B (113.309MHz) */
3846
3847 { 0xBC,0x44,116 },/* 1C (116.406MHz) */
3848
3849 { 0xE0,0x46,132 },/* 1D (132.258MHz) */
3850
3851 { 0xD4,0x28,135 },/* 1E (135.220MHz) */
3852
3853 { 0xEA,0x2A,139 },/* 1F (139.275MHz) */
3854
3855 { 0x41,0x22,157 },/* 20 (157.500MHz) */
3856
3857 { 0x70,0x24,162 },/* 21 (161.793MHz) */
3858
3859 { 0x30,0x21,175 },/* 22 (175.000MHz) */
3860
3861 { 0x4E,0x22,189 },/* 23 (188.520MHz) */
3862
3863 { 0xDE,0x26,194 },/* 24 (194.400MHz) */
3864
3865 { 0x70,0x07,202 },/* 25 (202.500MHz) */
3866
3867 { 0x3F,0x03,229 },/* 26 (229.500MHz) */
3868
3869 { 0xB8,0x06,234 },/* 27 (233.178MHz) */
3870
3871 { 0x34,0x02,253 },/* 28 (252.699997 MHz) */
3872
3873 { 0x58,0x04,255 },/* 29 (254.817MHz) */
3874
3875 { 0x24,0x01,265 },/* 2A (265.728MHz) */
3876
3877 { 0x9B,0x02,267 },/* 2B (266.952MHz) */
3878
3879 { 0x70,0x05,270 },/* 2C (269.65567 MHz) */
3880
3881 { 0x25,0x01,272 },/* 2D (272.041992 MHz) */
3882
3883 { 0x9C,0x02,277 },/* 2E (277.015MHz) */
3884
3885 { 0x27,0x01,286 },/* 2F (286.359985 MHz) */
3886
3887 { 0x3C,0x02,291 },/* 30 (291.132660 MHz) */
3888
3889 { 0xEF,0x0A,292 },/* 31 (291.766MHz) */
3890
3891 { 0xF6,0x0A,310 },/* 32 (309.789459 MHz) */
3892
3893 { 0x95,0x01,315 },/* 33 (315.195MHz) */
3894
3895 { 0xF0,0x09,324 },/* 34 (323.586792 MHz) */
3896
3897 { 0xFE,0x0A,331 },/* 35 (330.615631 MHz) */
3898
3899 { 0xF3,0x09,332 },/* 36 (332.177612 MHz) */
3900
3901 { 0xEA,0x08,340 },/* 37 (340.477MHz) */
3902
3903 { 0xE8,0x07,376 },/* 38 (375.847504 MHz) */
3904
3905 { 0xDE,0x06,389 },/* 39 (388.631439 MHz) */
3906
3907 { 0x52,0x2A,54 },/* 3A (54.000MHz) */
3908
3909 { 0x52,0x6A,27 },/* 3B (27.000MHz) */
3910
3911
3912 { 0x62,0x24,70 },/* 3C (70.874991MHz) */
3913
3914
3915 { 0x62,0x64,70 },/* 3D (70.1048912MHz) */
3916
3917 { 0xA8,0x4C,30 },/* 3E (30.1048912MHz) */
3918
3919 { 0x20,0x26,33 },/* 3F (33.7499957MHz) */
3920
3921 { 0x31,0xc2,39 },/* 40 (39.77MHz) */
3922
3923 { 0x11,0x21,30 },/* 41 (30MHz) }// NTSC 1024X768 */
3924
3925 { 0x2E,0x48,25 },/* 42 (25.175MHz) }// ScaleLCD */
3926
3927 { 0x24,0x46,25 },/* 43 (25.175MHz) */
3928
3929 { 0x26,0x64,28 },/* 44 (28.322MHz) */
3930
3931 { 0x37,0x64,40 },/* 45 (40.000MHz) */
3932
3933 { 0xA1,0x42,108 },/* 46 (95.000MHz) }// QVGA */
3934
3935 { 0x37,0x61,100 },/* 47 (100.00MHz) */
3936
3937 { 0x78,0x27,108 },/* 48 (108.200MHz) */
3938
3939 { 0xBF,0xC8,35 },/* 49 (35.2MHz) */
3940
3941 { 0x66,0x43,123 },/* 4A (122.61Mhz) */
3942
3943 { 0x2C,0x61,80 },/* 4B (80.350Mhz) */
3944
3945 { 0x3B,0x61,108 },/* 4C (107.385Mhz) */
3946
3947/*
3948 { 0x60,0x36,30 },// 4D (30.200MHz) }// No use
3949
3950 { 0x60,0x36,30 },// 4E (30.200MHz) }// No use
3951
3952 { 0x60,0x36,30 },// 4F (30.200MHz) }// No use
3953
3954 { 0x60,0x36,30 },// 50 (30.200MHz) }// CHTV
3955
3956 { 0x40,0x4A,28 },// 51 (28.190MHz)
3957
3958 { 0x9F,0x46,44 },// 52 (43.600MHz)
3959
3960 { 0x97,0x2C,26 },// 53 (26.400MHz)
3961
3962 { 0x44,0xE4,25 },// 54 (24.600MHz)
3963
3964 { 0x7E,0x32,47 },// 55 (47.832MHz)
3965
3966 { 0x8A,0x24,31 },// 56 (31.500MHz)
3967
3968 { 0x97,0x2C,26 },// 57 (26.200MHz)
3969
3970 { 0xCE,0x3C,39 },// 58 (39.000MHz)
3971
3972 { 0x52,0x4A,36 },// 59 (36.000MHz)
3973*/
3974 { 0x69,0x61,191 }, /* 4D (190.96MHz ) */
3975 { 0x4F,0x22,192 }, /* 4E (192.069MHz) */
3976 { 0x28,0x26,322 }, /* 4F (322.273MHz) */
3977 { 0x5C,0x6B,27 }, /* 50 (27.74HMz) */
3978 { 0x57,0x24,126 }, /* 51 (125.999MHz) */
3979 { 0x5C,0x42,148 }, /* 52 (148.5MHz) */
3980 { 0x42,0x61,120 }, /* 53 (120.839MHz) */
3981 { 0x62,0x61,178 }, /* 54 (178.992MHz) */
3982 { 0x59,0x22,217 }, /* 55 (217.325MHz) */
3983 { 0x29,0x01,300 }, /* 56 (299.505Mhz) */
3984 { 0x52,0x63,74 }, /* 57 (74.25MHz) */
3985
3986
3987 { 0xFF,0x00,0 } /* End mark */
3988};
3989
3990UCHAR XGI660_TVDelayList[]=
3991{
3992 0x44, /* ; 0 ExtNTSCDelay */
3993 0x44, /* ; 1 StNTSCDelay */
3994 0x44, /* ; 2 ExtPALDelay */
3995 0x44, /* ; 3 StPALDelay */
3996 0x44, /* ; 4 ExtHiTVDelay(1080i) */
3997 0x44, /* ; 5 StHiTVDelay(1080i) */
3998 0x44, /* ; 6 ExtYPbPrDelay(525i) */
3999 0x44, /* ; 7 StYPbPrDealy(525i) */
4000 0x44, /* ; 8 ExtYPbPrDelay(525p) */
4001 0x44, /* ; 9 StYPbPrDealy(525p) */
4002 0x44, /* ; A ExtYPbPrDelay(750p) */
4003 0x44 /* ; B StYPbPrDealy(750p) */
4004};
4005
4006UCHAR XGI660_TVDelayList2[]=
4007{
4008 0x44, /* ; 0 ExtNTSCDelay */
4009 0x44, /* ; 1 StNTSCDelay */
4010 0x44, /* ; 2 ExtPALDelay */
4011 0x44, /* ; 3 StPALDelay */
4012 0x44, /* ; 4 ExtHiTVDelay */
4013 0x44, /* ; 5 StHiTVDelay */
4014 0x44, /* ; 6 ExtYPbPrDelay(525i) */
4015 0x44, /* ; 7 StYPbPrDealy(525i) */
4016 0x44, /* ; 8 ExtYPbPrDelay(525p) */
4017 0x44, /* ; 9 StYPbPrDealy(525p) */
4018 0x44, /* ; A ExtYPbPrDelay(750p) */
4019 0x44 /* ; B StYPbPrDealy(750p) */
4020};
4021
4022UCHAR XGI301TVDelayList[]=
4023{
4024 0x22, /* ; 0 ExtNTSCDelay */
4025 0x22, /* ; 1 StNTSCDelay */
4026 0x22, /* ; 2 ExtPALDelay */
4027 0x22, /* ; 3 StPALDelay */
4028 0x88, /* ; 4 ExtHiTVDelay(1080i) */
4029 0xBB, /* ; 5 StHiTVDelay(1080i) */
4030 0x22, /* ; 6 ExtYPbPrDelay(525i) */
4031 0x22, /* ; 7 StYPbPrDealy(525i) */
4032 0x22, /* ; 8 ExtYPbPrDelay(525p) */
4033 0x22, /* ; 9 StYPbPrDealy(525p) */
4034 0x22, /* ; A ExtYPbPrDelay(750p) */
4035 0x22 /* B StYPbPrDealy(750p) */
4036};
4037
4038UCHAR XGI301TVDelayList2[]=
4039{
4040 0x22, /* ; 0 ExtNTSCDelay */
4041 0x22, /* ; 1 StNTSCDelay */
4042 0x22, /* ; 2 ExtPALDelay */
4043 0x22, /* ; 3 StPALDelay */
4044 0x22, /* ; 4 ExtHiTVDelay */
4045 0x22, /* ; 5 StHiTVDelay */
4046 0x22, /* ; 6 ExtYPbPrDelay(525i) */
4047 0x22, /* ; 7 StYPbPrDealy(525i) */
4048 0x22, /* ; 8 ExtYPbPrDelay(525p) */
4049 0x22, /* ; 9 StYPbPrDealy(525p) */
4050 0x22, /* ; A ExtYPbPrDelay(750p) */
4051 0x22 /* ; B StYPbPrDealy(750p) */
4052};
4053
4054
4055UCHAR TVAntiFlickList[]=
4056{/* NTSCAntiFlicker */
4057 0x04, /* ; 0 Adaptive */
4058 0x00, /* ; 1 new anti-flicker ? */
4059/* PALAntiFlicker */
4060 0x04, /* ; 0 Adaptive */
4061 0x08, /* ; 1 new anti-flicker ? */
4062/* HiTVAntiFlicker */
4063 0x04, /* ; 0 ? */
4064 0x00 /* ; 1 new anti-flicker ? */
4065};
4066
4067
4068UCHAR TVEdgeList[]=
4069{
4070 0x00, /* ; 0 NTSC No Edge enhance */
4071 0x04, /* ; 1 NTSC Adaptive Edge enhance */
4072 0x00, /* ; 0 PAL No Edge enhance */
4073 0x04, /* ; 1 PAL Adaptive Edge enhance */
4074 0x00, /* ; 0 HiTV */
4075 0x00 /* ; 1 HiTV */
4076};
4077
4078ULONG TVPhaseList[]=
4079{ 0x08BAED21, /* ; 0 NTSC phase */
4080 0x00E3052A, /* ; 1 PAL phase */
4081 0x9B2EE421, /* ; 2 PAL-M phase */
4082 0xBA3EF421, /* ; 3 PAL-N phase */
4083 0xA7A28B1E, /* ; 4 NTSC 1024x768 */
4084 0xE00A831E, /* ; 5 PAL-M 1024x768 */
4085 0x00000000, /* ; 6 reserved */
4086 0x00000000, /* ; 7 reserved */
4087 0xD67BF021, /* ; 8 NTSC phase */
4088 0xE986092A, /* ; 9 PAL phase */
4089 0xA4EFE621, /* ; A PAL-M phase */
4090 0x4694F621, /* ; B PAL-N phase */
4091 0x8BDE711C, /* ; C NTSC 1024x768 */
4092 0xE00A831E /* ; D PAL-M 1024x768 */
4093};
4094
4095UCHAR NTSCYFilter1[]=
4096{
4097 0x00,0xF4,0x10,0x38 ,/* 0 : 320x text mode */
4098 0x00,0xF4,0x10,0x38 ,/* 1 : 360x text mode */
4099 0xEB,0x04,0x25,0x18 ,/* 2 : 640x text mode */
4100 0xF1,0x04,0x1F,0x18 ,/* 3 : 720x text mode */
4101 0x00,0xF4,0x10,0x38 ,/* 4 : 320x gra. mode */
4102 0xEB,0x04,0x25,0x18 ,/* 5 : 640x gra. mode */
4103 0xEB,0x15,0x25,0xF6 /* 6 : 800x gra. mode */
4104};
4105
4106UCHAR PALYFilter1[]=
4107{
4108 0x00,0xF4,0x10,0x38, /* 0 : 320x text mode */
4109 0x00,0xF4,0x10,0x38 ,/* 1 : 360x text mode */
4110 0xF1,0xF7,0x1F,0x32 ,/* 2 : 640x text mode */
4111 0xF3,0x00,0x1D,0x20 ,/* 3 : 720x text mode */
4112 0x00,0xF4,0x10,0x38 ,/* 4 : 320x gra. mode */
4113 0xF1,0xF7,0x1F,0x32 ,/* 5 : 640x gra. mode */
4114 0xFC,0xFB,0x14,0x2A /* 6 : 800x gra. mode */
4115};
4116
4117UCHAR PALMYFilter1[]=
4118{
4119 0x00,0xF4,0x10,0x38, /* 0 : 320x text mode */
4120 0x00,0xF4,0x10,0x38, /* 1 : 360x text mode */
4121 0xEB,0x04,0x10,0x18, /* 2 : 640x text mode */
4122 0xF7,0x06,0x19,0x14, /* 3 : 720x text mode */
4123 0x00,0xF4,0x10,0x38, /* 4 : 320x gra. mode */
4124 0xEB,0x04,0x25,0x18, /* 5 : 640x gra. mode */
4125 0xEB,0x15,0x25,0xF6, /* 6 : 800x gra. mode */
4126 0xFF,0xFF,0xFF,0xFF /* End of Table */
4127};
4128
4129UCHAR PALNYFilter1[]=
4130{
4131 0x00,0xF4,0x10,0x38, /* 0 : 320x text mode */
4132 0x00,0xF4,0x10,0x38, /* 1 : 360x text mode */
4133 0xEB,0x04,0x10,0x18, /* 2 : 640x text mode */
4134 0xF7,0x06,0x19,0x14, /* 3 : 720x text mode */
4135 0x00,0xF4,0x10,0x38, /* 4 : 320x gra. mode */
4136 0xEB,0x04,0x25,0x18, /* 5 : 640x gra. mode */
4137 0xEB,0x15,0x25,0xF6, /* 6 : 800x gra. mode */
4138 0xFF,0xFF,0xFF,0xFF /* End of Table */
4139};
4140
4141UCHAR NTSCYFilter2[]=
4142{
4143 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 0 : 320x text mode */
4144 0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C, /* 1 : 360x text mode */
4145 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 2 : 640x text mode */
4146 0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C, /* 3 : 720x text mode */
4147 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 4 : 320x gra. mode */
4148 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 5 : 640x gra. mode */
4149 0x01,0x01,0xFC,0xF8,0x08,0x26,0x38, /* 6 : 800x gra. mode */
4150 0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28 /* 7 : 1024xgra. mode */
4151};
4152
4153UCHAR PALYFilter2[]=
4154{
4155 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 0 : 320x text mode */
4156 0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C, /* 1 : 360x text mode */
4157 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 2 : 640x text mode */
4158 0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C, /* 3 : 720x text mode */
4159 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 4 : 320x gra. mode */
4160 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 5 : 640x gra. mode */
4161 0x01,0x01,0xFC,0xF8,0x08,0x26,0x38, /* 6 : 800x gra. mode */
4162 0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28 /* 7 : 1024xgra. mode */
4163};
4164
4165UCHAR PALMYFilter2[]=
4166{
4167 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 0 : 320x text mode */
4168 0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C, /* 1 : 360x text mode */
4169 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 2 : 640x text mode */
4170 0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C, /* 3 : 720x text mode */
4171 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 4 : 320x gra. mode */
4172 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 5 : 640x gra. mode */
4173 0x01,0x01,0xFC,0xF8,0x08,0x26,0x38, /* 6 : 800x gra. mode */
4174 0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28 /* 7 : 1024xgra. mode */
4175};
4176
4177UCHAR PALNYFilter2[]=
4178{
4179 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 0 : 320x text mode */
4180 0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C, /* 1 : 360x text mode */
4181 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 2 : 640x text mode */
4182 0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C, /* 3 : 720x text mode */
4183 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 4 : 320x gra. mode */
4184 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 5 : 640x gra. mode */
4185 0x01,0x01,0xFC,0xF8,0x08,0x26,0x38, /* 6 : 800x gra. mode */
4186 0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28 /* 7 : 1024xgra. mode */
4187};
4188
4189UCHAR XGI_NTSC1024AdjTime[]=
4190{
4191 0xa7,0x07,0xf2,0x6e,0x17,0x8b,0x73,0x53,
4192 0x13,0x40,0x34,0xF4,0x63,0xBB,0xCC,0x7A,
4193 0x58,0xe4,0x73,0xd0,0x13
4194};
4195
4196XGI301C_Tap4TimingStruct HiTVTap4Timing[]=
4197{
4198 {0,{
4199 0x00,0x20,0x00,0x00,0x7F,0x20,0x02,0x7F, /* ; C0-C7 */
4200 0x7D,0x20,0x04,0x7F,0x7D,0x1F,0x06,0x7E, /* ; C8-CF */
4201 0x7C,0x1D,0x09,0x7E,0x7C,0x1B,0x0B,0x7E, /* ; D0-D7 */
4202 0x7C,0x19,0x0E,0x7D,0x7C,0x17,0x11,0x7C, /* ; D8-DF */
4203 0x7C,0x14,0x14,0x7C,0x7C,0x11,0x17,0x7C, /* ; E0-E7 */
4204 0x7D,0x0E,0x19,0x7C,0x7E,0x0B,0x1B,0x7C, /* ; EA-EF */
4205 0x7E,0x09,0x1D,0x7C,0x7F,0x06,0x1F,0x7C, /* ; F0-F7 */
4206 0x7F,0x04,0x20,0x7D,0x00,0x02,0x20,0x7E /* ; F8-FF */
4207 }
4208 }
4209};
4210
4211XGI301C_Tap4TimingStruct EnlargeTap4Timing[]=
4212{
4213 {0,{
4214 0x00,0x20,0x00,0x00,0x7F,0x20,0x02,0x7F, /* ; C0-C7 */
4215 0x7D,0x20,0x04,0x7F,0x7D,0x1F,0x06,0x7E, /* ; C8-CF */
4216 0x7C,0x1D,0x09,0x7E,0x7C,0x1B,0x0B,0x7E, /* ; D0-D7 */
4217 0x7C,0x19,0x0E,0x7D,0x7C,0x17,0x11,0x7C, /* ; D8-DF */
4218 0x7C,0x14,0x14,0x7C,0x7C,0x11,0x17,0x7C, /* ; E0-E7 */
4219 0x7D,0x0E,0x19,0x7C,0x7E,0x0B,0x1B,0x7C, /* ; EA-EF */
4220 0x7E,0x09,0x1D,0x7C,0x7F,0x06,0x1F,0x7C, /* ; F0-F7 */
4221 0x7F,0x04,0x20,0x7D,0x00,0x02,0x20,0x7E /* ; F8-FF */
4222 }
4223 }
4224};
4225
4226XGI301C_Tap4TimingStruct NoScaleTap4Timing[]=
4227{
4228 {0,{
4229 0x00,0x20,0x00,0x00,0x7F,0x20,0x02,0x7F, /* ; C0-C7 */
4230 0x7D,0x20,0x04,0x7F,0x7D,0x1F,0x06,0x7E, /* ; C8-CF */
4231 0x7C,0x1D,0x09,0x7E,0x7C,0x1B,0x0B,0x7E, /* ; D0-D7 */
4232 0x7C,0x19,0x0E,0x7D,0x7C,0x17,0x11,0x7C, /* ; D8-DF */
4233 0x7C,0x14,0x14,0x7C,0x7C,0x11,0x17,0x7C, /* ; E0-E7 */
4234 0x7D,0x0E,0x19,0x7C,0x7E,0x0B,0x1B,0x7C, /* ; EA-EF */
4235 0x7E,0x09,0x1D,0x7C,0x7F,0x06,0x1F,0x7C, /* ; F0-F7 */
4236 0x7F,0x04,0x20,0x7D,0x00,0x02,0x20,0x7E /* ; F8-FF */
4237 }
4238 }
4239};
4240
4241XGI301C_Tap4TimingStruct PALTap4Timing[]=
4242{
4243 {600, {
4244 0x05,0x19,0x05,0x7D,0x03,0x19,0x06,0x7E, /* ; C0-C7 */
4245 0x02,0x19,0x08,0x7D,0x01,0x18,0x0A,0x7D, /* ; C8-CF */
4246 0x00,0x18,0x0C,0x7C,0x7F,0x17,0x0E,0x7C, /* ; D0-D7 */
4247 0x7E,0x16,0x0F,0x7D,0x7E,0x14,0x11,0x7D, /* ; D8-DF */
4248 0x7D,0x13,0x13,0x7D,0x7D,0x11,0x14,0x7E, /* ; E0-E7 */
4249 0x7D,0x0F,0x16,0x7E,0x7D,0x0E,0x17,0x7E, /* ; EA-EF */
4250 0x7D,0x0C,0x18,0x7F,0x7D,0x0A,0x18,0x01, /* ; F0-F7 */
4251 0x7D,0x08,0x19,0x02,0x7D,0x06,0x19,0x04 /* ; F8-FF */
4252 }
4253 },
4254 {768, {
4255 0x08,0x12,0x08,0x7E,0x07,0x12,0x09,0x7E, /* ; C0-C7 */
4256 0x06,0x12,0x0A,0x7E,0x05,0x11,0x0B,0x7F, /* ; C8-CF */
4257 0x04,0x11,0x0C,0x7F,0x03,0x11,0x0C,0x00, /* ; D0-D7 */
4258 0x03,0x10,0x0D,0x00,0x02,0x0F,0x0E,0x01, /* ; D8-DF */
4259 0x01,0x0F,0x0F,0x01,0x01,0x0E,0x0F,0x02, /* ; E0-E7 */
4260 0x00,0x0D,0x10,0x03,0x7F,0x0C,0x11,0x04, /* ; EA-EF */
4261 0x7F,0x0C,0x11,0x04,0x7F,0x0B,0x11,0x05, /* ; F0-F7 */
4262 0x7E,0x0A,0x12,0x06,0x7E,0x09,0x12,0x07 /* ; F8-FF */
4263 }
4264 },
4265 {0xFFFF,
4266 {
4267 0x04,0x1A,0x04,0x7E,0x02,0x1B,0x05,0x7E, /* ; C0-C7 */
4268 0x01,0x1A,0x07,0x7E,0x00,0x1A,0x09,0x7D, /* ; C8-CF */
4269 0x7F,0x19,0x0B,0x7D,0x7E,0x18,0x0D,0x7D, /* ; D0-D7 */
4270 0x7D,0x17,0x10,0x7C,0x7D,0x15,0x12,0x7C, /* ; D8-DF */
4271 0x7C,0x14,0x14,0x7C,0x7C,0x12,0x15,0x7D, /* ; E0-E7 */
4272 0x7C,0x10,0x17,0x7D,0x7C,0x0D,0x18,0x7F, /* ; EA-EF */
4273 0x7D,0x0B,0x19,0x7F,0x7D,0x09,0x1A,0x00, /* ; F0-F7 */
4274 0x7D,0x07,0x1A,0x02,0x7E,0x05,0x1B,0x02 /* ; F8-FF */
4275 }
4276 }
4277};
4278
4279XGI301C_Tap4TimingStruct NTSCTap4Timing[]=
4280{
4281 {480, {
4282 0x04,0x1A,0x04,0x7E,0x03,0x1A,0x06,0x7D, /* ; C0-C7 */
4283 0x01,0x1A,0x08,0x7D,0x00,0x19,0x0A,0x7D, /* ; C8-CF */
4284 0x7F,0x19,0x0C,0x7C,0x7E,0x18,0x0E,0x7C, /* ; D0-D7 */
4285 0x7E,0x17,0x10,0x7B,0x7D,0x15,0x12,0x7C, /* ; D8-DF */
4286 0x7D,0x13,0x13,0x7D,0x7C,0x12,0x15,0x7D, /* ; E0-E7 */
4287 0x7C,0x10,0x17,0x7D,0x7C,0x0E,0x18,0x7E, /* ; EA-EF */
4288 0x7D,0x0C,0x19,0x7E,0x7D,0x0A,0x19,0x00, /* ; F0-F7 */
4289 0x7D,0x08,0x1A,0x01,0x7E,0x06,0x1A,0x02 /* ; F8-FF */
4290 }
4291 },
4292 {600, {
4293 0x07,0x14,0x07,0x7E,0x06,0x14,0x09,0x7D, /* ; C0-C7 */
4294 0x05,0x14,0x0A,0x7D,0x04,0x13,0x0B,0x7E, /* ; C8-CF */
4295 0x03,0x13,0x0C,0x7E,0x02,0x12,0x0D,0x7F, /* ; D0-D7 */
4296 0x01,0x12,0x0E,0x7F,0x01,0x11,0x0F,0x7F, /* ; D8-DF */
4297 0x01,0x10,0x10,0x00,0x7F,0x0F,0x11,0x01, /* ; E0-E7 */
4298 0x7F,0x0E,0x12,0x01,0x7E,0x0D,0x12,0x03, /* ; EA-EF */
4299 0x7E,0x0C,0x13,0x03,0x7E,0x0B,0x13,0x04, /* ; F0-F7 */
4300 0x7E,0x0A,0x14,0x04,0x7D,0x09,0x14,0x06 /* ; F8-FF */
4301 }
4302 },
4303 {0xFFFF,
4304 {
4305 0x09,0x0F,0x09,0x7F,0x08,0x0F,0x09,0x00, /* ; C0-C7 */
4306 0x07,0x0F,0x0A,0x00,0x06,0x0F,0x0A,0x01, /* ; C8-CF */
4307 0x06,0x0E,0x0B,0x01,0x05,0x0E,0x0B,0x02, /* ; D0-D7 */
4308 0x04,0x0E,0x0C,0x02,0x04,0x0D,0x0C,0x03, /* ; D8-DF */
4309 0x03,0x0D,0x0D,0x03,0x02,0x0C,0x0D,0x05, /* ; E0-E7 */
4310 0x02,0x0C,0x0E,0x04,0x01,0x0B,0x0E,0x06, /* ; EA-EF */
4311 0x01,0x0B,0x0E,0x06,0x00,0x0A,0x0F,0x07, /* ; F0-F7 */
4312 0x00,0x0A,0x0F,0x07,0x00,0x09,0x0F,0x08 /* ; F8-FF */
4313 }
4314 }
4315};
4316
4317XGI301C_Tap4TimingStruct YPbPr525pTap4Timing[]=
4318{
4319 {480, {
4320 0x04,0x1A,0x04,0x7E,0x03,0x1A,0x06,0x7D, /* ; C0-C7 */
4321 0x01,0x1A,0x08,0x7D,0x00,0x19,0x0A,0x7D, /* ; C8-CF */
4322 0x7F,0x19,0x0C,0x7C,0x7E,0x18,0x0E,0x7C, /* ; D0-D7 */
4323 0x7E,0x17,0x10,0x7B,0x7D,0x15,0x12,0x7C, /* ; D8-DF */
4324 0x7D,0x13,0x13,0x7D,0x7C,0x12,0x15,0x7D, /* ; E0-E7 */
4325 0x7C,0x10,0x17,0x7D,0x7C,0x0E,0x18,0x7E, /* ; EA-EF */
4326 0x7D,0x0C,0x19,0x7E,0x7D,0x0A,0x19,0x00, /* ; F0-F7 */
4327 0x7D,0x08,0x1A,0x01,0x7E,0x06,0x1A,0x02 /* ; F8-FF */
4328 }
4329 },
4330 {600, {
4331 0x07,0x14,0x07,0x7E,0x06,0x14,0x09,0x7D, /* ; C0-C7 */
4332 0x05,0x14,0x0A,0x7D,0x04,0x13,0x0B,0x7E, /* ; C8-CF */
4333 0x03,0x13,0x0C,0x7E,0x02,0x12,0x0D,0x7F, /* ; D0-D7 */
4334 0x01,0x12,0x0E,0x7F,0x01,0x11,0x0F,0x7F, /* ; D8-DF */
4335 0x01,0x10,0x10,0x00,0x7F,0x0F,0x11,0x01, /* ; E0-E7 */
4336 0x7F,0x0E,0x12,0x01,0x7E,0x0D,0x12,0x03, /* ; EA-EF */
4337 0x7E,0x0C,0x13,0x03,0x7E,0x0B,0x13,0x04, /* ; F0-F7 */
4338 0x7E,0x0A,0x14,0x04,0x7D,0x09,0x14,0x06 /* ; F8-FF */
4339 }
4340 },
4341 {0xFFFF,
4342 {
4343 0x09,0x0F,0x09,0x7F,0x08,0x0F,0x09,0x00, /* ; C0-C7 */
4344 0x07,0x0F,0x0A,0x00,0x06,0x0F,0x0A,0x01, /* ; C8-CF */
4345 0x06,0x0E,0x0B,0x01,0x05,0x0E,0x0B,0x02, /* ; D0-D7 */
4346 0x04,0x0E,0x0C,0x02,0x04,0x0D,0x0C,0x03, /* ; D8-DF */
4347 0x03,0x0D,0x0D,0x03,0x02,0x0C,0x0D,0x05, /* ; E0-E7 */
4348 0x02,0x0C,0x0E,0x04,0x01,0x0B,0x0E,0x06, /* ; EA-EF */
4349 0x01,0x0B,0x0E,0x06,0x00,0x0A,0x0F,0x07, /* ; F0-F7 */
4350 0x00,0x0A,0x0F,0x07,0x00,0x09,0x0F,0x08 /* ; F8-FF */
4351 }
4352 }
4353};
4354
4355XGI301C_Tap4TimingStruct YPbPr525iTap4Timing[]=
4356{
4357 {480, {
4358 0x04,0x1A,0x04,0x7E,0x03,0x1A,0x06,0x7D, /* ; C0-C7 */
4359 0x01,0x1A,0x08,0x7D,0x00,0x19,0x0A,0x7D, /* ; C8-CF */
4360 0x7F,0x19,0x0C,0x7C,0x7E,0x18,0x0E,0x7C, /* ; D0-D7 */
4361 0x7E,0x17,0x10,0x7B,0x7D,0x15,0x12,0x7C, /* ; D8-DF */
4362 0x7D,0x13,0x13,0x7D,0x7C,0x12,0x15,0x7D, /* ; E0-E7 */
4363 0x7C,0x10,0x17,0x7D,0x7C,0x0E,0x18,0x7E, /* ; EA-EF */
4364 0x7D,0x0C,0x19,0x7E,0x7D,0x0A,0x19,0x00, /* ; F0-F7 */
4365 0x7D,0x08,0x1A,0x01,0x7E,0x06,0x1A,0x02 /* ; F8-FF */
4366 }
4367 },
4368 {600, {
4369 0x07,0x14,0x07,0x7E,0x06,0x14,0x09,0x7D, /* ; C0-C7 */
4370 0x05,0x14,0x0A,0x7D,0x04,0x13,0x0B,0x7E, /* ; C8-CF */
4371 0x03,0x13,0x0C,0x7E,0x02,0x12,0x0D,0x7F, /* ; D0-D7 */
4372 0x01,0x12,0x0E,0x7F,0x01,0x11,0x0F,0x7F, /* ; D8-DF */
4373 0x01,0x10,0x10,0x00,0x7F,0x0F,0x11,0x01, /* ; E0-E7 */
4374 0x7F,0x0E,0x12,0x01,0x7E,0x0D,0x12,0x03, /* ; EA-EF */
4375 0x7E,0x0C,0x13,0x03,0x7E,0x0B,0x13,0x04, /* ; F0-F7 */
4376 0x7E,0x0A,0x14,0x04,0x7D,0x09,0x14,0x06 /* ; F8-FF */
4377 }
4378 },
4379 {0xFFFF,
4380 {
4381 0x09,0x0F,0x09,0x7F,0x08,0x0F,0x09,0x00, /* ; C0-C7 */
4382 0x07,0x0F,0x0A,0x00,0x06,0x0F,0x0A,0x01, /* ; C8-CF */
4383 0x06,0x0E,0x0B,0x01,0x05,0x0E,0x0B,0x02, /* ; D0-D7 */
4384 0x04,0x0E,0x0C,0x02,0x04,0x0D,0x0C,0x03, /* ; D8-DF */
4385 0x03,0x0D,0x0D,0x03,0x02,0x0C,0x0D,0x05, /* ; E0-E7 */
4386 0x02,0x0C,0x0E,0x04,0x01,0x0B,0x0E,0x06, /* ; EA-EF */
4387 0x01,0x0B,0x0E,0x06,0x00,0x0A,0x0F,0x07, /* ; F0-F7 */
4388 0x00,0x0A,0x0F,0x07,0x00,0x09,0x0F,0x08 /* ; F8-FF */
4389 }
4390 }
4391};
4392
4393XGI301C_Tap4TimingStruct YPbPr750pTap4Timing[]=
4394{ {0xFFFF,
4395 {
4396 0x05,0x19,0x05,0x7D,0x03,0x19,0x06,0x7E, /* ; C0-C7 */
4397 0x02,0x19,0x08,0x7D,0x01,0x18,0x0A,0x7D, /* ; C8-CF */
4398 0x00,0x18,0x0C,0x7C,0x7F,0x17,0x0E,0x7C, /* ; D0-D7 */
4399 0x7E,0x16,0x0F,0x7D,0x7E,0x14,0x11,0x7D, /* ; D8-DF */
4400 0x7D,0x13,0x13,0x7D,0x7D,0x11,0x14,0x7E, /* ; E0-E7 */
4401 0x7D,0x0F,0x16,0x7E,0x7D,0x0E,0x17,0x7E, /* ; EA-EF */
4402 0x7D,0x0C,0x18,0x7F,0x7D,0x0A,0x18,0x01, /* ; F0-F7 */
4403 0x7D,0x08,0x19,0x02,0x7D,0x06,0x19,0x04 /* F8-FF */
4404 }
4405 }
4406};
diff --git a/drivers/staging/xgifb/vb_util.c b/drivers/staging/xgifb/vb_util.c
new file mode 100644
index 000000000000..87531b49b739
--- /dev/null
+++ b/drivers/staging/xgifb/vb_util.c
@@ -0,0 +1,263 @@
1#include "osdef.h"
2#include "vb_def.h"
3#include "vgatypes.h"
4#include "vb_struct.h"
5
6#ifdef LINUX_KERNEL
7#include "XGIfb.h"
8#include <asm/io.h>
9#include <linux/types.h>
10#endif
11
12#ifdef TC
13#include <stdio.h>
14#include <string.h>
15#include <conio.h>
16#include <dos.h>
17#endif
18
19#ifdef WIN2000
20#include <dderror.h>
21#include <devioctl.h>
22#include <miniport.h>
23#include <ntddvdeo.h>
24#include <video.h>
25
26#include "xgiv.h"
27#include "dd_i2c.h"
28#include "tools.h"
29#endif
30
31#ifdef LINUX_XF86
32#include "xf86.h"
33#include "xf86PciInfo.h"
34#include "xgi.h"
35#include "xgi_regs.h"
36#endif
37
38
39
40
41void XGINew_SetReg1( ULONG , USHORT , USHORT ) ;
42void XGINew_SetReg2( ULONG , USHORT , USHORT ) ;
43void XGINew_SetReg3( ULONG , USHORT ) ;
44void XGINew_SetReg4( ULONG , ULONG ) ;
45UCHAR XGINew_GetReg1( ULONG , USHORT) ;
46UCHAR XGINew_GetReg2( ULONG ) ;
47ULONG XGINew_GetReg3( ULONG ) ;
48void XGINew_ClearDAC( PUCHAR ) ;
49void XGINew_SetRegANDOR(ULONG Port,USHORT Index,USHORT DataAND,USHORT DataOR);
50void XGINew_SetRegOR(ULONG Port,USHORT Index,USHORT DataOR);
51void XGINew_SetRegAND(ULONG Port,USHORT Index,USHORT DataAND);
52
53
54/* --------------------------------------------------------------------- */
55/* Function : XGINew_SetReg1 */
56/* Input : */
57/* Output : */
58/* Description : SR CRTC GR */
59/* --------------------------------------------------------------------- */
60void XGINew_SetReg1( ULONG port , USHORT index , USHORT data )
61{
62#ifdef LINUX_XF86
63 OutPortByte( ( PUCHAR )(ULONG)port , index ) ;
64 OutPortByte( ( PUCHAR )(ULONG)port + 1 , data ) ;
65#else
66 OutPortByte( port , index ) ;
67 OutPortByte( port + 1 , data ) ;
68#endif
69}
70
71
72/* --------------------------------------------------------------------- */
73/* Function : XGINew_SetReg2 */
74/* Input : */
75/* Output : */
76/* Description : AR( 3C0 ) */
77/* --------------------------------------------------------------------- */
78/*void XGINew_SetReg2( ULONG port , USHORT index , USHORT data )
79{
80 InPortByte( ( PUCHAR )port + 0x3da - 0x3c0 ) ;
81 OutPortByte( XGINew_P3c0 , index ) ;
82 OutPortByte( XGINew_P3c0 , data ) ;
83 OutPortByte( XGINew_P3c0 , 0x20 ) ;
84}*/
85
86
87/* --------------------------------------------------------------------- */
88/* Function : */
89/* Input : */
90/* Output : */
91/* Description : */
92/* --------------------------------------------------------------------- */
93void XGINew_SetReg3( ULONG port , USHORT data )
94{
95 OutPortByte( port , data ) ;
96}
97
98
99/* --------------------------------------------------------------------- */
100/* Function : XGINew_SetReg4 */
101/* Input : */
102/* Output : */
103/* Description : */
104/* --------------------------------------------------------------------- */
105void XGINew_SetReg4( ULONG port , ULONG data )
106{
107 OutPortLong( port , data ) ;
108}
109
110
111/* --------------------------------------------------------------------- */
112/* Function : XGINew_GetReg1 */
113/* Input : */
114/* Output : */
115/* Description : */
116/* --------------------------------------------------------------------- */
117UCHAR XGINew_GetReg1( ULONG port , USHORT index )
118{
119 UCHAR data ;
120
121#ifdef LINUX_XF86
122 OutPortByte( ( PUCHAR )(ULONG)port , index ) ;
123 data = InPortByte( ( PUCHAR )(ULONG)port + 1 ) ;
124#else
125 OutPortByte( port , index ) ;
126 data = InPortByte( port + 1 ) ;
127#endif
128
129 return( data ) ;
130}
131
132
133/* --------------------------------------------------------------------- */
134/* Function : XGINew_GetReg2 */
135/* Input : */
136/* Output : */
137/* Description : */
138/* --------------------------------------------------------------------- */
139UCHAR XGINew_GetReg2( ULONG port )
140{
141 UCHAR data ;
142
143 data = InPortByte( port ) ;
144
145 return( data ) ;
146}
147
148
149/* --------------------------------------------------------------------- */
150/* Function : XGINew_GetReg3 */
151/* Input : */
152/* Output : */
153/* Description : */
154/* --------------------------------------------------------------------- */
155ULONG XGINew_GetReg3( ULONG port )
156{
157 ULONG data ;
158
159 data = InPortLong( port ) ;
160
161 return( data ) ;
162}
163
164
165
166/* --------------------------------------------------------------------- */
167/* Function : XGINew_SetRegANDOR */
168/* Input : */
169/* Output : */
170/* Description : */
171/* --------------------------------------------------------------------- */
172void XGINew_SetRegANDOR( ULONG Port , USHORT Index , USHORT DataAND , USHORT DataOR )
173{
174 USHORT temp ;
175
176 temp = XGINew_GetReg1( Port , Index ) ; /* XGINew_Part1Port index 02 */
177 temp = ( temp & ( DataAND ) ) | DataOR ;
178 XGINew_SetReg1( Port , Index , temp ) ;
179}
180
181
182/* --------------------------------------------------------------------- */
183/* Function : XGINew_SetRegAND */
184/* Input : */
185/* Output : */
186/* Description : */
187/* --------------------------------------------------------------------- */
188void XGINew_SetRegAND(ULONG Port,USHORT Index,USHORT DataAND)
189{
190 USHORT temp ;
191
192 temp = XGINew_GetReg1( Port , Index ) ; /* XGINew_Part1Port index 02 */
193 temp &= DataAND ;
194 XGINew_SetReg1( Port , Index , temp ) ;
195}
196
197
198/* --------------------------------------------------------------------- */
199/* Function : XGINew_SetRegOR */
200/* Input : */
201/* Output : */
202/* Description : */
203/* --------------------------------------------------------------------- */
204void XGINew_SetRegOR( ULONG Port , USHORT Index , USHORT DataOR )
205{
206 USHORT temp ;
207
208 temp = XGINew_GetReg1( Port , Index ) ; /* XGINew_Part1Port index 02 */
209 temp |= DataOR ;
210 XGINew_SetReg1( Port , Index , temp ) ;
211}
212
213
214/* --------------------------------------------------------------------- */
215/* Function : NewDelaySecond */
216/* Input : */
217/* Output : */
218/* Description : */
219/* --------------------------------------------------------------------- */
220void NewDelaySeconds( int seconds )
221{
222#ifdef WIN2000
223 int j ;
224#endif
225 int i ;
226
227
228 for( i = 0 ; i < seconds ; i++ )
229 {
230#ifdef TC
231 delay( 1000 ) ;
232#endif
233
234#ifdef WIN2000
235
236 for ( j = 0 ; j < 20000 ; j++ )
237 VideoPortStallExecution( 50 ) ;
238#endif
239
240#ifdef WINCE_HEADER
241#endif
242
243#ifdef LINUX_KERNEL
244#endif
245 }
246}
247
248
249/* --------------------------------------------------------------------- */
250/* Function : Newdebugcode */
251/* Input : */
252/* Output : */
253/* Description : */
254/* --------------------------------------------------------------------- */
255void Newdebugcode( UCHAR code )
256{
257// OutPortByte ( 0x80 , code ) ;
258 /* OutPortByte ( 0x300 , code ) ; */
259 /* NewDelaySeconds( 0x3 ) ; */
260}
261
262
263
diff --git a/drivers/staging/xgifb/vb_util.h b/drivers/staging/xgifb/vb_util.h
new file mode 100644
index 000000000000..91779d8cfdc6
--- /dev/null
+++ b/drivers/staging/xgifb/vb_util.h
@@ -0,0 +1,15 @@
1#ifndef _VBUTIL_
2#define _VBUTIL_
3extern void NewDelaySeconds( int );
4extern void Newdebugcode( UCHAR );
5extern void XGINew_SetReg1(ULONG, USHORT, USHORT);
6extern void XGINew_SetReg3(ULONG, USHORT);
7extern UCHAR XGINew_GetReg1(ULONG, USHORT);
8extern UCHAR XGINew_GetReg2(ULONG);
9extern void XGINew_SetReg4(ULONG, ULONG);
10extern ULONG XGINew_GetReg3(ULONG);
11extern void XGINew_SetRegOR(ULONG Port,USHORT Index,USHORT DataOR);
12extern void XGINew_SetRegAND(ULONG Port,USHORT Index,USHORT DataAND);
13extern void XGINew_SetRegANDOR(ULONG Port,USHORT Index,USHORT DataAND,USHORT DataOR);
14#endif
15
diff --git a/drivers/staging/xgifb/vgatypes.h b/drivers/staging/xgifb/vgatypes.h
new file mode 100644
index 000000000000..295ea860ae47
--- /dev/null
+++ b/drivers/staging/xgifb/vgatypes.h
@@ -0,0 +1,325 @@
1
2#ifndef _VGATYPES_
3#define _VGATYPES_
4
5#include "osdef.h"
6
7#ifdef LINUX_XF86
8#include "xf86Version.h"
9#include "xf86Pci.h"
10#endif
11
12#ifdef LINUX_KERNEL /* We don't want the X driver to depend on kernel source */
13#include <linux/ioctl.h>
14#endif
15
16#ifndef FALSE
17#define FALSE 0
18#endif
19
20#ifndef TRUE
21#define TRUE 1
22#endif
23
24#ifndef NULL
25#define NULL 0
26#endif
27
28#ifndef CHAR
29typedef char CHAR;
30#endif
31
32#ifndef SHORT
33typedef short SHORT;
34#endif
35
36#ifndef LONG
37typedef long LONG;
38#endif
39
40#ifndef UCHAR
41typedef unsigned char UCHAR;
42#endif
43
44#ifndef USHORT
45typedef unsigned short USHORT;
46#endif
47
48#ifndef ULONG
49typedef unsigned long ULONG;
50#endif
51
52#ifndef PUCHAR
53typedef UCHAR *PUCHAR;
54#endif
55
56#ifndef PUSHORT
57typedef USHORT *PUSHORT;
58#endif
59
60#ifndef PLONGU
61typedef ULONG *PULONG;
62#endif
63
64#ifndef VOID
65typedef void VOID;
66#endif
67
68#ifndef PVOID
69typedef void *PVOID;
70#endif
71
72#ifndef BOOLEAN
73typedef UCHAR BOOLEAN;
74#endif
75/*
76#ifndef bool
77typedef UCHAR bool;
78#endif
79*/
80#ifdef LINUX_KERNEL
81typedef unsigned long XGIIOADDRESS;
82#endif
83
84#ifdef LINUX_XF86
85#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,0,0,0)
86typedef unsigned char IOADDRESS;
87typedef unsigned char XGIIOADDRESS;
88#else
89typedef IOADDRESS XGIIOADDRESS;
90#endif
91#endif
92
93#ifndef VBIOS_VER_MAX_LENGTH
94#define VBIOS_VER_MAX_LENGTH 4
95#endif
96
97#ifndef WIN2000
98
99#ifndef LINUX_KERNEL /* For the linux kernel, this is defined in xgifb.h */
100#ifndef XGI_CHIP_TYPE
101typedef enum _XGI_CHIP_TYPE {
102 XGI_VGALegacy = 0,
103#ifdef LINUX_XF86
104 XGI_530,
105 XGI_OLD,
106#endif
107 XGI_300,
108 XGI_630,
109 XGI_640,
110 XGI_315H,
111 XGI_315,
112 XGI_315PRO,
113 XGI_550,
114 XGI_650,
115 XGI_650M,
116 XGI_740,
117 XGI_330,
118 XGI_661,
119 XGI_660,
120 XGI_760,
121 XG40 = 32,
122 XG41,
123 XG42,
124 XG45,
125 XG20 = 48,
126 XG21,
127 XG27,
128 MAX_XGI_CHIP
129} XGI_CHIP_TYPE;
130#endif
131#endif
132
133#ifndef XGI_VB_CHIP_TYPE
134typedef enum _XGI_VB_CHIP_TYPE {
135 VB_CHIP_Legacy = 0,
136 VB_CHIP_301,
137 VB_CHIP_301B,
138 VB_CHIP_301LV,
139 VB_CHIP_302,
140 VB_CHIP_302B,
141 VB_CHIP_302LV,
142 VB_CHIP_301C,
143 VB_CHIP_302ELV,
144 VB_CHIP_UNKNOWN, /* other video bridge or no video bridge */
145 MAX_VB_CHIP
146} XGI_VB_CHIP_TYPE;
147#endif
148
149#ifndef XGI_LCD_TYPE
150typedef enum _XGI_LCD_TYPE {
151 LCD_INVALID = 0,
152 LCD_320x480, /* FSTN, DSTN */
153 LCD_640x480,
154 LCD_640x480_2, /* FSTN, DSTN */
155 LCD_640x480_3, /* FSTN, DSTN */
156 LCD_800x600,
157 LCD_848x480,
158 LCD_1024x600,
159 LCD_1024x768,
160 LCD_1152x768,
161 LCD_1152x864,
162 LCD_1280x720,
163 LCD_1280x768,
164 LCD_1280x800,
165 LCD_1280x960,
166 LCD_1280x1024,
167 LCD_1400x1050,
168 LCD_1600x1200,
169 LCD_1680x1050,
170 LCD_1920x1440,
171 LCD_2048x1536,
172 LCD_CUSTOM,
173 LCD_UNKNOWN
174} XGI_LCD_TYPE;
175#endif
176
177#endif /* not WIN2000 */
178
179#ifndef PXGI_DSReg
180typedef struct _XGI_DSReg
181{
182 UCHAR jIdx;
183 UCHAR jVal;
184} XGI_DSReg, *PXGI_DSReg;
185#endif
186
187#ifndef XGI_HW_DEVICE_INFO
188
189typedef struct _XGI_HW_DEVICE_INFO XGI_HW_DEVICE_INFO, *PXGI_HW_DEVICE_INFO;
190
191typedef BOOLEAN (*PXGI_QUERYSPACE) (PXGI_HW_DEVICE_INFO, ULONG, ULONG, ULONG *);
192
193struct _XGI_HW_DEVICE_INFO
194{
195 ULONG ulExternalChip; /* NO VB or other video bridge*/
196 /* if ujVBChipID = VB_CHIP_UNKNOWN, */
197#ifdef LINUX_XF86
198 PCITAG PciTag; /* PCI Tag */
199#endif
200
201 PUCHAR pjVirtualRomBase; /* ROM image */
202
203 BOOLEAN UseROM; /* Use the ROM image if provided */
204
205 PVOID pDevice;
206
207 PUCHAR pjVideoMemoryAddress;/* base virtual memory address */
208 /* of Linear VGA memory */
209
210 ULONG ulVideoMemorySize; /* size, in bytes, of the memory on the board */
211
212 PUCHAR pjIOAddress; /* base I/O address of VGA ports (0x3B0) */
213
214 PUCHAR pjCustomizedROMImage;
215
216 PUCHAR pj2ndVideoMemoryAddress;
217 ULONG ul2ndVideoMemorySize;
218
219 PUCHAR pj2ndIOAddress;
220/*#ifndef WIN2000
221 XGIIOADDRESS pjIOAddress; // base I/O address of VGA ports (0x3B0)
222#endif */
223 UCHAR jChipType; /* Used to Identify Graphics Chip */
224 /* defined in the data structure type */
225 /* "XGI_CHIP_TYPE" */
226
227 UCHAR jChipRevision; /* Used to Identify Graphics Chip Revision */
228
229 UCHAR ujVBChipID; /* the ID of video bridge */
230 /* defined in the data structure type */
231 /* "XGI_VB_CHIP_TYPE" */
232
233 BOOLEAN bNewScratch;
234
235 ULONG ulCRT2LCDType; /* defined in the data structure type */
236
237 ULONG usExternalChip; /* NO VB or other video bridge (other than */
238 /* video bridge) */
239
240 BOOLEAN bIntegratedMMEnabled;/* supporting integration MM enable */
241
242 BOOLEAN bSkipDramSizing; /* True: Skip video memory sizing. */
243
244 BOOLEAN bSkipSense;
245
246 BOOLEAN bIsPowerSaving; /* True: XGIInit() is invoked by power management,
247 otherwise by 2nd adapter's initialzation */
248
249 PXGI_DSReg pSR; /* restore SR registers in initial function. */
250 /* end data :(idx, val) = (FF, FF). */
251 /* Note : restore SR registers if */
252 /* bSkipDramSizing = TRUE */
253
254 PXGI_DSReg pCR; /* restore CR registers in initial function. */
255 /* end data :(idx, val) = (FF, FF) */
256 /* Note : restore cR registers if */
257 /* bSkipDramSizing = TRUE */
258/*
259#endif
260*/
261
262 PXGI_QUERYSPACE pQueryVGAConfigSpace;
263
264 PXGI_QUERYSPACE pQueryNorthBridgeSpace;
265
266 UCHAR szVBIOSVer[VBIOS_VER_MAX_LENGTH];
267
268};
269#endif
270
271/* Addtional IOCTL for communication xgifb <> X driver */
272/* If changing this, xgifb.h must also be changed (for xgifb) */
273
274#ifdef LINUX_XF86 /* We don't want the X driver to depend on the kernel source */
275
276/* ioctl for identifying and giving some info (esp. memory heap start) */
277#define XGIFB_GET_INFO 0x80046ef8 /* Wow, what a terrible hack... */
278
279/* Structure argument for XGIFB_GET_INFO ioctl */
280typedef struct _XGIFB_INFO xgifb_info, *pxgifb_info;
281
282struct _XGIFB_INFO {
283 CARD32 xgifb_id; /* for identifying xgifb */
284#ifndef XGIFB_ID
285#define XGIFB_ID 0x53495346 /* Identify myself with 'XGIF' */
286#endif
287 CARD32 chip_id; /* PCI ID of detected chip */
288 CARD32 memory; /* video memory in KB which xgifb manages */
289 CARD32 heapstart; /* heap start (= xgifb "mem" argument) in KB */
290 CARD8 fbvidmode; /* current xgifb mode */
291
292 CARD8 xgifb_version;
293 CARD8 xgifb_revision;
294 CARD8 xgifb_patchlevel;
295
296 CARD8 xgifb_caps; /* xgifb's capabilities */
297
298 CARD32 xgifb_tqlen; /* turbo queue length (in KB) */
299
300 CARD32 xgifb_pcibus; /* The card's PCI ID */
301 CARD32 xgifb_pcislot;
302 CARD32 xgifb_pcifunc;
303
304 CARD8 xgifb_lcdpdc;
305
306 CARD8 xgifb_lcda;
307
308 CARD32 xgifb_vbflags;
309 CARD32 xgifb_currentvbflags;
310
311 CARD32 xgifb_scalelcd;
312 CARD32 xgifb_specialtiming;
313
314 CARD8 xgifb_haveemi;
315 CARD8 xgifb_emi30,xgifb_emi31,xgifb_emi32,xgifb_emi33;
316 CARD8 xgifb_haveemilcd;
317
318 CARD8 xgifb_lcdpdca;
319
320 CARD8 reserved[212]; /* for future use */
321};
322#endif
323
324#endif
325
diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c
index e89304c72568..b53deee25d74 100644
--- a/drivers/telephony/ixj.c
+++ b/drivers/telephony/ixj.c
@@ -5879,20 +5879,13 @@ out:
5879static int ixj_build_filter_cadence(IXJ *j, IXJ_FILTER_CADENCE __user * cp) 5879static int ixj_build_filter_cadence(IXJ *j, IXJ_FILTER_CADENCE __user * cp)
5880{ 5880{
5881 IXJ_FILTER_CADENCE *lcp; 5881 IXJ_FILTER_CADENCE *lcp;
5882 lcp = kmalloc(sizeof(IXJ_FILTER_CADENCE), GFP_KERNEL); 5882 lcp = memdup_user(cp, sizeof(IXJ_FILTER_CADENCE));
5883 if (lcp == NULL) { 5883 if (IS_ERR(lcp)) {
5884 if(ixjdebug & 0x0001) { 5884 if(ixjdebug & 0x0001) {
5885 printk(KERN_INFO "Could not allocate memory for cadence\n"); 5885 printk(KERN_INFO "Could not allocate memory for cadence or could not copy cadence to kernel\n");
5886 } 5886 }
5887 return -ENOMEM; 5887 return PTR_ERR(lcp);
5888 } 5888 }
5889 if (copy_from_user(lcp, cp, sizeof(IXJ_FILTER_CADENCE))) {
5890 if(ixjdebug & 0x0001) {
5891 printk(KERN_INFO "Could not copy cadence to kernel\n");
5892 }
5893 kfree(lcp);
5894 return -EFAULT;
5895 }
5896 if (lcp->filter > 5) { 5889 if (lcp->filter > 5) {
5897 if(ixjdebug & 0x0001) { 5890 if(ixjdebug & 0x0001) {
5898 printk(KERN_INFO "Cadence out of range\n"); 5891 printk(KERN_INFO "Cadence out of range\n");
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 0c2f14ff9696..61d75507d5d0 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -1201,7 +1201,7 @@ made_compressed_probe:
1201 if (rcv->urb == NULL) { 1201 if (rcv->urb == NULL) {
1202 dev_dbg(&intf->dev, 1202 dev_dbg(&intf->dev,
1203 "out of memory (read urbs usb_alloc_urb)\n"); 1203 "out of memory (read urbs usb_alloc_urb)\n");
1204 goto alloc_fail7; 1204 goto alloc_fail6;
1205 } 1205 }
1206 1206
1207 rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 1207 rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
@@ -1225,7 +1225,7 @@ made_compressed_probe:
1225 if (snd->urb == NULL) { 1225 if (snd->urb == NULL) {
1226 dev_dbg(&intf->dev, 1226 dev_dbg(&intf->dev,
1227 "out of memory (write urbs usb_alloc_urb)"); 1227 "out of memory (write urbs usb_alloc_urb)");
1228 goto alloc_fail7; 1228 goto alloc_fail8;
1229 } 1229 }
1230 1230
1231 if (usb_endpoint_xfer_int(epwrite)) 1231 if (usb_endpoint_xfer_int(epwrite))
@@ -1264,6 +1264,7 @@ made_compressed_probe:
1264 i = device_create_file(&intf->dev, 1264 i = device_create_file(&intf->dev,
1265 &dev_attr_iCountryCodeRelDate); 1265 &dev_attr_iCountryCodeRelDate);
1266 if (i < 0) { 1266 if (i < 0) {
1267 device_remove_file(&intf->dev, &dev_attr_wCountryCodes);
1267 kfree(acm->country_codes); 1268 kfree(acm->country_codes);
1268 goto skip_countries; 1269 goto skip_countries;
1269 } 1270 }
@@ -1300,6 +1301,7 @@ alloc_fail8:
1300 usb_free_urb(acm->wb[i].urb); 1301 usb_free_urb(acm->wb[i].urb);
1301alloc_fail7: 1302alloc_fail7:
1302 acm_read_buffers_free(acm); 1303 acm_read_buffers_free(acm);
1304alloc_fail6:
1303 for (i = 0; i < num_rx_buf; i++) 1305 for (i = 0; i < num_rx_buf; i++)
1304 usb_free_urb(acm->ru[i].urb); 1306 usb_free_urb(acm->ru[i].urb);
1305 usb_free_urb(acm->ctrlurb); 1307 usb_free_urb(acm->ctrlurb);
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index ded550eda5d9..de98a94d1853 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1328,6 +1328,7 @@ int usb_resume(struct device *dev, pm_message_t msg)
1328 1328
1329 /* For all other calls, take the device back to full power and 1329 /* For all other calls, take the device back to full power and
1330 * tell the PM core in case it was autosuspended previously. 1330 * tell the PM core in case it was autosuspended previously.
1331 * Unbind the interfaces that will need rebinding later.
1331 */ 1332 */
1332 } else { 1333 } else {
1333 status = usb_resume_both(udev, msg); 1334 status = usb_resume_both(udev, msg);
@@ -1336,6 +1337,7 @@ int usb_resume(struct device *dev, pm_message_t msg)
1336 pm_runtime_set_active(dev); 1337 pm_runtime_set_active(dev);
1337 pm_runtime_enable(dev); 1338 pm_runtime_enable(dev);
1338 udev->last_busy = jiffies; 1339 udev->last_busy = jiffies;
1340 do_unbind_rebind(udev, DO_REBIND);
1339 } 1341 }
1340 } 1342 }
1341 1343
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 649c0c5f7158..591ae9fde199 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -295,6 +295,7 @@ config USB_GADGET_S3C_HSOTG
295 boolean "S3C HS/OtG USB Device controller" 295 boolean "S3C HS/OtG USB Device controller"
296 depends on S3C_DEV_USB_HSOTG 296 depends on S3C_DEV_USB_HSOTG
297 select USB_GADGET_S3C_HSOTG_PIO 297 select USB_GADGET_S3C_HSOTG_PIO
298 select USB_GADGET_DUALSPEED
298 help 299 help
299 The Samsung S3C64XX USB2.0 high-speed gadget controller 300 The Samsung S3C64XX USB2.0 high-speed gadget controller
300 integrated into the S3C64XX series SoC. 301 integrated into the S3C64XX series SoC.
diff --git a/drivers/usb/gadget/f_audio.c b/drivers/usb/gadget/f_audio.c
index 43bf44514c41..b91115f84b13 100644
--- a/drivers/usb/gadget/f_audio.c
+++ b/drivers/usb/gadget/f_audio.c
@@ -101,7 +101,7 @@ static struct uac_feature_unit_descriptor_0 feature_unit_desc = {
101static struct usb_audio_control mute_control = { 101static struct usb_audio_control mute_control = {
102 .list = LIST_HEAD_INIT(mute_control.list), 102 .list = LIST_HEAD_INIT(mute_control.list),
103 .name = "Mute Control", 103 .name = "Mute Control",
104 .type = UAC_MUTE_CONTROL, 104 .type = UAC_FU_MUTE,
105 /* Todo: add real Mute control code */ 105 /* Todo: add real Mute control code */
106 .set = generic_set_cmd, 106 .set = generic_set_cmd,
107 .get = generic_get_cmd, 107 .get = generic_get_cmd,
@@ -110,7 +110,7 @@ static struct usb_audio_control mute_control = {
110static struct usb_audio_control volume_control = { 110static struct usb_audio_control volume_control = {
111 .list = LIST_HEAD_INIT(volume_control.list), 111 .list = LIST_HEAD_INIT(volume_control.list),
112 .name = "Volume Control", 112 .name = "Volume Control",
113 .type = UAC_VOLUME_CONTROL, 113 .type = UAC_FU_VOLUME,
114 /* Todo: add real Volume control code */ 114 /* Todo: add real Volume control code */
115 .set = generic_set_cmd, 115 .set = generic_set_cmd,
116 .get = generic_get_cmd, 116 .get = generic_get_cmd,
diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c
index 2928523268b5..82506ca297d5 100644
--- a/drivers/usb/gadget/fsl_qe_udc.c
+++ b/drivers/usb/gadget/fsl_qe_udc.c
@@ -2400,7 +2400,7 @@ EXPORT_SYMBOL(usb_gadget_unregister_driver);
2400static struct qe_udc __devinit *qe_udc_config(struct of_device *ofdev) 2400static struct qe_udc __devinit *qe_udc_config(struct of_device *ofdev)
2401{ 2401{
2402 struct qe_udc *udc; 2402 struct qe_udc *udc;
2403 struct device_node *np = ofdev->node; 2403 struct device_node *np = ofdev->dev.of_node;
2404 unsigned int tmp_addr = 0; 2404 unsigned int tmp_addr = 0;
2405 struct usb_device_para __iomem *usbpram; 2405 struct usb_device_para __iomem *usbpram;
2406 unsigned int i; 2406 unsigned int i;
@@ -2525,7 +2525,7 @@ static void qe_udc_release(struct device *dev)
2525static int __devinit qe_udc_probe(struct of_device *ofdev, 2525static int __devinit qe_udc_probe(struct of_device *ofdev,
2526 const struct of_device_id *match) 2526 const struct of_device_id *match)
2527{ 2527{
2528 struct device_node *np = ofdev->node; 2528 struct device_node *np = ofdev->dev.of_node;
2529 struct qe_ep *ep; 2529 struct qe_ep *ep;
2530 unsigned int ret = 0; 2530 unsigned int ret = 0;
2531 unsigned int i; 2531 unsigned int i;
diff --git a/drivers/usb/gadget/m66592-udc.h b/drivers/usb/gadget/m66592-udc.h
index 8b960deed680..c3caf1ac73ce 100644
--- a/drivers/usb/gadget/m66592-udc.h
+++ b/drivers/usb/gadget/m66592-udc.h
@@ -537,35 +537,35 @@ struct m66592 {
537/*-------------------------------------------------------------------------*/ 537/*-------------------------------------------------------------------------*/
538static inline u16 m66592_read(struct m66592 *m66592, unsigned long offset) 538static inline u16 m66592_read(struct m66592 *m66592, unsigned long offset)
539{ 539{
540 return inw((unsigned long)m66592->reg + offset); 540 return ioread16(m66592->reg + offset);
541} 541}
542 542
543static inline void m66592_read_fifo(struct m66592 *m66592, 543static inline void m66592_read_fifo(struct m66592 *m66592,
544 unsigned long offset, 544 unsigned long offset,
545 void *buf, unsigned long len) 545 void *buf, unsigned long len)
546{ 546{
547 unsigned long fifoaddr = (unsigned long)m66592->reg + offset; 547 void __iomem *fifoaddr = m66592->reg + offset;
548 548
549 if (m66592->pdata->on_chip) { 549 if (m66592->pdata->on_chip) {
550 len = (len + 3) / 4; 550 len = (len + 3) / 4;
551 insl(fifoaddr, buf, len); 551 ioread32_rep(fifoaddr, buf, len);
552 } else { 552 } else {
553 len = (len + 1) / 2; 553 len = (len + 1) / 2;
554 insw(fifoaddr, buf, len); 554 ioread16_rep(fifoaddr, buf, len);
555 } 555 }
556} 556}
557 557
558static inline void m66592_write(struct m66592 *m66592, u16 val, 558static inline void m66592_write(struct m66592 *m66592, u16 val,
559 unsigned long offset) 559 unsigned long offset)
560{ 560{
561 outw(val, (unsigned long)m66592->reg + offset); 561 iowrite16(val, m66592->reg + offset);
562} 562}
563 563
564static inline void m66592_write_fifo(struct m66592 *m66592, 564static inline void m66592_write_fifo(struct m66592 *m66592,
565 unsigned long offset, 565 unsigned long offset,
566 void *buf, unsigned long len) 566 void *buf, unsigned long len)
567{ 567{
568 unsigned long fifoaddr = (unsigned long)m66592->reg + offset; 568 void __iomem *fifoaddr = m66592->reg + offset;
569 569
570 if (m66592->pdata->on_chip) { 570 if (m66592->pdata->on_chip) {
571 unsigned long count; 571 unsigned long count;
@@ -573,25 +573,25 @@ static inline void m66592_write_fifo(struct m66592 *m66592,
573 int i; 573 int i;
574 574
575 count = len / 4; 575 count = len / 4;
576 outsl(fifoaddr, buf, count); 576 iowrite32_rep(fifoaddr, buf, count);
577 577
578 if (len & 0x00000003) { 578 if (len & 0x00000003) {
579 pb = buf + count * 4; 579 pb = buf + count * 4;
580 for (i = 0; i < (len & 0x00000003); i++) { 580 for (i = 0; i < (len & 0x00000003); i++) {
581 if (m66592_read(m66592, M66592_CFBCFG)) /* le */ 581 if (m66592_read(m66592, M66592_CFBCFG)) /* le */
582 outb(pb[i], fifoaddr + (3 - i)); 582 iowrite8(pb[i], fifoaddr + (3 - i));
583 else 583 else
584 outb(pb[i], fifoaddr + i); 584 iowrite8(pb[i], fifoaddr + i);
585 } 585 }
586 } 586 }
587 } else { 587 } else {
588 unsigned long odd = len & 0x0001; 588 unsigned long odd = len & 0x0001;
589 589
590 len = len / 2; 590 len = len / 2;
591 outsw(fifoaddr, buf, len); 591 iowrite16_rep(fifoaddr, buf, len);
592 if (odd) { 592 if (odd) {
593 unsigned char *p = buf + len*2; 593 unsigned char *p = buf + len*2;
594 outb(*p, fifoaddr); 594 iowrite8(*p, fifoaddr);
595 } 595 }
596 } 596 }
597} 597}
diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c
index 6b8bf8c781c4..43abf55d8c60 100644
--- a/drivers/usb/gadget/printer.c
+++ b/drivers/usb/gadget/printer.c
@@ -794,7 +794,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
794} 794}
795 795
796static int 796static int
797printer_fsync(struct file *fd, struct dentry *dentry, int datasync) 797printer_fsync(struct file *fd, int datasync)
798{ 798{
799 struct printer_dev *dev = fd->private_data; 799 struct printer_dev *dev = fd->private_data;
800 unsigned long flags; 800 unsigned long flags;
diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c
index 888d8f166c0b..70a817842755 100644
--- a/drivers/usb/gadget/r8a66597-udc.c
+++ b/drivers/usb/gadget/r8a66597-udc.c
@@ -1500,7 +1500,7 @@ static int __exit r8a66597_remove(struct platform_device *pdev)
1500 struct r8a66597 *r8a66597 = dev_get_drvdata(&pdev->dev); 1500 struct r8a66597 *r8a66597 = dev_get_drvdata(&pdev->dev);
1501 1501
1502 del_timer_sync(&r8a66597->timer); 1502 del_timer_sync(&r8a66597->timer);
1503 iounmap((void *)r8a66597->reg); 1503 iounmap(r8a66597->reg);
1504 free_irq(platform_get_irq(pdev, 0), r8a66597); 1504 free_irq(platform_get_irq(pdev, 0), r8a66597);
1505 r8a66597_free_request(&r8a66597->ep[0].ep, r8a66597->ep0_req); 1505 r8a66597_free_request(&r8a66597->ep[0].ep, r8a66597->ep0_req);
1506#ifdef CONFIG_HAVE_CLK 1506#ifdef CONFIG_HAVE_CLK
@@ -1578,7 +1578,7 @@ static int __init r8a66597_probe(struct platform_device *pdev)
1578 init_timer(&r8a66597->timer); 1578 init_timer(&r8a66597->timer);
1579 r8a66597->timer.function = r8a66597_timer; 1579 r8a66597->timer.function = r8a66597_timer;
1580 r8a66597->timer.data = (unsigned long)r8a66597; 1580 r8a66597->timer.data = (unsigned long)r8a66597;
1581 r8a66597->reg = (unsigned long)reg; 1581 r8a66597->reg = reg;
1582 1582
1583#ifdef CONFIG_HAVE_CLK 1583#ifdef CONFIG_HAVE_CLK
1584 if (r8a66597->pdata->on_chip) { 1584 if (r8a66597->pdata->on_chip) {
diff --git a/drivers/usb/gadget/r8a66597-udc.h b/drivers/usb/gadget/r8a66597-udc.h
index 9a537aa07968..f763b5190afa 100644
--- a/drivers/usb/gadget/r8a66597-udc.h
+++ b/drivers/usb/gadget/r8a66597-udc.h
@@ -91,7 +91,7 @@ struct r8a66597_ep {
91 91
92struct r8a66597 { 92struct r8a66597 {
93 spinlock_t lock; 93 spinlock_t lock;
94 unsigned long reg; 94 void __iomem *reg;
95 95
96#ifdef CONFIG_HAVE_CLK 96#ifdef CONFIG_HAVE_CLK
97 struct clk *clk; 97 struct clk *clk;
@@ -127,7 +127,7 @@ struct r8a66597 {
127 127
128static inline u16 r8a66597_read(struct r8a66597 *r8a66597, unsigned long offset) 128static inline u16 r8a66597_read(struct r8a66597 *r8a66597, unsigned long offset)
129{ 129{
130 return inw(r8a66597->reg + offset); 130 return ioread16(r8a66597->reg + offset);
131} 131}
132 132
133static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597, 133static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
@@ -135,7 +135,7 @@ static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
135 unsigned char *buf, 135 unsigned char *buf,
136 int len) 136 int len)
137{ 137{
138 unsigned long fifoaddr = r8a66597->reg + offset; 138 void __iomem *fifoaddr = r8a66597->reg + offset;
139 unsigned int data; 139 unsigned int data;
140 int i; 140 int i;
141 141
@@ -144,7 +144,7 @@ static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
144 144
145 /* aligned buf case */ 145 /* aligned buf case */
146 if (len >= 4 && !((unsigned long)buf & 0x03)) { 146 if (len >= 4 && !((unsigned long)buf & 0x03)) {
147 insl(fifoaddr, buf, len / 4); 147 ioread32_rep(fifoaddr, buf, len / 4);
148 buf += len & ~0x03; 148 buf += len & ~0x03;
149 len &= 0x03; 149 len &= 0x03;
150 } 150 }
@@ -152,7 +152,7 @@ static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
152 /* unaligned buf case */ 152 /* unaligned buf case */
153 for (i = 0; i < len; i++) { 153 for (i = 0; i < len; i++) {
154 if (!(i & 0x03)) 154 if (!(i & 0x03))
155 data = inl(fifoaddr); 155 data = ioread32(fifoaddr);
156 156
157 buf[i] = (data >> ((i & 0x03) * 8)) & 0xff; 157 buf[i] = (data >> ((i & 0x03) * 8)) & 0xff;
158 } 158 }
@@ -161,7 +161,7 @@ static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
161 161
162 /* aligned buf case */ 162 /* aligned buf case */
163 if (len >= 2 && !((unsigned long)buf & 0x01)) { 163 if (len >= 2 && !((unsigned long)buf & 0x01)) {
164 insw(fifoaddr, buf, len / 2); 164 ioread16_rep(fifoaddr, buf, len / 2);
165 buf += len & ~0x01; 165 buf += len & ~0x01;
166 len &= 0x01; 166 len &= 0x01;
167 } 167 }
@@ -169,7 +169,7 @@ static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
169 /* unaligned buf case */ 169 /* unaligned buf case */
170 for (i = 0; i < len; i++) { 170 for (i = 0; i < len; i++) {
171 if (!(i & 0x01)) 171 if (!(i & 0x01))
172 data = inw(fifoaddr); 172 data = ioread16(fifoaddr);
173 173
174 buf[i] = (data >> ((i & 0x01) * 8)) & 0xff; 174 buf[i] = (data >> ((i & 0x01) * 8)) & 0xff;
175 } 175 }
@@ -179,7 +179,7 @@ static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
179static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val, 179static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val,
180 unsigned long offset) 180 unsigned long offset)
181{ 181{
182 outw(val, r8a66597->reg + offset); 182 iowrite16(val, r8a66597->reg + offset);
183} 183}
184 184
185static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597, 185static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
@@ -187,21 +187,21 @@ static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
187 unsigned char *buf, 187 unsigned char *buf,
188 int len) 188 int len)
189{ 189{
190 unsigned long fifoaddr = r8a66597->reg + offset; 190 void __iomem *fifoaddr = r8a66597->reg + offset;
191 int adj = 0; 191 int adj = 0;
192 int i; 192 int i;
193 193
194 if (r8a66597->pdata->on_chip) { 194 if (r8a66597->pdata->on_chip) {
195 /* 32-bit access only if buf is 32-bit aligned */ 195 /* 32-bit access only if buf is 32-bit aligned */
196 if (len >= 4 && !((unsigned long)buf & 0x03)) { 196 if (len >= 4 && !((unsigned long)buf & 0x03)) {
197 outsl(fifoaddr, buf, len / 4); 197 iowrite32_rep(fifoaddr, buf, len / 4);
198 buf += len & ~0x03; 198 buf += len & ~0x03;
199 len &= 0x03; 199 len &= 0x03;
200 } 200 }
201 } else { 201 } else {
202 /* 16-bit access only if buf is 16-bit aligned */ 202 /* 16-bit access only if buf is 16-bit aligned */
203 if (len >= 2 && !((unsigned long)buf & 0x01)) { 203 if (len >= 2 && !((unsigned long)buf & 0x01)) {
204 outsw(fifoaddr, buf, len / 2); 204 iowrite16_rep(fifoaddr, buf, len / 2);
205 buf += len & ~0x01; 205 buf += len & ~0x01;
206 len &= 0x01; 206 len &= 0x01;
207 } 207 }
@@ -216,7 +216,7 @@ static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
216 } 216 }
217 217
218 for (i = 0; i < len; i++) 218 for (i = 0; i < len; i++)
219 outb(buf[i], fifoaddr + adj - (i & adj)); 219 iowrite8(buf[i], fifoaddr + adj - (i & adj));
220} 220}
221 221
222static inline void r8a66597_mdfy(struct r8a66597 *r8a66597, 222static inline void r8a66597_mdfy(struct r8a66597 *r8a66597,
diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c
index 1f73b485732d..26193eceb323 100644
--- a/drivers/usb/gadget/s3c-hsotg.c
+++ b/drivers/usb/gadget/s3c-hsotg.c
@@ -297,6 +297,12 @@ static void s3c_hsotg_ctrl_epint(struct s3c_hsotg *hsotg,
297 */ 297 */
298static void s3c_hsotg_init_fifo(struct s3c_hsotg *hsotg) 298static void s3c_hsotg_init_fifo(struct s3c_hsotg *hsotg)
299{ 299{
300 unsigned int ep;
301 unsigned int addr;
302 unsigned int size;
303 int timeout;
304 u32 val;
305
300 /* the ryu 2.6.24 release ahs 306 /* the ryu 2.6.24 release ahs
301 writel(0x1C0, hsotg->regs + S3C_GRXFSIZ); 307 writel(0x1C0, hsotg->regs + S3C_GRXFSIZ);
302 writel(S3C_GNPTXFSIZ_NPTxFStAddr(0x200) | 308 writel(S3C_GNPTXFSIZ_NPTxFStAddr(0x200) |
@@ -310,6 +316,51 @@ static void s3c_hsotg_init_fifo(struct s3c_hsotg *hsotg)
310 writel(S3C_GNPTXFSIZ_NPTxFStAddr(2048) | 316 writel(S3C_GNPTXFSIZ_NPTxFStAddr(2048) |
311 S3C_GNPTXFSIZ_NPTxFDep(0x1C0), 317 S3C_GNPTXFSIZ_NPTxFDep(0x1C0),
312 hsotg->regs + S3C_GNPTXFSIZ); 318 hsotg->regs + S3C_GNPTXFSIZ);
319
320 /* arange all the rest of the TX FIFOs, as some versions of this
321 * block have overlapping default addresses. This also ensures
322 * that if the settings have been changed, then they are set to
323 * known values. */
324
325 /* start at the end of the GNPTXFSIZ, rounded up */
326 addr = 2048 + 1024;
327 size = 768;
328
329 /* currently we allocate TX FIFOs for all possible endpoints,
330 * and assume that they are all the same size. */
331
332 for (ep = 0; ep <= 15; ep++) {
333 val = addr;
334 val |= size << S3C_DPTXFSIZn_DPTxFSize_SHIFT;
335 addr += size;
336
337 writel(val, hsotg->regs + S3C_DPTXFSIZn(ep));
338 }
339
340 /* according to p428 of the design guide, we need to ensure that
341 * all fifos are flushed before continuing */
342
343 writel(S3C_GRSTCTL_TxFNum(0x10) | S3C_GRSTCTL_TxFFlsh |
344 S3C_GRSTCTL_RxFFlsh, hsotg->regs + S3C_GRSTCTL);
345
346 /* wait until the fifos are both flushed */
347 timeout = 100;
348 while (1) {
349 val = readl(hsotg->regs + S3C_GRSTCTL);
350
351 if ((val & (S3C_GRSTCTL_TxFFlsh | S3C_GRSTCTL_RxFFlsh)) == 0)
352 break;
353
354 if (--timeout == 0) {
355 dev_err(hsotg->dev,
356 "%s: timeout flushing fifos (GRSTCTL=%08x)\n",
357 __func__, val);
358 }
359
360 udelay(1);
361 }
362
363 dev_dbg(hsotg->dev, "FIFOs reset, timeout at %d\n", timeout);
313} 364}
314 365
315/** 366/**
@@ -2574,6 +2625,9 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
2574 writel(S3C_DCTL_CGOUTNak | S3C_DCTL_CGNPInNAK, 2625 writel(S3C_DCTL_CGOUTNak | S3C_DCTL_CGNPInNAK,
2575 hsotg->regs + S3C_DCTL); 2626 hsotg->regs + S3C_DCTL);
2576 2627
2628 /* must be at-least 3ms to allow bus to see disconnect */
2629 msleep(3);
2630
2577 /* remove the soft-disconnect and let's go */ 2631 /* remove the soft-disconnect and let's go */
2578 __bic32(hsotg->regs + S3C_DCTL, S3C_DCTL_SftDiscon); 2632 __bic32(hsotg->regs + S3C_DCTL, S3C_DCTL_SftDiscon);
2579 2633
@@ -2730,6 +2784,9 @@ static void s3c_hsotg_init(struct s3c_hsotg *hsotg)
2730 2784
2731 writel(0, hsotg->regs + S3C_DAINTMSK); 2785 writel(0, hsotg->regs + S3C_DAINTMSK);
2732 2786
2787 /* Be in disconnected state until gadget is registered */
2788 __orr32(hsotg->regs + S3C_DCTL, S3C_DCTL_SftDiscon);
2789
2733 if (0) { 2790 if (0) {
2734 /* post global nak until we're ready */ 2791 /* post global nak until we're ready */
2735 writel(S3C_DCTL_SGNPInNAK | S3C_DCTL_SGOUTNak, 2792 writel(S3C_DCTL_SGNPInNAK | S3C_DCTL_SGOUTNak,
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index ef3e88f0b3c3..a3ef2a9d9dc2 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1135,7 +1135,7 @@ MODULE_LICENSE ("GPL");
1135 1135
1136#ifdef CONFIG_XPS_USB_HCD_XILINX 1136#ifdef CONFIG_XPS_USB_HCD_XILINX
1137#include "ehci-xilinx-of.c" 1137#include "ehci-xilinx-of.c"
1138#define OF_PLATFORM_DRIVER ehci_hcd_xilinx_of_driver 1138#define XILINX_OF_PLATFORM_DRIVER ehci_hcd_xilinx_of_driver
1139#endif 1139#endif
1140 1140
1141#ifdef CONFIG_PLAT_ORION 1141#ifdef CONFIG_PLAT_ORION
@@ -1159,7 +1159,8 @@ MODULE_LICENSE ("GPL");
1159#endif 1159#endif
1160 1160
1161#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ 1161#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
1162 !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) 1162 !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \
1163 !defined(XILINX_OF_PLATFORM_DRIVER)
1163#error "missing bus glue for ehci-hcd" 1164#error "missing bus glue for ehci-hcd"
1164#endif 1165#endif
1165 1166
@@ -1213,10 +1214,20 @@ static int __init ehci_hcd_init(void)
1213 if (retval < 0) 1214 if (retval < 0)
1214 goto clean3; 1215 goto clean3;
1215#endif 1216#endif
1217
1218#ifdef XILINX_OF_PLATFORM_DRIVER
1219 retval = of_register_platform_driver(&XILINX_OF_PLATFORM_DRIVER);
1220 if (retval < 0)
1221 goto clean4;
1222#endif
1216 return retval; 1223 return retval;
1217 1224
1225#ifdef XILINX_OF_PLATFORM_DRIVER
1226 /* of_unregister_platform_driver(&XILINX_OF_PLATFORM_DRIVER); */
1227clean4:
1228#endif
1218#ifdef OF_PLATFORM_DRIVER 1229#ifdef OF_PLATFORM_DRIVER
1219 /* of_unregister_platform_driver(&OF_PLATFORM_DRIVER); */ 1230 of_unregister_platform_driver(&OF_PLATFORM_DRIVER);
1220clean3: 1231clean3:
1221#endif 1232#endif
1222#ifdef PS3_SYSTEM_BUS_DRIVER 1233#ifdef PS3_SYSTEM_BUS_DRIVER
@@ -1243,6 +1254,9 @@ module_init(ehci_hcd_init);
1243 1254
1244static void __exit ehci_hcd_cleanup(void) 1255static void __exit ehci_hcd_cleanup(void)
1245{ 1256{
1257#ifdef XILINX_OF_PLATFORM_DRIVER
1258 of_unregister_platform_driver(&XILINX_OF_PLATFORM_DRIVER);
1259#endif
1246#ifdef OF_PLATFORM_DRIVER 1260#ifdef OF_PLATFORM_DRIVER
1247 of_unregister_platform_driver(&OF_PLATFORM_DRIVER); 1261 of_unregister_platform_driver(&OF_PLATFORM_DRIVER);
1248#endif 1262#endif
diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c
index 013972bbde57..4899f451add9 100644
--- a/drivers/usb/host/ehci-xilinx-of.c
+++ b/drivers/usb/host/ehci-xilinx-of.c
@@ -151,7 +151,7 @@ static const struct hc_driver ehci_xilinx_of_hc_driver = {
151static int __devinit 151static int __devinit
152ehci_hcd_xilinx_of_probe(struct of_device *op, const struct of_device_id *match) 152ehci_hcd_xilinx_of_probe(struct of_device *op, const struct of_device_id *match)
153{ 153{
154 struct device_node *dn = op->node; 154 struct device_node *dn = op->dev.of_node;
155 struct usb_hcd *hcd; 155 struct usb_hcd *hcd;
156 struct ehci_hcd *ehci; 156 struct ehci_hcd *ehci;
157 struct resource res; 157 struct resource res;
diff --git a/drivers/usb/host/isp1362.h b/drivers/usb/host/isp1362.h
index 5151516ea1de..d995351f9bed 100644
--- a/drivers/usb/host/isp1362.h
+++ b/drivers/usb/host/isp1362.h
@@ -65,7 +65,7 @@ static inline void delayed_insw(unsigned int addr, void *buf, int len)
65 unsigned short *bp = (unsigned short *)buf; 65 unsigned short *bp = (unsigned short *)buf;
66 while (len--) { 66 while (len--) {
67 DUMMY_DELAY_ACCESS; 67 DUMMY_DELAY_ACCESS;
68 *bp++ = inw((void *)addr); 68 *bp++ = inw(addr);
69 } 69 }
70} 70}
71 71
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index 6db57ab6079d..1a2bb4ce638f 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -2404,7 +2404,7 @@ static int __init_or_module r8a66597_remove(struct platform_device *pdev)
2404 2404
2405 del_timer_sync(&r8a66597->rh_timer); 2405 del_timer_sync(&r8a66597->rh_timer);
2406 usb_remove_hcd(hcd); 2406 usb_remove_hcd(hcd);
2407 iounmap((void *)r8a66597->reg); 2407 iounmap(r8a66597->reg);
2408#ifdef CONFIG_HAVE_CLK 2408#ifdef CONFIG_HAVE_CLK
2409 if (r8a66597->pdata->on_chip) 2409 if (r8a66597->pdata->on_chip)
2410 clk_put(r8a66597->clk); 2410 clk_put(r8a66597->clk);
@@ -2496,7 +2496,7 @@ static int __devinit r8a66597_probe(struct platform_device *pdev)
2496 init_timer(&r8a66597->rh_timer); 2496 init_timer(&r8a66597->rh_timer);
2497 r8a66597->rh_timer.function = r8a66597_timer; 2497 r8a66597->rh_timer.function = r8a66597_timer;
2498 r8a66597->rh_timer.data = (unsigned long)r8a66597; 2498 r8a66597->rh_timer.data = (unsigned long)r8a66597;
2499 r8a66597->reg = (unsigned long)reg; 2499 r8a66597->reg = reg;
2500 2500
2501 /* make sure no interrupts are pending */ 2501 /* make sure no interrupts are pending */
2502 ret = r8a66597_clock_enable(r8a66597); 2502 ret = r8a66597_clock_enable(r8a66597);
diff --git a/drivers/usb/host/r8a66597.h b/drivers/usb/host/r8a66597.h
index 228e3fb23854..95d0f5adfdcf 100644
--- a/drivers/usb/host/r8a66597.h
+++ b/drivers/usb/host/r8a66597.h
@@ -112,7 +112,7 @@ struct r8a66597_root_hub {
112 112
113struct r8a66597 { 113struct r8a66597 {
114 spinlock_t lock; 114 spinlock_t lock;
115 unsigned long reg; 115 void __iomem *reg;
116#ifdef CONFIG_HAVE_CLK 116#ifdef CONFIG_HAVE_CLK
117 struct clk *clk; 117 struct clk *clk;
118#endif 118#endif
@@ -170,67 +170,67 @@ static inline struct urb *r8a66597_get_urb(struct r8a66597 *r8a66597,
170 170
171static inline u16 r8a66597_read(struct r8a66597 *r8a66597, unsigned long offset) 171static inline u16 r8a66597_read(struct r8a66597 *r8a66597, unsigned long offset)
172{ 172{
173 return inw(r8a66597->reg + offset); 173 return ioread16(r8a66597->reg + offset);
174} 174}
175 175
176static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597, 176static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
177 unsigned long offset, u16 *buf, 177 unsigned long offset, u16 *buf,
178 int len) 178 int len)
179{ 179{
180 unsigned long fifoaddr = r8a66597->reg + offset; 180 void __iomem *fifoaddr = r8a66597->reg + offset;
181 unsigned long count; 181 unsigned long count;
182 182
183 if (r8a66597->pdata->on_chip) { 183 if (r8a66597->pdata->on_chip) {
184 count = len / 4; 184 count = len / 4;
185 insl(fifoaddr, buf, count); 185 ioread32_rep(fifoaddr, buf, count);
186 186
187 if (len & 0x00000003) { 187 if (len & 0x00000003) {
188 unsigned long tmp = inl(fifoaddr); 188 unsigned long tmp = ioread32(fifoaddr);
189 memcpy((unsigned char *)buf + count * 4, &tmp, 189 memcpy((unsigned char *)buf + count * 4, &tmp,
190 len & 0x03); 190 len & 0x03);
191 } 191 }
192 } else { 192 } else {
193 len = (len + 1) / 2; 193 len = (len + 1) / 2;
194 insw(fifoaddr, buf, len); 194 ioread16_rep(fifoaddr, buf, len);
195 } 195 }
196} 196}
197 197
198static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val, 198static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val,
199 unsigned long offset) 199 unsigned long offset)
200{ 200{
201 outw(val, r8a66597->reg + offset); 201 iowrite16(val, r8a66597->reg + offset);
202} 202}
203 203
204static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597, 204static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
205 unsigned long offset, u16 *buf, 205 unsigned long offset, u16 *buf,
206 int len) 206 int len)
207{ 207{
208 unsigned long fifoaddr = r8a66597->reg + offset; 208 void __iomem *fifoaddr = r8a66597->reg + offset;
209 unsigned long count; 209 unsigned long count;
210 unsigned char *pb; 210 unsigned char *pb;
211 int i; 211 int i;
212 212
213 if (r8a66597->pdata->on_chip) { 213 if (r8a66597->pdata->on_chip) {
214 count = len / 4; 214 count = len / 4;
215 outsl(fifoaddr, buf, count); 215 iowrite32_rep(fifoaddr, buf, count);
216 216
217 if (len & 0x00000003) { 217 if (len & 0x00000003) {
218 pb = (unsigned char *)buf + count * 4; 218 pb = (unsigned char *)buf + count * 4;
219 for (i = 0; i < (len & 0x00000003); i++) { 219 for (i = 0; i < (len & 0x00000003); i++) {
220 if (r8a66597_read(r8a66597, CFIFOSEL) & BIGEND) 220 if (r8a66597_read(r8a66597, CFIFOSEL) & BIGEND)
221 outb(pb[i], fifoaddr + i); 221 iowrite8(pb[i], fifoaddr + i);
222 else 222 else
223 outb(pb[i], fifoaddr + 3 - i); 223 iowrite8(pb[i], fifoaddr + 3 - i);
224 } 224 }
225 } 225 }
226 } else { 226 } else {
227 int odd = len & 0x0001; 227 int odd = len & 0x0001;
228 228
229 len = len / 2; 229 len = len / 2;
230 outsw(fifoaddr, buf, len); 230 ioread16_rep(fifoaddr, buf, len);
231 if (unlikely(odd)) { 231 if (unlikely(odd)) {
232 buf = &buf[len]; 232 buf = &buf[len];
233 outb((unsigned char)*buf, fifoaddr); 233 iowrite8((unsigned char)*buf, fifoaddr);
234 } 234 }
235 } 235 }
236} 236}
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index edffd81fc253..11482b6b9381 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -78,6 +78,8 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
78 xhci_dbg(xhci, "QUIRK: Fresco Logic xHC needs configure" 78 xhci_dbg(xhci, "QUIRK: Fresco Logic xHC needs configure"
79 " endpoint cmd after reset endpoint\n"); 79 " endpoint cmd after reset endpoint\n");
80 } 80 }
81 if (pdev->vendor == PCI_VENDOR_ID_NEC)
82 xhci->quirks |= XHCI_NEC_HOST;
81 83
82 /* Make sure the HC is halted. */ 84 /* Make sure the HC is halted. */
83 retval = xhci_halt(xhci); 85 retval = xhci_halt(xhci);
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 36c858e5b529..9012098add6b 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1071,6 +1071,15 @@ bandwidth_change:
1071 xhci_warn(xhci, "Reset device command completion " 1071 xhci_warn(xhci, "Reset device command completion "
1072 "for disabled slot %u\n", slot_id); 1072 "for disabled slot %u\n", slot_id);
1073 break; 1073 break;
1074 case TRB_TYPE(TRB_NEC_GET_FW):
1075 if (!(xhci->quirks & XHCI_NEC_HOST)) {
1076 xhci->error_bitmask |= 1 << 6;
1077 break;
1078 }
1079 xhci_dbg(xhci, "NEC firmware version %2x.%02x\n",
1080 NEC_FW_MAJOR(event->status),
1081 NEC_FW_MINOR(event->status));
1082 break;
1074 default: 1083 default:
1075 /* Skip over unknown commands on the event ring */ 1084 /* Skip over unknown commands on the event ring */
1076 xhci->error_bitmask |= 1 << 6; 1085 xhci->error_bitmask |= 1 << 6;
@@ -1079,6 +1088,17 @@ bandwidth_change:
1079 inc_deq(xhci, xhci->cmd_ring, false); 1088 inc_deq(xhci, xhci->cmd_ring, false);
1080} 1089}
1081 1090
1091static void handle_vendor_event(struct xhci_hcd *xhci,
1092 union xhci_trb *event)
1093{
1094 u32 trb_type;
1095
1096 trb_type = TRB_FIELD_TO_TYPE(event->generic.field[3]);
1097 xhci_dbg(xhci, "Vendor specific event TRB type = %u\n", trb_type);
1098 if (trb_type == TRB_NEC_CMD_COMP && (xhci->quirks & XHCI_NEC_HOST))
1099 handle_cmd_completion(xhci, &event->event_cmd);
1100}
1101
1082static void handle_port_status(struct xhci_hcd *xhci, 1102static void handle_port_status(struct xhci_hcd *xhci,
1083 union xhci_trb *event) 1103 union xhci_trb *event)
1084{ 1104{
@@ -1659,7 +1679,10 @@ void xhci_handle_event(struct xhci_hcd *xhci)
1659 update_ptrs = 0; 1679 update_ptrs = 0;
1660 break; 1680 break;
1661 default: 1681 default:
1662 xhci->error_bitmask |= 1 << 3; 1682 if ((event->event_cmd.flags & TRB_TYPE_BITMASK) >= TRB_TYPE(48))
1683 handle_vendor_event(xhci, event);
1684 else
1685 xhci->error_bitmask |= 1 << 3;
1663 } 1686 }
1664 /* Any of the above functions may drop and re-acquire the lock, so check 1687 /* Any of the above functions may drop and re-acquire the lock, so check
1665 * to make sure a watchdog timer didn't mark the host as non-responsive. 1688 * to make sure a watchdog timer didn't mark the host as non-responsive.
@@ -2378,6 +2401,12 @@ int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
2378 false); 2401 false);
2379} 2402}
2380 2403
2404int xhci_queue_vendor_command(struct xhci_hcd *xhci,
2405 u32 field1, u32 field2, u32 field3, u32 field4)
2406{
2407 return queue_command(xhci, field1, field2, field3, field4, false);
2408}
2409
2381/* Queue a reset device command TRB */ 2410/* Queue a reset device command TRB */
2382int xhci_queue_reset_device(struct xhci_hcd *xhci, u32 slot_id) 2411int xhci_queue_reset_device(struct xhci_hcd *xhci, u32 slot_id)
2383{ 2412{
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 40e0a0c221b8..27345cd04da0 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -106,6 +106,33 @@ int xhci_halt(struct xhci_hcd *xhci)
106} 106}
107 107
108/* 108/*
109 * Set the run bit and wait for the host to be running.
110 */
111int xhci_start(struct xhci_hcd *xhci)
112{
113 u32 temp;
114 int ret;
115
116 temp = xhci_readl(xhci, &xhci->op_regs->command);
117 temp |= (CMD_RUN);
118 xhci_dbg(xhci, "// Turn on HC, cmd = 0x%x.\n",
119 temp);
120 xhci_writel(xhci, temp, &xhci->op_regs->command);
121
122 /*
123 * Wait for the HCHalted Status bit to be 0 to indicate the host is
124 * running.
125 */
126 ret = handshake(xhci, &xhci->op_regs->status,
127 STS_HALT, 0, XHCI_MAX_HALT_USEC);
128 if (ret == -ETIMEDOUT)
129 xhci_err(xhci, "Host took too long to start, "
130 "waited %u microseconds.\n",
131 XHCI_MAX_HALT_USEC);
132 return ret;
133}
134
135/*
109 * Reset a halted HC, and set the internal HC state to HC_STATE_HALT. 136 * Reset a halted HC, and set the internal HC state to HC_STATE_HALT.
110 * 137 *
111 * This resets pipelines, timers, counters, state machines, etc. 138 * This resets pipelines, timers, counters, state machines, etc.
@@ -116,6 +143,7 @@ int xhci_reset(struct xhci_hcd *xhci)
116{ 143{
117 u32 command; 144 u32 command;
118 u32 state; 145 u32 state;
146 int ret;
119 147
120 state = xhci_readl(xhci, &xhci->op_regs->status); 148 state = xhci_readl(xhci, &xhci->op_regs->status);
121 if ((state & STS_HALT) == 0) { 149 if ((state & STS_HALT) == 0) {
@@ -130,7 +158,17 @@ int xhci_reset(struct xhci_hcd *xhci)
130 /* XXX: Why does EHCI set this here? Shouldn't other code do this? */ 158 /* XXX: Why does EHCI set this here? Shouldn't other code do this? */
131 xhci_to_hcd(xhci)->state = HC_STATE_HALT; 159 xhci_to_hcd(xhci)->state = HC_STATE_HALT;
132 160
133 return handshake(xhci, &xhci->op_regs->command, CMD_RESET, 0, 250 * 1000); 161 ret = handshake(xhci, &xhci->op_regs->command,
162 CMD_RESET, 0, 250 * 1000);
163 if (ret)
164 return ret;
165
166 xhci_dbg(xhci, "Wait for controller to be ready for doorbell rings\n");
167 /*
168 * xHCI cannot write to any doorbells or operational registers other
169 * than status until the "Controller Not Ready" flag is cleared.
170 */
171 return handshake(xhci, &xhci->op_regs->status, STS_CNR, 0, 250 * 1000);
134} 172}
135 173
136 174
@@ -448,17 +486,20 @@ int xhci_run(struct usb_hcd *hcd)
448 486
449 if (NUM_TEST_NOOPS > 0) 487 if (NUM_TEST_NOOPS > 0)
450 doorbell = xhci_setup_one_noop(xhci); 488 doorbell = xhci_setup_one_noop(xhci);
489 if (xhci->quirks & XHCI_NEC_HOST)
490 xhci_queue_vendor_command(xhci, 0, 0, 0,
491 TRB_TYPE(TRB_NEC_GET_FW));
492
493 if (xhci_start(xhci)) {
494 xhci_halt(xhci);
495 return -ENODEV;
496 }
451 497
452 temp = xhci_readl(xhci, &xhci->op_regs->command);
453 temp |= (CMD_RUN);
454 xhci_dbg(xhci, "// Turn on HC, cmd = 0x%x.\n",
455 temp);
456 xhci_writel(xhci, temp, &xhci->op_regs->command);
457 /* Flush PCI posted writes */
458 temp = xhci_readl(xhci, &xhci->op_regs->command);
459 xhci_dbg(xhci, "// @%p = 0x%x\n", &xhci->op_regs->command, temp); 498 xhci_dbg(xhci, "// @%p = 0x%x\n", &xhci->op_regs->command, temp);
460 if (doorbell) 499 if (doorbell)
461 (*doorbell)(xhci); 500 (*doorbell)(xhci);
501 if (xhci->quirks & XHCI_NEC_HOST)
502 xhci_ring_cmd_db(xhci);
462 503
463 xhci_dbg(xhci, "Finished xhci_run\n"); 504 xhci_dbg(xhci, "Finished xhci_run\n");
464 return 0; 505 return 0;
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index dada2fb59261..8b4b7d39f79c 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -925,6 +925,7 @@ union xhci_trb {
925/* TRB bit mask */ 925/* TRB bit mask */
926#define TRB_TYPE_BITMASK (0xfc00) 926#define TRB_TYPE_BITMASK (0xfc00)
927#define TRB_TYPE(p) ((p) << 10) 927#define TRB_TYPE(p) ((p) << 10)
928#define TRB_FIELD_TO_TYPE(p) (((p) & TRB_TYPE_BITMASK) >> 10)
928/* TRB type IDs */ 929/* TRB type IDs */
929/* bulk, interrupt, isoc scatter/gather, and control data stage */ 930/* bulk, interrupt, isoc scatter/gather, and control data stage */
930#define TRB_NORMAL 1 931#define TRB_NORMAL 1
@@ -992,6 +993,14 @@ union xhci_trb {
992#define TRB_MFINDEX_WRAP 39 993#define TRB_MFINDEX_WRAP 39
993/* TRB IDs 40-47 reserved, 48-63 is vendor-defined */ 994/* TRB IDs 40-47 reserved, 48-63 is vendor-defined */
994 995
996/* Nec vendor-specific command completion event. */
997#define TRB_NEC_CMD_COMP 48
998/* Get NEC firmware revision. */
999#define TRB_NEC_GET_FW 49
1000
1001#define NEC_FW_MINOR(p) (((p) >> 0) & 0xff)
1002#define NEC_FW_MAJOR(p) (((p) >> 8) & 0xff)
1003
995/* 1004/*
996 * TRBS_PER_SEGMENT must be a multiple of 4, 1005 * TRBS_PER_SEGMENT must be a multiple of 4,
997 * since the command ring is 64-byte aligned. 1006 * since the command ring is 64-byte aligned.
@@ -1172,6 +1181,7 @@ struct xhci_hcd {
1172 unsigned int quirks; 1181 unsigned int quirks;
1173#define XHCI_LINK_TRB_QUIRK (1 << 0) 1182#define XHCI_LINK_TRB_QUIRK (1 << 0)
1174#define XHCI_RESET_EP_QUIRK (1 << 1) 1183#define XHCI_RESET_EP_QUIRK (1 << 1)
1184#define XHCI_NEC_HOST (1 << 2)
1175}; 1185};
1176 1186
1177/* For testing purposes */ 1187/* For testing purposes */
@@ -1379,6 +1389,8 @@ void xhci_set_hc_event_deq(struct xhci_hcd *xhci);
1379int xhci_queue_slot_control(struct xhci_hcd *xhci, u32 trb_type, u32 slot_id); 1389int xhci_queue_slot_control(struct xhci_hcd *xhci, u32 trb_type, u32 slot_id);
1380int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, 1390int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
1381 u32 slot_id); 1391 u32 slot_id);
1392int xhci_queue_vendor_command(struct xhci_hcd *xhci,
1393 u32 field1, u32 field2, u32 field3, u32 field4);
1382int xhci_queue_stop_endpoint(struct xhci_hcd *xhci, int slot_id, 1394int xhci_queue_stop_endpoint(struct xhci_hcd *xhci, int slot_id,
1383 unsigned int ep_index); 1395 unsigned int ep_index);
1384int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb, 1396int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb,
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index 3edda3ed822a..fd35f73b5721 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -1239,8 +1239,7 @@ static void digi_write_bulk_callback(struct urb *urb)
1239 1239
1240 /* port and serial sanity check */ 1240 /* port and serial sanity check */
1241 if (port == NULL || (priv = usb_get_serial_port_data(port)) == NULL) { 1241 if (port == NULL || (priv = usb_get_serial_port_data(port)) == NULL) {
1242 dev_err(&port->dev, 1242 pr_err("%s: port or port->private is NULL, status=%d\n",
1243 "%s: port or port->private is NULL, status=%d\n",
1244 __func__, status); 1243 __func__, status);
1245 return; 1244 return;
1246 } 1245 }
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 050211afc07e..79dd1ae195e5 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -2005,6 +2005,8 @@ static void ftdi_set_termios(struct tty_struct *tty,
2005 "urb failed to set to rts/cts flow control\n"); 2005 "urb failed to set to rts/cts flow control\n");
2006 } 2006 }
2007 2007
2008 /* raise DTR/RTS */
2009 set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
2008 } else { 2010 } else {
2009 /* 2011 /*
2010 * Xon/Xoff code 2012 * Xon/Xoff code
@@ -2052,6 +2054,8 @@ static void ftdi_set_termios(struct tty_struct *tty,
2052 } 2054 }
2053 } 2055 }
2054 2056
2057 /* lower DTR/RTS */
2058 clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
2055 } 2059 }
2056 return; 2060 return;
2057} 2061}
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index f8424d1bfc1b..585b7e663740 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -730,7 +730,6 @@ static void mos7840_bulk_in_callback(struct urb *urb)
730 mos7840_port = urb->context; 730 mos7840_port = urb->context;
731 if (!mos7840_port) { 731 if (!mos7840_port) {
732 dbg("%s", "NULL mos7840_port pointer"); 732 dbg("%s", "NULL mos7840_port pointer");
733 mos7840_port->read_urb_busy = false;
734 return; 733 return;
735 } 734 }
736 735
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index aa88911c9504..df5b6b971f26 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -593,17 +593,17 @@ static long vhost_net_ioctl(struct file *f, unsigned int ioctl,
593 int r; 593 int r;
594 switch (ioctl) { 594 switch (ioctl) {
595 case VHOST_NET_SET_BACKEND: 595 case VHOST_NET_SET_BACKEND:
596 r = copy_from_user(&backend, argp, sizeof backend); 596 if (copy_from_user(&backend, argp, sizeof backend))
597 if (r < 0) 597 return -EFAULT;
598 return r;
599 return vhost_net_set_backend(n, backend.index, backend.fd); 598 return vhost_net_set_backend(n, backend.index, backend.fd);
600 case VHOST_GET_FEATURES: 599 case VHOST_GET_FEATURES:
601 features = VHOST_FEATURES; 600 features = VHOST_FEATURES;
602 return copy_to_user(featurep, &features, sizeof features); 601 if (copy_to_user(featurep, &features, sizeof features))
602 return -EFAULT;
603 return 0;
603 case VHOST_SET_FEATURES: 604 case VHOST_SET_FEATURES:
604 r = copy_from_user(&features, featurep, sizeof features); 605 if (copy_from_user(&features, featurep, sizeof features))
605 if (r < 0) 606 return -EFAULT;
606 return r;
607 if (features & ~VHOST_FEATURES) 607 if (features & ~VHOST_FEATURES)
608 return -EOPNOTSUPP; 608 return -EOPNOTSUPP;
609 return vhost_net_set_features(n, features); 609 return vhost_net_set_features(n, features);
@@ -637,7 +637,7 @@ const static struct file_operations vhost_net_fops = {
637}; 637};
638 638
639static struct miscdevice vhost_net_misc = { 639static struct miscdevice vhost_net_misc = {
640 VHOST_NET_MINOR, 640 MISC_DYNAMIC_MINOR,
641 "vhost-net", 641 "vhost-net",
642 &vhost_net_fops, 642 &vhost_net_fops,
643}; 643};
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index c6fb8e968f21..3b83382e06eb 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -320,10 +320,8 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m)
320{ 320{
321 struct vhost_memory mem, *newmem, *oldmem; 321 struct vhost_memory mem, *newmem, *oldmem;
322 unsigned long size = offsetof(struct vhost_memory, regions); 322 unsigned long size = offsetof(struct vhost_memory, regions);
323 long r; 323 if (copy_from_user(&mem, m, size))
324 r = copy_from_user(&mem, m, size); 324 return -EFAULT;
325 if (r)
326 return r;
327 if (mem.padding) 325 if (mem.padding)
328 return -EOPNOTSUPP; 326 return -EOPNOTSUPP;
329 if (mem.nregions > VHOST_MEMORY_MAX_NREGIONS) 327 if (mem.nregions > VHOST_MEMORY_MAX_NREGIONS)
@@ -333,15 +331,16 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m)
333 return -ENOMEM; 331 return -ENOMEM;
334 332
335 memcpy(newmem, &mem, size); 333 memcpy(newmem, &mem, size);
336 r = copy_from_user(newmem->regions, m->regions, 334 if (copy_from_user(newmem->regions, m->regions,
337 mem.nregions * sizeof *m->regions); 335 mem.nregions * sizeof *m->regions)) {
338 if (r) {
339 kfree(newmem); 336 kfree(newmem);
340 return r; 337 return -EFAULT;
341 } 338 }
342 339
343 if (!memory_access_ok(d, newmem, vhost_has_feature(d, VHOST_F_LOG_ALL))) 340 if (!memory_access_ok(d, newmem, vhost_has_feature(d, VHOST_F_LOG_ALL))) {
341 kfree(newmem);
344 return -EFAULT; 342 return -EFAULT;
343 }
345 oldmem = d->memory; 344 oldmem = d->memory;
346 rcu_assign_pointer(d->memory, newmem); 345 rcu_assign_pointer(d->memory, newmem);
347 synchronize_rcu(); 346 synchronize_rcu();
@@ -374,7 +373,7 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp)
374 r = get_user(idx, idxp); 373 r = get_user(idx, idxp);
375 if (r < 0) 374 if (r < 0)
376 return r; 375 return r;
377 if (idx > d->nvqs) 376 if (idx >= d->nvqs)
378 return -ENOBUFS; 377 return -ENOBUFS;
379 378
380 vq = d->vqs + idx; 379 vq = d->vqs + idx;
@@ -389,9 +388,10 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp)
389 r = -EBUSY; 388 r = -EBUSY;
390 break; 389 break;
391 } 390 }
392 r = copy_from_user(&s, argp, sizeof s); 391 if (copy_from_user(&s, argp, sizeof s)) {
393 if (r < 0) 392 r = -EFAULT;
394 break; 393 break;
394 }
395 if (!s.num || s.num > 0xffff || (s.num & (s.num - 1))) { 395 if (!s.num || s.num > 0xffff || (s.num & (s.num - 1))) {
396 r = -EINVAL; 396 r = -EINVAL;
397 break; 397 break;
@@ -405,9 +405,10 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp)
405 r = -EBUSY; 405 r = -EBUSY;
406 break; 406 break;
407 } 407 }
408 r = copy_from_user(&s, argp, sizeof s); 408 if (copy_from_user(&s, argp, sizeof s)) {
409 if (r < 0) 409 r = -EFAULT;
410 break; 410 break;
411 }
411 if (s.num > 0xffff) { 412 if (s.num > 0xffff) {
412 r = -EINVAL; 413 r = -EINVAL;
413 break; 414 break;
@@ -419,12 +420,14 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp)
419 case VHOST_GET_VRING_BASE: 420 case VHOST_GET_VRING_BASE:
420 s.index = idx; 421 s.index = idx;
421 s.num = vq->last_avail_idx; 422 s.num = vq->last_avail_idx;
422 r = copy_to_user(argp, &s, sizeof s); 423 if (copy_to_user(argp, &s, sizeof s))
424 r = -EFAULT;
423 break; 425 break;
424 case VHOST_SET_VRING_ADDR: 426 case VHOST_SET_VRING_ADDR:
425 r = copy_from_user(&a, argp, sizeof a); 427 if (copy_from_user(&a, argp, sizeof a)) {
426 if (r < 0) 428 r = -EFAULT;
427 break; 429 break;
430 }
428 if (a.flags & ~(0x1 << VHOST_VRING_F_LOG)) { 431 if (a.flags & ~(0x1 << VHOST_VRING_F_LOG)) {
429 r = -EOPNOTSUPP; 432 r = -EOPNOTSUPP;
430 break; 433 break;
@@ -477,9 +480,10 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp)
477 vq->used = (void __user *)(unsigned long)a.used_user_addr; 480 vq->used = (void __user *)(unsigned long)a.used_user_addr;
478 break; 481 break;
479 case VHOST_SET_VRING_KICK: 482 case VHOST_SET_VRING_KICK:
480 r = copy_from_user(&f, argp, sizeof f); 483 if (copy_from_user(&f, argp, sizeof f)) {
481 if (r < 0) 484 r = -EFAULT;
482 break; 485 break;
486 }
483 eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd); 487 eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd);
484 if (IS_ERR(eventfp)) { 488 if (IS_ERR(eventfp)) {
485 r = PTR_ERR(eventfp); 489 r = PTR_ERR(eventfp);
@@ -492,9 +496,10 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp)
492 filep = eventfp; 496 filep = eventfp;
493 break; 497 break;
494 case VHOST_SET_VRING_CALL: 498 case VHOST_SET_VRING_CALL:
495 r = copy_from_user(&f, argp, sizeof f); 499 if (copy_from_user(&f, argp, sizeof f)) {
496 if (r < 0) 500 r = -EFAULT;
497 break; 501 break;
502 }
498 eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd); 503 eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd);
499 if (IS_ERR(eventfp)) { 504 if (IS_ERR(eventfp)) {
500 r = PTR_ERR(eventfp); 505 r = PTR_ERR(eventfp);
@@ -510,9 +515,10 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp)
510 filep = eventfp; 515 filep = eventfp;
511 break; 516 break;
512 case VHOST_SET_VRING_ERR: 517 case VHOST_SET_VRING_ERR:
513 r = copy_from_user(&f, argp, sizeof f); 518 if (copy_from_user(&f, argp, sizeof f)) {
514 if (r < 0) 519 r = -EFAULT;
515 break; 520 break;
521 }
516 eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd); 522 eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd);
517 if (IS_ERR(eventfp)) { 523 if (IS_ERR(eventfp)) {
518 r = PTR_ERR(eventfp); 524 r = PTR_ERR(eventfp);
@@ -575,9 +581,10 @@ long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, unsigned long arg)
575 r = vhost_set_memory(d, argp); 581 r = vhost_set_memory(d, argp);
576 break; 582 break;
577 case VHOST_SET_LOG_BASE: 583 case VHOST_SET_LOG_BASE:
578 r = copy_from_user(&p, argp, sizeof p); 584 if (copy_from_user(&p, argp, sizeof p)) {
579 if (r < 0) 585 r = -EFAULT;
580 break; 586 break;
587 }
581 if ((u64)(unsigned long)p != p) { 588 if ((u64)(unsigned long)p != p) {
582 r = -EFAULT; 589 r = -EFAULT;
583 break; 590 break;
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 1e6fec487973..3d94a1471724 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -8,6 +8,9 @@ menu "Graphics support"
8config HAVE_FB_ATMEL 8config HAVE_FB_ATMEL
9 bool 9 bool
10 10
11config HAVE_FB_IMX
12 bool
13
11source "drivers/char/agp/Kconfig" 14source "drivers/char/agp/Kconfig"
12 15
13source "drivers/gpu/vga/Kconfig" 16source "drivers/gpu/vga/Kconfig"
@@ -400,9 +403,6 @@ config FB_SA1100
400 If you plan to use the LCD display with your SA-1100 system, say 403 If you plan to use the LCD display with your SA-1100 system, say
401 Y here. 404 Y here.
402 405
403config HAVE_FB_IMX
404 bool
405
406config FB_IMX 406config FB_IMX
407 tristate "Motorola i.MX LCD support" 407 tristate "Motorola i.MX LCD support"
408 depends on FB && (HAVE_FB_IMX || ARCH_MX1 || ARCH_MX2) 408 depends on FB && (HAVE_FB_IMX || ARCH_MX1 || ARCH_MX2)
diff --git a/drivers/video/aty/mach64_accel.c b/drivers/video/aty/mach64_accel.c
index 51fcc0a2c94a..e45833ce975b 100644
--- a/drivers/video/aty/mach64_accel.c
+++ b/drivers/video/aty/mach64_accel.c
@@ -242,7 +242,7 @@ void atyfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
242void atyfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) 242void atyfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
243{ 243{
244 struct atyfb_par *par = (struct atyfb_par *) info->par; 244 struct atyfb_par *par = (struct atyfb_par *) info->par;
245 u32 color = rect->color, dx = rect->dx, width = rect->width, rotation = 0; 245 u32 color, dx = rect->dx, width = rect->width, rotation = 0;
246 246
247 if (par->asleep) 247 if (par->asleep)
248 return; 248 return;
@@ -253,8 +253,11 @@ void atyfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
253 return; 253 return;
254 } 254 }
255 255
256 color |= (rect->color << 8); 256 if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
257 color |= (rect->color << 16); 257 info->fix.visual == FB_VISUAL_DIRECTCOLOR)
258 color = ((u32 *)(info->pseudo_palette))[rect->color];
259 else
260 color = rect->color;
258 261
259 if (info->var.bits_per_pixel == 24) { 262 if (info->var.bits_per_pixel == 24) {
260 /* In 24 bpp, the engine is in 8 bpp - this requires that all */ 263 /* In 24 bpp, the engine is in 8 bpp - this requires that all */
diff --git a/drivers/video/backlight/88pm860x_bl.c b/drivers/video/backlight/88pm860x_bl.c
index 68d2518fadaa..38ffc3fbcbe4 100644
--- a/drivers/video/backlight/88pm860x_bl.c
+++ b/drivers/video/backlight/88pm860x_bl.c
@@ -222,6 +222,7 @@ static int pm860x_backlight_probe(struct platform_device *pdev)
222 data->port = __check_device(pdata, name); 222 data->port = __check_device(pdata, name);
223 if (data->port < 0) { 223 if (data->port < 0) {
224 dev_err(&pdev->dev, "wrong platform data is assigned"); 224 dev_err(&pdev->dev, "wrong platform data is assigned");
225 kfree(data);
225 return -EINVAL; 226 return -EINVAL;
226 } 227 }
227 228
@@ -266,6 +267,7 @@ static int pm860x_backlight_probe(struct platform_device *pdev)
266 backlight_update_status(bl); 267 backlight_update_status(bl);
267 return 0; 268 return 0;
268out: 269out:
270 backlight_device_unregister(bl);
269 kfree(data); 271 kfree(data);
270 return ret; 272 return ret;
271} 273}
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index c025c84601b0..e54a337227ea 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -8,12 +8,13 @@ menuconfig BACKLIGHT_LCD_SUPPORT
8 Enable this to be able to choose the drivers for controlling the 8 Enable this to be able to choose the drivers for controlling the
9 backlight and the LCD panel on some platforms, for example on PDAs. 9 backlight and the LCD panel on some platforms, for example on PDAs.
10 10
11if BACKLIGHT_LCD_SUPPORT
12
11# 13#
12# LCD 14# LCD
13# 15#
14config LCD_CLASS_DEVICE 16config LCD_CLASS_DEVICE
15 tristate "Lowlevel LCD controls" 17 tristate "Lowlevel LCD controls"
16 depends on BACKLIGHT_LCD_SUPPORT
17 default m 18 default m
18 help 19 help
19 This framework adds support for low-level control of LCD. 20 This framework adds support for low-level control of LCD.
@@ -24,31 +25,32 @@ config LCD_CLASS_DEVICE
24 To have support for your specific LCD panel you will have to 25 To have support for your specific LCD panel you will have to
25 select the proper drivers which depend on this option. 26 select the proper drivers which depend on this option.
26 27
28if LCD_CLASS_DEVICE
29
27config LCD_CORGI 30config LCD_CORGI
28 tristate "LCD Panel support for SHARP corgi/spitz model" 31 tristate "LCD Panel support for SHARP corgi/spitz model"
29 depends on LCD_CLASS_DEVICE && SPI_MASTER && PXA_SHARPSL 32 depends on SPI_MASTER && PXA_SHARPSL
30 help 33 help
31 Say y here to support the LCD panels usually found on SHARP 34 Say y here to support the LCD panels usually found on SHARP
32 corgi (C7x0) and spitz (Cxx00) models. 35 corgi (C7x0) and spitz (Cxx00) models.
33 36
34config LCD_L4F00242T03 37config LCD_L4F00242T03
35 tristate "Epson L4F00242T03 LCD" 38 tristate "Epson L4F00242T03 LCD"
36 depends on LCD_CLASS_DEVICE && SPI_MASTER && GENERIC_GPIO 39 depends on SPI_MASTER && GENERIC_GPIO
37 help 40 help
38 SPI driver for Epson L4F00242T03. This provides basic support 41 SPI driver for Epson L4F00242T03. This provides basic support
39 for init and powering the LCD up/down through a sysfs interface. 42 for init and powering the LCD up/down through a sysfs interface.
40 43
41config LCD_LMS283GF05 44config LCD_LMS283GF05
42 tristate "Samsung LMS283GF05 LCD" 45 tristate "Samsung LMS283GF05 LCD"
43 depends on LCD_CLASS_DEVICE && SPI_MASTER && GENERIC_GPIO 46 depends on SPI_MASTER && GENERIC_GPIO
44 help 47 help
45 SPI driver for Samsung LMS283GF05. This provides basic support 48 SPI driver for Samsung LMS283GF05. This provides basic support
46 for powering the LCD up/down through a sysfs interface. 49 for powering the LCD up/down through a sysfs interface.
47 50
48config LCD_LTV350QV 51config LCD_LTV350QV
49 tristate "Samsung LTV350QV LCD Panel" 52 tristate "Samsung LTV350QV LCD Panel"
50 depends on LCD_CLASS_DEVICE && SPI_MASTER 53 depends on SPI_MASTER
51 default n
52 help 54 help
53 If you have a Samsung LTV350QV LCD panel, say y to include a 55 If you have a Samsung LTV350QV LCD panel, say y to include a
54 power control driver for it. The panel starts up in power 56 power control driver for it. The panel starts up in power
@@ -59,60 +61,61 @@ config LCD_LTV350QV
59 61
60config LCD_ILI9320 62config LCD_ILI9320
61 tristate 63 tristate
62 depends on LCD_CLASS_DEVICE && BACKLIGHT_LCD_SUPPORT
63 default n
64 help 64 help
65 If you have a panel based on the ILI9320 controller chip 65 If you have a panel based on the ILI9320 controller chip
66 then say y to include a power driver for it. 66 then say y to include a power driver for it.
67 67
68config LCD_TDO24M 68config LCD_TDO24M
69 tristate "Toppoly TDO24M and TDO35S LCD Panels support" 69 tristate "Toppoly TDO24M and TDO35S LCD Panels support"
70 depends on LCD_CLASS_DEVICE && SPI_MASTER 70 depends on SPI_MASTER
71 default n
72 help 71 help
73 If you have a Toppoly TDO24M/TDO35S series LCD panel, say y here to 72 If you have a Toppoly TDO24M/TDO35S series LCD panel, say y here to
74 include the support for it. 73 include the support for it.
75 74
76config LCD_VGG2432A4 75config LCD_VGG2432A4
77 tristate "VGG2432A4 LCM device support" 76 tristate "VGG2432A4 LCM device support"
78 depends on BACKLIGHT_LCD_SUPPORT && LCD_CLASS_DEVICE && SPI_MASTER 77 depends on SPI_MASTER
79 select LCD_ILI9320 78 select LCD_ILI9320
80 default n
81 help 79 help
82 If you have a VGG2432A4 panel based on the ILI9320 controller chip 80 If you have a VGG2432A4 panel based on the ILI9320 controller chip
83 then say y to include a power driver for it. 81 then say y to include a power driver for it.
84 82
85config LCD_PLATFORM 83config LCD_PLATFORM
86 tristate "Platform LCD controls" 84 tristate "Platform LCD controls"
87 depends on LCD_CLASS_DEVICE
88 help 85 help
89 This driver provides a platform-device registered LCD power 86 This driver provides a platform-device registered LCD power
90 control interface. 87 control interface.
91 88
92config LCD_TOSA 89config LCD_TOSA
93 tristate "Sharp SL-6000 LCD Driver" 90 tristate "Sharp SL-6000 LCD Driver"
94 depends on LCD_CLASS_DEVICE && SPI 91 depends on SPI && MACH_TOSA
95 depends on MACH_TOSA
96 default n
97 help 92 help
98 If you have an Sharp SL-6000 Zaurus say Y to enable a driver 93 If you have an Sharp SL-6000 Zaurus say Y to enable a driver
99 for its LCD. 94 for its LCD.
100 95
101config LCD_HP700 96config LCD_HP700
102 tristate "HP Jornada 700 series LCD Driver" 97 tristate "HP Jornada 700 series LCD Driver"
103 depends on LCD_CLASS_DEVICE
104 depends on SA1100_JORNADA720_SSP && !PREEMPT 98 depends on SA1100_JORNADA720_SSP && !PREEMPT
105 default y 99 default y
106 help 100 help
107 If you have an HP Jornada 700 series handheld (710/720/728) 101 If you have an HP Jornada 700 series handheld (710/720/728)
108 say Y to enable LCD control driver. 102 say Y to enable LCD control driver.
109 103
104config LCD_S6E63M0
105 tristate "S6E63M0 AMOLED LCD Driver"
106 depends on SPI && BACKLIGHT_CLASS_DEVICE
107 default n
108 help
109 If you have an S6E63M0 LCD Panel, say Y to enable its
110 LCD control driver.
111
112endif # LCD_CLASS_DEVICE
113
110# 114#
111# Backlight 115# Backlight
112# 116#
113config BACKLIGHT_CLASS_DEVICE 117config BACKLIGHT_CLASS_DEVICE
114 tristate "Lowlevel Backlight controls" 118 tristate "Lowlevel Backlight controls"
115 depends on BACKLIGHT_LCD_SUPPORT
116 default m 119 default m
117 help 120 help
118 This framework adds support for low-level control of the LCD 121 This framework adds support for low-level control of the LCD
@@ -121,9 +124,11 @@ config BACKLIGHT_CLASS_DEVICE
121 To have support for your specific LCD panel you will have to 124 To have support for your specific LCD panel you will have to
122 select the proper drivers which depend on this option. 125 select the proper drivers which depend on this option.
123 126
127if BACKLIGHT_CLASS_DEVICE
128
124config BACKLIGHT_ATMEL_LCDC 129config BACKLIGHT_ATMEL_LCDC
125 bool "Atmel LCDC Contrast-as-Backlight control" 130 bool "Atmel LCDC Contrast-as-Backlight control"
126 depends on BACKLIGHT_CLASS_DEVICE && FB_ATMEL 131 depends on FB_ATMEL
127 default y if MACH_SAM9261EK || MACH_SAM9G10EK || MACH_SAM9263EK 132 default y if MACH_SAM9261EK || MACH_SAM9G10EK || MACH_SAM9263EK
128 help 133 help
129 This provides a backlight control internal to the Atmel LCDC 134 This provides a backlight control internal to the Atmel LCDC
@@ -136,8 +141,7 @@ config BACKLIGHT_ATMEL_LCDC
136 141
137config BACKLIGHT_ATMEL_PWM 142config BACKLIGHT_ATMEL_PWM
138 tristate "Atmel PWM backlight control" 143 tristate "Atmel PWM backlight control"
139 depends on BACKLIGHT_CLASS_DEVICE && ATMEL_PWM 144 depends on ATMEL_PWM
140 default n
141 help 145 help
142 Say Y here if you want to use the PWM peripheral in Atmel AT91 and 146 Say Y here if you want to use the PWM peripheral in Atmel AT91 and
143 AVR32 devices. This driver will need additional platform data to know 147 AVR32 devices. This driver will need additional platform data to know
@@ -146,9 +150,18 @@ config BACKLIGHT_ATMEL_PWM
146 To compile this driver as a module, choose M here: the module will be 150 To compile this driver as a module, choose M here: the module will be
147 called atmel-pwm-bl. 151 called atmel-pwm-bl.
148 152
153config BACKLIGHT_EP93XX
154 tristate "Cirrus EP93xx Backlight Driver"
155 depends on FB_EP93XX
156 help
157 If you have a LCD backlight connected to the BRIGHT output of
158 the EP93xx, say Y here to enable this driver.
159
160 To compile this driver as a module, choose M here: the module will
161 be called ep93xx_bl.
162
149config BACKLIGHT_GENERIC 163config BACKLIGHT_GENERIC
150 tristate "Generic (aka Sharp Corgi) Backlight Driver" 164 tristate "Generic (aka Sharp Corgi) Backlight Driver"
151 depends on BACKLIGHT_CLASS_DEVICE
152 default y 165 default y
153 help 166 help
154 Say y to enable the generic platform backlight driver previously 167 Say y to enable the generic platform backlight driver previously
@@ -157,7 +170,7 @@ config BACKLIGHT_GENERIC
157 170
158config BACKLIGHT_LOCOMO 171config BACKLIGHT_LOCOMO
159 tristate "Sharp LOCOMO LCD/Backlight Driver" 172 tristate "Sharp LOCOMO LCD/Backlight Driver"
160 depends on BACKLIGHT_CLASS_DEVICE && SHARP_LOCOMO 173 depends on SHARP_LOCOMO
161 default y 174 default y
162 help 175 help
163 If you have a Sharp Zaurus SL-5500 (Collie) or SL-5600 (Poodle) say y to 176 If you have a Sharp Zaurus SL-5500 (Collie) or SL-5600 (Poodle) say y to
@@ -165,7 +178,7 @@ config BACKLIGHT_LOCOMO
165 178
166config BACKLIGHT_OMAP1 179config BACKLIGHT_OMAP1
167 tristate "OMAP1 PWL-based LCD Backlight" 180 tristate "OMAP1 PWL-based LCD Backlight"
168 depends on BACKLIGHT_CLASS_DEVICE && ARCH_OMAP1 181 depends on ARCH_OMAP1
169 default y 182 default y
170 help 183 help
171 This driver controls the LCD backlight level and power for 184 This driver controls the LCD backlight level and power for
@@ -174,7 +187,7 @@ config BACKLIGHT_OMAP1
174 187
175config BACKLIGHT_HP680 188config BACKLIGHT_HP680
176 tristate "HP Jornada 680 Backlight Driver" 189 tristate "HP Jornada 680 Backlight Driver"
177 depends on BACKLIGHT_CLASS_DEVICE && SH_HP6XX 190 depends on SH_HP6XX
178 default y 191 default y
179 help 192 help
180 If you have a HP Jornada 680, say y to enable the 193 If you have a HP Jornada 680, say y to enable the
@@ -182,7 +195,6 @@ config BACKLIGHT_HP680
182 195
183config BACKLIGHT_HP700 196config BACKLIGHT_HP700
184 tristate "HP Jornada 700 series Backlight Driver" 197 tristate "HP Jornada 700 series Backlight Driver"
185 depends on BACKLIGHT_CLASS_DEVICE
186 depends on SA1100_JORNADA720_SSP && !PREEMPT 198 depends on SA1100_JORNADA720_SSP && !PREEMPT
187 default y 199 default y
188 help 200 help
@@ -191,76 +203,70 @@ config BACKLIGHT_HP700
191 203
192config BACKLIGHT_PROGEAR 204config BACKLIGHT_PROGEAR
193 tristate "Frontpath ProGear Backlight Driver" 205 tristate "Frontpath ProGear Backlight Driver"
194 depends on BACKLIGHT_CLASS_DEVICE && PCI && X86 206 depends on PCI && X86
195 default n
196 help 207 help
197 If you have a Frontpath ProGear say Y to enable the 208 If you have a Frontpath ProGear say Y to enable the
198 backlight driver. 209 backlight driver.
199 210
200config BACKLIGHT_CARILLO_RANCH 211config BACKLIGHT_CARILLO_RANCH
201 tristate "Intel Carillo Ranch Backlight Driver" 212 tristate "Intel Carillo Ranch Backlight Driver"
202 depends on BACKLIGHT_CLASS_DEVICE && LCD_CLASS_DEVICE && PCI && X86 && FB_LE80578 213 depends on LCD_CLASS_DEVICE && PCI && X86 && FB_LE80578
203 default n
204 help 214 help
205 If you have a Intel LE80578 (Carillo Ranch) say Y to enable the 215 If you have a Intel LE80578 (Carillo Ranch) say Y to enable the
206 backlight driver. 216 backlight driver.
207 217
208config BACKLIGHT_PWM 218config BACKLIGHT_PWM
209 tristate "Generic PWM based Backlight Driver" 219 tristate "Generic PWM based Backlight Driver"
210 depends on BACKLIGHT_CLASS_DEVICE && HAVE_PWM 220 depends on HAVE_PWM
211 help 221 help
212 If you have a LCD backlight adjustable by PWM, say Y to enable 222 If you have a LCD backlight adjustable by PWM, say Y to enable
213 this driver. 223 this driver.
214 224
215config BACKLIGHT_DA903X 225config BACKLIGHT_DA903X
216 tristate "Backlight Driver for DA9030/DA9034 using WLED" 226 tristate "Backlight Driver for DA9030/DA9034 using WLED"
217 depends on BACKLIGHT_CLASS_DEVICE && PMIC_DA903X 227 depends on PMIC_DA903X
218 help 228 help
219 If you have a LCD backlight connected to the WLED output of DA9030 229 If you have a LCD backlight connected to the WLED output of DA9030
220 or DA9034 WLED output, say Y here to enable this driver. 230 or DA9034 WLED output, say Y here to enable this driver.
221 231
222config BACKLIGHT_MAX8925 232config BACKLIGHT_MAX8925
223 tristate "Backlight driver for MAX8925" 233 tristate "Backlight driver for MAX8925"
224 depends on BACKLIGHT_CLASS_DEVICE && MFD_MAX8925 234 depends on MFD_MAX8925
225 help 235 help
226 If you have a LCD backlight connected to the WLED output of MAX8925 236 If you have a LCD backlight connected to the WLED output of MAX8925
227 WLED output, say Y here to enable this driver. 237 WLED output, say Y here to enable this driver.
228 238
229config BACKLIGHT_MBP_NVIDIA 239config BACKLIGHT_MBP_NVIDIA
230 tristate "MacBook Pro Nvidia Backlight Driver" 240 tristate "MacBook Pro Nvidia Backlight Driver"
231 depends on BACKLIGHT_CLASS_DEVICE && X86 241 depends on X86
232 default n
233 help 242 help
234 If you have an Apple Macbook Pro with Nvidia graphics hardware say Y 243 If you have an Apple Macbook Pro with Nvidia graphics hardware say Y
235 to enable a driver for its backlight 244 to enable a driver for its backlight
236 245
237config BACKLIGHT_TOSA 246config BACKLIGHT_TOSA
238 tristate "Sharp SL-6000 Backlight Driver" 247 tristate "Sharp SL-6000 Backlight Driver"
239 depends on BACKLIGHT_CLASS_DEVICE && I2C 248 depends on I2C && MACH_TOSA && LCD_TOSA
240 depends on MACH_TOSA && LCD_TOSA
241 default n
242 help 249 help
243 If you have an Sharp SL-6000 Zaurus say Y to enable a driver 250 If you have an Sharp SL-6000 Zaurus say Y to enable a driver
244 for its backlight 251 for its backlight
245 252
246config BACKLIGHT_SAHARA 253config BACKLIGHT_SAHARA
247 tristate "Tabletkiosk Sahara Touch-iT Backlight Driver" 254 tristate "Tabletkiosk Sahara Touch-iT Backlight Driver"
248 depends on BACKLIGHT_CLASS_DEVICE && X86 255 depends on X86
249 default n
250 help 256 help
251 If you have a Tabletkiosk Sahara Touch-iT, say y to enable the 257 If you have a Tabletkiosk Sahara Touch-iT, say y to enable the
252 backlight driver. 258 backlight driver.
253 259
254config BACKLIGHT_WM831X 260config BACKLIGHT_WM831X
255 tristate "WM831x PMIC Backlight Driver" 261 tristate "WM831x PMIC Backlight Driver"
256 depends on BACKLIGHT_CLASS_DEVICE && MFD_WM831X 262 depends on MFD_WM831X
257 help 263 help
258 If you have a backlight driven by the ISINK and DCDC of a 264 If you have a backlight driven by the ISINK and DCDC of a
259 WM831x PMIC say y to enable the backlight driver for it. 265 WM831x PMIC say y to enable the backlight driver for it.
260 266
261config BACKLIGHT_ADX 267config BACKLIGHT_ADX
262 tristate "Avionic Design Xanthos Backlight Driver" 268 tristate "Avionic Design Xanthos Backlight Driver"
263 depends on BACKLIGHT_CLASS_DEVICE && ARCH_PXA_ADX 269 depends on ARCH_PXA_ADX
264 default y 270 default y
265 help 271 help
266 Say Y to enable the backlight driver on Avionic Design Xanthos-based 272 Say Y to enable the backlight driver on Avionic Design Xanthos-based
@@ -268,7 +274,7 @@ config BACKLIGHT_ADX
268 274
269config BACKLIGHT_ADP5520 275config BACKLIGHT_ADP5520
270 tristate "Backlight Driver for ADP5520/ADP5501 using WLED" 276 tristate "Backlight Driver for ADP5520/ADP5501 using WLED"
271 depends on BACKLIGHT_CLASS_DEVICE && PMIC_ADP5520 277 depends on PMIC_ADP5520
272 help 278 help
273 If you have a LCD backlight connected to the BST/BL_SNK output of 279 If you have a LCD backlight connected to the BST/BL_SNK output of
274 ADP5520 or ADP5501, say Y here to enable this driver. 280 ADP5520 or ADP5501, say Y here to enable this driver.
@@ -276,9 +282,31 @@ config BACKLIGHT_ADP5520
276 To compile this driver as a module, choose M here: the module will 282 To compile this driver as a module, choose M here: the module will
277 be called adp5520_bl. 283 be called adp5520_bl.
278 284
285config BACKLIGHT_ADP8860
286 tristate "Backlight Driver for ADP8860/ADP8861/ADP8863 using WLED"
287 depends on BACKLIGHT_CLASS_DEVICE && I2C
288 select NEW_LEDS
289 select LEDS_CLASS
290 help
291 If you have a LCD backlight connected to the ADP8860, ADP8861 or
292 ADP8863 say Y here to enable this driver.
293
294 To compile this driver as a module, choose M here: the module will
295 be called adp8860_bl.
296
279config BACKLIGHT_88PM860X 297config BACKLIGHT_88PM860X
280 tristate "Backlight Driver for 88PM8606 using WLED" 298 tristate "Backlight Driver for 88PM8606 using WLED"
281 depends on BACKLIGHT_CLASS_DEVICE && MFD_88PM860X 299 depends on MFD_88PM860X
282 help 300 help
283 Say Y to enable the backlight driver for Marvell 88PM8606. 301 Say Y to enable the backlight driver for Marvell 88PM8606.
284 302
303config BACKLIGHT_PCF50633
304 tristate "Backlight driver for NXP PCF50633 MFD"
305 depends on BACKLIGHT_CLASS_DEVICE && MFD_PCF50633
306 help
307 If you have a backlight driven by a NXP PCF50633 MFD, say Y here to
308 enable its driver.
309
310endif # BACKLIGHT_CLASS_DEVICE
311
312endif # BACKLIGHT_LCD_SUPPORT
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index 09d1f14d6257..44c0f81ad85d 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -11,9 +11,11 @@ obj-$(CONFIG_LCD_PLATFORM) += platform_lcd.o
11obj-$(CONFIG_LCD_VGG2432A4) += vgg2432a4.o 11obj-$(CONFIG_LCD_VGG2432A4) += vgg2432a4.o
12obj-$(CONFIG_LCD_TDO24M) += tdo24m.o 12obj-$(CONFIG_LCD_TDO24M) += tdo24m.o
13obj-$(CONFIG_LCD_TOSA) += tosa_lcd.o 13obj-$(CONFIG_LCD_TOSA) += tosa_lcd.o
14obj-$(CONFIG_LCD_S6E63M0) += s6e63m0.o
14 15
15obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o 16obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
16obj-$(CONFIG_BACKLIGHT_ATMEL_PWM) += atmel-pwm-bl.o 17obj-$(CONFIG_BACKLIGHT_ATMEL_PWM) += atmel-pwm-bl.o
18obj-$(CONFIG_BACKLIGHT_EP93XX) += ep93xx_bl.o
17obj-$(CONFIG_BACKLIGHT_GENERIC) += generic_bl.o 19obj-$(CONFIG_BACKLIGHT_GENERIC) += generic_bl.o
18obj-$(CONFIG_BACKLIGHT_HP700) += jornada720_bl.o 20obj-$(CONFIG_BACKLIGHT_HP700) += jornada720_bl.o
19obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o 21obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o
@@ -30,5 +32,7 @@ obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o
30obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o 32obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o
31obj-$(CONFIG_BACKLIGHT_ADX) += adx_bl.o 33obj-$(CONFIG_BACKLIGHT_ADX) += adx_bl.o
32obj-$(CONFIG_BACKLIGHT_ADP5520) += adp5520_bl.o 34obj-$(CONFIG_BACKLIGHT_ADP5520) += adp5520_bl.o
35obj-$(CONFIG_BACKLIGHT_ADP8860) += adp8860_bl.o
33obj-$(CONFIG_BACKLIGHT_88PM860X) += 88pm860x_bl.o 36obj-$(CONFIG_BACKLIGHT_88PM860X) += 88pm860x_bl.o
37obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o
34 38
diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c
new file mode 100644
index 000000000000..3ec24609151e
--- /dev/null
+++ b/drivers/video/backlight/adp8860_bl.c
@@ -0,0 +1,836 @@
1/*
2 * Backlight driver for Analog Devices ADP8860 Backlight Devices
3 *
4 * Copyright 2009-2010 Analog Devices Inc.
5 *
6 * Licensed under the GPL-2 or later.
7 */
8
9#include <linux/module.h>
10#include <linux/version.h>
11#include <linux/init.h>
12#include <linux/errno.h>
13#include <linux/pm.h>
14#include <linux/platform_device.h>
15#include <linux/i2c.h>
16#include <linux/fb.h>
17#include <linux/backlight.h>
18#include <linux/leds.h>
19#include <linux/slab.h>
20#include <linux/workqueue.h>
21
22#include <linux/i2c/adp8860.h>
23#define ADP8860_EXT_FEATURES
24#define ADP8860_USE_LEDS
25
26#define ADP8860_MFDVID 0x00 /* Manufacturer and device ID */
27#define ADP8860_MDCR 0x01 /* Device mode and status */
28#define ADP8860_MDCR2 0x02 /* Device mode and Status Register 2 */
29#define ADP8860_INTR_EN 0x03 /* Interrupts enable */
30#define ADP8860_CFGR 0x04 /* Configuration register */
31#define ADP8860_BLSEN 0x05 /* Sink enable backlight or independent */
32#define ADP8860_BLOFF 0x06 /* Backlight off timeout */
33#define ADP8860_BLDIM 0x07 /* Backlight dim timeout */
34#define ADP8860_BLFR 0x08 /* Backlight fade in and out rates */
35#define ADP8860_BLMX1 0x09 /* Backlight (Brightness Level 1-daylight) maximum current */
36#define ADP8860_BLDM1 0x0A /* Backlight (Brightness Level 1-daylight) dim current */
37#define ADP8860_BLMX2 0x0B /* Backlight (Brightness Level 2-office) maximum current */
38#define ADP8860_BLDM2 0x0C /* Backlight (Brightness Level 2-office) dim current */
39#define ADP8860_BLMX3 0x0D /* Backlight (Brightness Level 3-dark) maximum current */
40#define ADP8860_BLDM3 0x0E /* Backlight (Brightness Level 3-dark) dim current */
41#define ADP8860_ISCFR 0x0F /* Independent sink current fade control register */
42#define ADP8860_ISCC 0x10 /* Independent sink current control register */
43#define ADP8860_ISCT1 0x11 /* Independent Sink Current Timer Register LED[7:5] */
44#define ADP8860_ISCT2 0x12 /* Independent Sink Current Timer Register LED[4:1] */
45#define ADP8860_ISCF 0x13 /* Independent sink current fade register */
46#define ADP8860_ISC7 0x14 /* Independent Sink Current LED7 */
47#define ADP8860_ISC6 0x15 /* Independent Sink Current LED6 */
48#define ADP8860_ISC5 0x16 /* Independent Sink Current LED5 */
49#define ADP8860_ISC4 0x17 /* Independent Sink Current LED4 */
50#define ADP8860_ISC3 0x18 /* Independent Sink Current LED3 */
51#define ADP8860_ISC2 0x19 /* Independent Sink Current LED2 */
52#define ADP8860_ISC1 0x1A /* Independent Sink Current LED1 */
53#define ADP8860_CCFG 0x1B /* Comparator configuration */
54#define ADP8860_CCFG2 0x1C /* Second comparator configuration */
55#define ADP8860_L2_TRP 0x1D /* L2 comparator reference */
56#define ADP8860_L2_HYS 0x1E /* L2 hysteresis */
57#define ADP8860_L3_TRP 0x1F /* L3 comparator reference */
58#define ADP8860_L3_HYS 0x20 /* L3 hysteresis */
59#define ADP8860_PH1LEVL 0x21 /* First phototransistor ambient light level-low byte register */
60#define ADP8860_PH1LEVH 0x22 /* First phototransistor ambient light level-high byte register */
61#define ADP8860_PH2LEVL 0x23 /* Second phototransistor ambient light level-low byte register */
62#define ADP8860_PH2LEVH 0x24 /* Second phototransistor ambient light level-high byte register */
63
64#define ADP8860_MANUFID 0x0 /* Analog Devices ADP8860 Manufacturer ID */
65#define ADP8861_MANUFID 0x4 /* Analog Devices ADP8861 Manufacturer ID */
66#define ADP8863_MANUFID 0x2 /* Analog Devices ADP8863 Manufacturer ID */
67
68#define ADP8860_DEVID(x) ((x) & 0xF)
69#define ADP8860_MANID(x) ((x) >> 4)
70
71/* MDCR Device mode and status */
72#define INT_CFG (1 << 6)
73#define NSTBY (1 << 5)
74#define DIM_EN (1 << 4)
75#define GDWN_DIS (1 << 3)
76#define SIS_EN (1 << 2)
77#define CMP_AUTOEN (1 << 1)
78#define BLEN (1 << 0)
79
80/* ADP8860_CCFG Main ALS comparator level enable */
81#define L3_EN (1 << 1)
82#define L2_EN (1 << 0)
83
84#define CFGR_BLV_SHIFT 3
85#define CFGR_BLV_MASK 0x3
86#define ADP8860_FLAG_LED_MASK 0xFF
87
88#define FADE_VAL(in, out) ((0xF & (in)) | ((0xF & (out)) << 4))
89#define BL_CFGR_VAL(law, blv) ((((blv) & CFGR_BLV_MASK) << CFGR_BLV_SHIFT) | ((0x3 & (law)) << 1))
90#define ALS_CCFG_VAL(filt) ((0x7 & filt) << 5)
91
92enum {
93 adp8860,
94 adp8861,
95 adp8863
96};
97
98struct adp8860_led {
99 struct led_classdev cdev;
100 struct work_struct work;
101 struct i2c_client *client;
102 enum led_brightness new_brightness;
103 int id;
104 int flags;
105};
106
107struct adp8860_bl {
108 struct i2c_client *client;
109 struct backlight_device *bl;
110 struct adp8860_led *led;
111 struct adp8860_backlight_platform_data *pdata;
112 struct mutex lock;
113 unsigned long cached_daylight_max;
114 int id;
115 int revid;
116 int current_brightness;
117 unsigned en_ambl_sens:1;
118 unsigned gdwn_dis:1;
119};
120
121static int adp8860_read(struct i2c_client *client, int reg, uint8_t *val)
122{
123 int ret;
124
125 ret = i2c_smbus_read_byte_data(client, reg);
126 if (ret < 0) {
127 dev_err(&client->dev, "failed reading at 0x%02x\n", reg);
128 return ret;
129 }
130
131 *val = (uint8_t)ret;
132 return 0;
133}
134
135static int adp8860_write(struct i2c_client *client, u8 reg, u8 val)
136{
137 return i2c_smbus_write_byte_data(client, reg, val);
138}
139
140static int adp8860_set_bits(struct i2c_client *client, int reg, uint8_t bit_mask)
141{
142 struct adp8860_bl *data = i2c_get_clientdata(client);
143 uint8_t reg_val;
144 int ret;
145
146 mutex_lock(&data->lock);
147
148 ret = adp8860_read(client, reg, &reg_val);
149
150 if (!ret && ((reg_val & bit_mask) == 0)) {
151 reg_val |= bit_mask;
152 ret = adp8860_write(client, reg, reg_val);
153 }
154
155 mutex_unlock(&data->lock);
156 return ret;
157}
158
159static int adp8860_clr_bits(struct i2c_client *client, int reg, uint8_t bit_mask)
160{
161 struct adp8860_bl *data = i2c_get_clientdata(client);
162 uint8_t reg_val;
163 int ret;
164
165 mutex_lock(&data->lock);
166
167 ret = adp8860_read(client, reg, &reg_val);
168
169 if (!ret && (reg_val & bit_mask)) {
170 reg_val &= ~bit_mask;
171 ret = adp8860_write(client, reg, reg_val);
172 }
173
174 mutex_unlock(&data->lock);
175 return ret;
176}
177
178/*
179 * Independent sink / LED
180 */
181#if defined(ADP8860_USE_LEDS)
182static void adp8860_led_work(struct work_struct *work)
183{
184 struct adp8860_led *led = container_of(work, struct adp8860_led, work);
185 adp8860_write(led->client, ADP8860_ISC1 - led->id + 1,
186 led->new_brightness >> 1);
187}
188
189static void adp8860_led_set(struct led_classdev *led_cdev,
190 enum led_brightness value)
191{
192 struct adp8860_led *led;
193
194 led = container_of(led_cdev, struct adp8860_led, cdev);
195 led->new_brightness = value;
196 schedule_work(&led->work);
197}
198
199static int adp8860_led_setup(struct adp8860_led *led)
200{
201 struct i2c_client *client = led->client;
202 int ret = 0;
203
204 ret = adp8860_write(client, ADP8860_ISC1 - led->id + 1, 0);
205 ret |= adp8860_set_bits(client, ADP8860_ISCC, 1 << (led->id - 1));
206
207 if (led->id > 4)
208 ret |= adp8860_set_bits(client, ADP8860_ISCT1,
209 (led->flags & 0x3) << ((led->id - 5) * 2));
210 else
211 ret |= adp8860_set_bits(client, ADP8860_ISCT2,
212 (led->flags & 0x3) << ((led->id - 1) * 2));
213
214 return ret;
215}
216
217static int __devinit adp8860_led_probe(struct i2c_client *client)
218{
219 struct adp8860_backlight_platform_data *pdata =
220 client->dev.platform_data;
221 struct adp8860_bl *data = i2c_get_clientdata(client);
222 struct adp8860_led *led, *led_dat;
223 struct led_info *cur_led;
224 int ret, i;
225
226 led = kzalloc(sizeof(*led) * pdata->num_leds, GFP_KERNEL);
227 if (led == NULL) {
228 dev_err(&client->dev, "failed to alloc memory\n");
229 return -ENOMEM;
230 }
231
232 ret = adp8860_write(client, ADP8860_ISCFR, pdata->led_fade_law);
233 ret = adp8860_write(client, ADP8860_ISCT1,
234 (pdata->led_on_time & 0x3) << 6);
235 ret |= adp8860_write(client, ADP8860_ISCF,
236 FADE_VAL(pdata->led_fade_in, pdata->led_fade_out));
237
238 if (ret) {
239 dev_err(&client->dev, "failed to write\n");
240 goto err_free;
241 }
242
243 for (i = 0; i < pdata->num_leds; ++i) {
244 cur_led = &pdata->leds[i];
245 led_dat = &led[i];
246
247 led_dat->id = cur_led->flags & ADP8860_FLAG_LED_MASK;
248
249 if (led_dat->id > 7 || led_dat->id < 1) {
250 dev_err(&client->dev, "Invalid LED ID %d\n",
251 led_dat->id);
252 goto err;
253 }
254
255 if (pdata->bl_led_assign & (1 << (led_dat->id - 1))) {
256 dev_err(&client->dev, "LED %d used by Backlight\n",
257 led_dat->id);
258 goto err;
259 }
260
261 led_dat->cdev.name = cur_led->name;
262 led_dat->cdev.default_trigger = cur_led->default_trigger;
263 led_dat->cdev.brightness_set = adp8860_led_set;
264 led_dat->cdev.brightness = LED_OFF;
265 led_dat->flags = cur_led->flags >> FLAG_OFFT_SHIFT;
266 led_dat->client = client;
267 led_dat->new_brightness = LED_OFF;
268 INIT_WORK(&led_dat->work, adp8860_led_work);
269
270 ret = led_classdev_register(&client->dev, &led_dat->cdev);
271 if (ret) {
272 dev_err(&client->dev, "failed to register LED %d\n",
273 led_dat->id);
274 goto err;
275 }
276
277 ret = adp8860_led_setup(led_dat);
278 if (ret) {
279 dev_err(&client->dev, "failed to write\n");
280 i++;
281 goto err;
282 }
283 }
284
285 data->led = led;
286
287 return 0;
288
289 err:
290 for (i = i - 1; i >= 0; --i) {
291 led_classdev_unregister(&led[i].cdev);
292 cancel_work_sync(&led[i].work);
293 }
294
295 err_free:
296 kfree(led);
297
298 return ret;
299}
300
301static int __devexit adp8860_led_remove(struct i2c_client *client)
302{
303 struct adp8860_backlight_platform_data *pdata =
304 client->dev.platform_data;
305 struct adp8860_bl *data = i2c_get_clientdata(client);
306 int i;
307
308 for (i = 0; i < pdata->num_leds; i++) {
309 led_classdev_unregister(&data->led[i].cdev);
310 cancel_work_sync(&data->led[i].work);
311 }
312
313 kfree(data->led);
314 return 0;
315}
316#else
317static int __devinit adp8860_led_probe(struct i2c_client *client)
318{
319 return 0;
320}
321
322static int __devexit adp8860_led_remove(struct i2c_client *client)
323{
324 return 0;
325}
326#endif
327
328static int adp8860_bl_set(struct backlight_device *bl, int brightness)
329{
330 struct adp8860_bl *data = bl_get_data(bl);
331 struct i2c_client *client = data->client;
332 int ret = 0;
333
334 if (data->en_ambl_sens) {
335 if ((brightness > 0) && (brightness < ADP8860_MAX_BRIGHTNESS)) {
336 /* Disable Ambient Light auto adjust */
337 ret |= adp8860_clr_bits(client, ADP8860_MDCR,
338 CMP_AUTOEN);
339 ret |= adp8860_write(client, ADP8860_BLMX1, brightness);
340 } else {
341 /*
342 * MAX_BRIGHTNESS -> Enable Ambient Light auto adjust
343 * restore daylight l1 sysfs brightness
344 */
345 ret |= adp8860_write(client, ADP8860_BLMX1,
346 data->cached_daylight_max);
347 ret |= adp8860_set_bits(client, ADP8860_MDCR,
348 CMP_AUTOEN);
349 }
350 } else
351 ret |= adp8860_write(client, ADP8860_BLMX1, brightness);
352
353 if (data->current_brightness && brightness == 0)
354 ret |= adp8860_set_bits(client,
355 ADP8860_MDCR, DIM_EN);
356 else if (data->current_brightness == 0 && brightness)
357 ret |= adp8860_clr_bits(client,
358 ADP8860_MDCR, DIM_EN);
359
360 if (!ret)
361 data->current_brightness = brightness;
362
363 return ret;
364}
365
366static int adp8860_bl_update_status(struct backlight_device *bl)
367{
368 int brightness = bl->props.brightness;
369 if (bl->props.power != FB_BLANK_UNBLANK)
370 brightness = 0;
371
372 if (bl->props.fb_blank != FB_BLANK_UNBLANK)
373 brightness = 0;
374
375 return adp8860_bl_set(bl, brightness);
376}
377
378static int adp8860_bl_get_brightness(struct backlight_device *bl)
379{
380 struct adp8860_bl *data = bl_get_data(bl);
381
382 return data->current_brightness;
383}
384
385static const struct backlight_ops adp8860_bl_ops = {
386 .update_status = adp8860_bl_update_status,
387 .get_brightness = adp8860_bl_get_brightness,
388};
389
390static int adp8860_bl_setup(struct backlight_device *bl)
391{
392 struct adp8860_bl *data = bl_get_data(bl);
393 struct i2c_client *client = data->client;
394 struct adp8860_backlight_platform_data *pdata = data->pdata;
395 int ret = 0;
396
397 ret |= adp8860_write(client, ADP8860_BLSEN, ~pdata->bl_led_assign);
398 ret |= adp8860_write(client, ADP8860_BLMX1, pdata->l1_daylight_max);
399 ret |= adp8860_write(client, ADP8860_BLDM1, pdata->l1_daylight_dim);
400
401 if (data->en_ambl_sens) {
402 data->cached_daylight_max = pdata->l1_daylight_max;
403 ret |= adp8860_write(client, ADP8860_BLMX2,
404 pdata->l2_office_max);
405 ret |= adp8860_write(client, ADP8860_BLDM2,
406 pdata->l2_office_dim);
407 ret |= adp8860_write(client, ADP8860_BLMX3,
408 pdata->l3_dark_max);
409 ret |= adp8860_write(client, ADP8860_BLDM3,
410 pdata->l3_dark_dim);
411
412 ret |= adp8860_write(client, ADP8860_L2_TRP, pdata->l2_trip);
413 ret |= adp8860_write(client, ADP8860_L2_HYS, pdata->l2_hyst);
414 ret |= adp8860_write(client, ADP8860_L3_TRP, pdata->l3_trip);
415 ret |= adp8860_write(client, ADP8860_L3_HYS, pdata->l3_hyst);
416 ret |= adp8860_write(client, ADP8860_CCFG, L2_EN | L3_EN |
417 ALS_CCFG_VAL(pdata->abml_filt));
418 }
419
420 ret |= adp8860_write(client, ADP8860_CFGR,
421 BL_CFGR_VAL(pdata->bl_fade_law, 0));
422
423 ret |= adp8860_write(client, ADP8860_BLFR, FADE_VAL(pdata->bl_fade_in,
424 pdata->bl_fade_out));
425
426 ret |= adp8860_set_bits(client, ADP8860_MDCR, BLEN | DIM_EN | NSTBY |
427 (data->gdwn_dis ? GDWN_DIS : 0));
428
429 return ret;
430}
431
432static ssize_t adp8860_show(struct device *dev, char *buf, int reg)
433{
434 struct adp8860_bl *data = dev_get_drvdata(dev);
435 int error;
436 uint8_t reg_val;
437
438 mutex_lock(&data->lock);
439 error = adp8860_read(data->client, reg, &reg_val);
440 mutex_unlock(&data->lock);
441
442 if (error < 0)
443 return error;
444
445 return sprintf(buf, "%u\n", reg_val);
446}
447
448static ssize_t adp8860_store(struct device *dev, const char *buf,
449 size_t count, int reg)
450{
451 struct adp8860_bl *data = dev_get_drvdata(dev);
452 unsigned long val;
453 int ret;
454
455 ret = strict_strtoul(buf, 10, &val);
456 if (ret)
457 return ret;
458
459 mutex_lock(&data->lock);
460 adp8860_write(data->client, reg, val);
461 mutex_unlock(&data->lock);
462
463 return count;
464}
465
466static ssize_t adp8860_bl_l3_dark_max_show(struct device *dev,
467 struct device_attribute *attr, char *buf)
468{
469 return adp8860_show(dev, buf, ADP8860_BLMX3);
470}
471
472static ssize_t adp8860_bl_l3_dark_max_store(struct device *dev,
473 struct device_attribute *attr, const char *buf, size_t count)
474{
475 return adp8860_store(dev, buf, count, ADP8860_BLMX3);
476}
477
478static DEVICE_ATTR(l3_dark_max, 0664, adp8860_bl_l3_dark_max_show,
479 adp8860_bl_l3_dark_max_store);
480
481static ssize_t adp8860_bl_l2_office_max_show(struct device *dev,
482 struct device_attribute *attr, char *buf)
483{
484 return adp8860_show(dev, buf, ADP8860_BLMX2);
485}
486
487static ssize_t adp8860_bl_l2_office_max_store(struct device *dev,
488 struct device_attribute *attr, const char *buf, size_t count)
489{
490 return adp8860_store(dev, buf, count, ADP8860_BLMX2);
491}
492static DEVICE_ATTR(l2_office_max, 0664, adp8860_bl_l2_office_max_show,
493 adp8860_bl_l2_office_max_store);
494
495static ssize_t adp8860_bl_l1_daylight_max_show(struct device *dev,
496 struct device_attribute *attr, char *buf)
497{
498 return adp8860_show(dev, buf, ADP8860_BLMX1);
499}
500
501static ssize_t adp8860_bl_l1_daylight_max_store(struct device *dev,
502 struct device_attribute *attr, const char *buf, size_t count)
503{
504 struct adp8860_bl *data = dev_get_drvdata(dev);
505
506 strict_strtoul(buf, 10, &data->cached_daylight_max);
507 return adp8860_store(dev, buf, count, ADP8860_BLMX1);
508}
509static DEVICE_ATTR(l1_daylight_max, 0664, adp8860_bl_l1_daylight_max_show,
510 adp8860_bl_l1_daylight_max_store);
511
512static ssize_t adp8860_bl_l3_dark_dim_show(struct device *dev,
513 struct device_attribute *attr, char *buf)
514{
515 return adp8860_show(dev, buf, ADP8860_BLDM3);
516}
517
518static ssize_t adp8860_bl_l3_dark_dim_store(struct device *dev,
519 struct device_attribute *attr,
520 const char *buf, size_t count)
521{
522 return adp8860_store(dev, buf, count, ADP8860_BLDM3);
523}
524static DEVICE_ATTR(l3_dark_dim, 0664, adp8860_bl_l3_dark_dim_show,
525 adp8860_bl_l3_dark_dim_store);
526
527static ssize_t adp8860_bl_l2_office_dim_show(struct device *dev,
528 struct device_attribute *attr, char *buf)
529{
530 return adp8860_show(dev, buf, ADP8860_BLDM2);
531}
532
533static ssize_t adp8860_bl_l2_office_dim_store(struct device *dev,
534 struct device_attribute *attr,
535 const char *buf, size_t count)
536{
537 return adp8860_store(dev, buf, count, ADP8860_BLDM2);
538}
539static DEVICE_ATTR(l2_office_dim, 0664, adp8860_bl_l2_office_dim_show,
540 adp8860_bl_l2_office_dim_store);
541
542static ssize_t adp8860_bl_l1_daylight_dim_show(struct device *dev,
543 struct device_attribute *attr, char *buf)
544{
545 return adp8860_show(dev, buf, ADP8860_BLDM1);
546}
547
548static ssize_t adp8860_bl_l1_daylight_dim_store(struct device *dev,
549 struct device_attribute *attr,
550 const char *buf, size_t count)
551{
552 return adp8860_store(dev, buf, count, ADP8860_BLDM1);
553}
554static DEVICE_ATTR(l1_daylight_dim, 0664, adp8860_bl_l1_daylight_dim_show,
555 adp8860_bl_l1_daylight_dim_store);
556
557#ifdef ADP8860_EXT_FEATURES
558static ssize_t adp8860_bl_ambient_light_level_show(struct device *dev,
559 struct device_attribute *attr, char *buf)
560{
561 struct adp8860_bl *data = dev_get_drvdata(dev);
562 int error;
563 uint8_t reg_val;
564 uint16_t ret_val;
565
566 mutex_lock(&data->lock);
567 error = adp8860_read(data->client, ADP8860_PH1LEVL, &reg_val);
568 ret_val = reg_val;
569 error |= adp8860_read(data->client, ADP8860_PH1LEVH, &reg_val);
570 mutex_unlock(&data->lock);
571
572 if (error < 0)
573 return error;
574
575 /* Return 13-bit conversion value for the first light sensor */
576 ret_val += (reg_val & 0x1F) << 8;
577
578 return sprintf(buf, "%u\n", ret_val);
579}
580static DEVICE_ATTR(ambient_light_level, 0444,
581 adp8860_bl_ambient_light_level_show, NULL);
582
583static ssize_t adp8860_bl_ambient_light_zone_show(struct device *dev,
584 struct device_attribute *attr, char *buf)
585{
586 struct adp8860_bl *data = dev_get_drvdata(dev);
587 int error;
588 uint8_t reg_val;
589
590 mutex_lock(&data->lock);
591 error = adp8860_read(data->client, ADP8860_CFGR, &reg_val);
592 mutex_unlock(&data->lock);
593
594 if (error < 0)
595 return error;
596
597 return sprintf(buf, "%u\n",
598 ((reg_val >> CFGR_BLV_SHIFT) & CFGR_BLV_MASK) + 1);
599}
600
601static ssize_t adp8860_bl_ambient_light_zone_store(struct device *dev,
602 struct device_attribute *attr,
603 const char *buf, size_t count)
604{
605 struct adp8860_bl *data = dev_get_drvdata(dev);
606 unsigned long val;
607 uint8_t reg_val;
608 int ret;
609
610 ret = strict_strtoul(buf, 10, &val);
611 if (ret)
612 return ret;
613
614 if (val == 0) {
615 /* Enable automatic ambient light sensing */
616 adp8860_set_bits(data->client, ADP8860_MDCR, CMP_AUTOEN);
617 } else if ((val > 0) && (val < 6)) {
618 /* Disable automatic ambient light sensing */
619 adp8860_clr_bits(data->client, ADP8860_MDCR, CMP_AUTOEN);
620
621 /* Set user supplied ambient light zone */
622 mutex_lock(&data->lock);
623 adp8860_read(data->client, ADP8860_CFGR, &reg_val);
624 reg_val &= ~(CFGR_BLV_MASK << CFGR_BLV_SHIFT);
625 reg_val |= val << CFGR_BLV_SHIFT;
626 adp8860_write(data->client, ADP8860_CFGR, reg_val);
627 mutex_unlock(&data->lock);
628 }
629
630 return count;
631}
632static DEVICE_ATTR(ambient_light_zone, 0664,
633 adp8860_bl_ambient_light_zone_show,
634 adp8860_bl_ambient_light_zone_store);
635#endif
636
637static struct attribute *adp8860_bl_attributes[] = {
638 &dev_attr_l3_dark_max.attr,
639 &dev_attr_l3_dark_dim.attr,
640 &dev_attr_l2_office_max.attr,
641 &dev_attr_l2_office_dim.attr,
642 &dev_attr_l1_daylight_max.attr,
643 &dev_attr_l1_daylight_dim.attr,
644#ifdef ADP8860_EXT_FEATURES
645 &dev_attr_ambient_light_level.attr,
646 &dev_attr_ambient_light_zone.attr,
647#endif
648 NULL
649};
650
651static const struct attribute_group adp8860_bl_attr_group = {
652 .attrs = adp8860_bl_attributes,
653};
654
655static int __devinit adp8860_probe(struct i2c_client *client,
656 const struct i2c_device_id *id)
657{
658 struct backlight_device *bl;
659 struct adp8860_bl *data;
660 struct adp8860_backlight_platform_data *pdata =
661 client->dev.platform_data;
662 struct backlight_properties props;
663 uint8_t reg_val;
664 int ret;
665
666 if (!i2c_check_functionality(client->adapter,
667 I2C_FUNC_SMBUS_BYTE_DATA)) {
668 dev_err(&client->dev, "SMBUS Byte Data not Supported\n");
669 return -EIO;
670 }
671
672 if (!pdata) {
673 dev_err(&client->dev, "no platform data?\n");
674 return -EINVAL;
675 }
676
677 data = kzalloc(sizeof(*data), GFP_KERNEL);
678 if (data == NULL)
679 return -ENOMEM;
680
681 ret = adp8860_read(client, ADP8860_MFDVID, &reg_val);
682 if (ret < 0)
683 goto out2;
684
685 switch (ADP8860_MANID(reg_val)) {
686 case ADP8863_MANUFID:
687 data->gdwn_dis = !!pdata->gdwn_dis;
688 case ADP8860_MANUFID:
689 data->en_ambl_sens = !!pdata->en_ambl_sens;
690 break;
691 case ADP8861_MANUFID:
692 data->gdwn_dis = !!pdata->gdwn_dis;
693 break;
694 default:
695 dev_err(&client->dev, "failed to probe\n");
696 ret = -ENODEV;
697 goto out2;
698 }
699
700 /* It's confirmed that the DEVID field is actually a REVID */
701
702 data->revid = ADP8860_DEVID(reg_val);
703 data->client = client;
704 data->pdata = pdata;
705 data->id = id->driver_data;
706 data->current_brightness = 0;
707 i2c_set_clientdata(client, data);
708
709 memset(&props, 0, sizeof(props));
710 props.max_brightness = ADP8860_MAX_BRIGHTNESS;
711
712 mutex_init(&data->lock);
713
714 bl = backlight_device_register(dev_driver_string(&client->dev),
715 &client->dev, data, &adp8860_bl_ops, &props);
716 if (IS_ERR(bl)) {
717 dev_err(&client->dev, "failed to register backlight\n");
718 ret = PTR_ERR(bl);
719 goto out2;
720 }
721
722 bl->props.max_brightness =
723 bl->props.brightness = ADP8860_MAX_BRIGHTNESS;
724
725 data->bl = bl;
726
727 if (data->en_ambl_sens)
728 ret = sysfs_create_group(&bl->dev.kobj,
729 &adp8860_bl_attr_group);
730
731 if (ret) {
732 dev_err(&client->dev, "failed to register sysfs\n");
733 goto out1;
734 }
735
736 ret = adp8860_bl_setup(bl);
737 if (ret) {
738 ret = -EIO;
739 goto out;
740 }
741
742 backlight_update_status(bl);
743
744 dev_info(&client->dev, "%s Rev.%d Backlight\n",
745 client->name, data->revid);
746
747 if (pdata->num_leds)
748 adp8860_led_probe(client);
749
750 return 0;
751
752out:
753 if (data->en_ambl_sens)
754 sysfs_remove_group(&data->bl->dev.kobj,
755 &adp8860_bl_attr_group);
756out1:
757 backlight_device_unregister(bl);
758out2:
759 kfree(data);
760
761 return ret;
762}
763
764static int __devexit adp8860_remove(struct i2c_client *client)
765{
766 struct adp8860_bl *data = i2c_get_clientdata(client);
767
768 adp8860_clr_bits(client, ADP8860_MDCR, NSTBY);
769
770 if (data->led)
771 adp8860_led_remove(client);
772
773 if (data->en_ambl_sens)
774 sysfs_remove_group(&data->bl->dev.kobj,
775 &adp8860_bl_attr_group);
776
777 backlight_device_unregister(data->bl);
778 kfree(data);
779
780 return 0;
781}
782
783#ifdef CONFIG_PM
784static int adp8860_i2c_suspend(struct i2c_client *client, pm_message_t message)
785{
786 adp8860_clr_bits(client, ADP8860_MDCR, NSTBY);
787
788 return 0;
789}
790
791static int adp8860_i2c_resume(struct i2c_client *client)
792{
793 adp8860_set_bits(client, ADP8860_MDCR, NSTBY);
794
795 return 0;
796}
797#else
798#define adp8860_i2c_suspend NULL
799#define adp8860_i2c_resume NULL
800#endif
801
802static const struct i2c_device_id adp8860_id[] = {
803 { "adp8860", adp8860 },
804 { "adp8861", adp8861 },
805 { "adp8863", adp8863 },
806 { }
807};
808MODULE_DEVICE_TABLE(i2c, adp8860_id);
809
810static struct i2c_driver adp8860_driver = {
811 .driver = {
812 .name = KBUILD_MODNAME,
813 },
814 .probe = adp8860_probe,
815 .remove = __devexit_p(adp8860_remove),
816 .suspend = adp8860_i2c_suspend,
817 .resume = adp8860_i2c_resume,
818 .id_table = adp8860_id,
819};
820
821static int __init adp8860_init(void)
822{
823 return i2c_add_driver(&adp8860_driver);
824}
825module_init(adp8860_init);
826
827static void __exit adp8860_exit(void)
828{
829 i2c_del_driver(&adp8860_driver);
830}
831module_exit(adp8860_exit);
832
833MODULE_LICENSE("GPL v2");
834MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
835MODULE_DESCRIPTION("ADP8860 Backlight driver");
836MODULE_ALIAS("i2c:adp8860-backlight");
diff --git a/drivers/video/backlight/adx_bl.c b/drivers/video/backlight/adx_bl.c
index 7f4a7c30a98b..fe9af129c5dd 100644
--- a/drivers/video/backlight/adx_bl.c
+++ b/drivers/video/backlight/adx_bl.c
@@ -107,8 +107,8 @@ static int __devinit adx_backlight_probe(struct platform_device *pdev)
107 props.max_brightness = 0xff; 107 props.max_brightness = 0xff;
108 bldev = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, 108 bldev = backlight_device_register(dev_name(&pdev->dev), &pdev->dev,
109 bl, &adx_backlight_ops, &props); 109 bl, &adx_backlight_ops, &props);
110 if (!bldev) { 110 if (IS_ERR(bldev)) {
111 ret = -ENOMEM; 111 ret = PTR_ERR(bldev);
112 goto out; 112 goto out;
113 } 113 }
114 114
diff --git a/drivers/video/backlight/ep93xx_bl.c b/drivers/video/backlight/ep93xx_bl.c
new file mode 100644
index 000000000000..b0cc49184803
--- /dev/null
+++ b/drivers/video/backlight/ep93xx_bl.c
@@ -0,0 +1,160 @@
1/*
2 * Driver for the Cirrus EP93xx lcd backlight
3 *
4 * Copyright (c) 2010 H Hartley Sweeten <hsweeten@visionengravers.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This driver controls the pulse width modulated brightness control output,
11 * BRIGHT, on the Cirrus EP9307, EP9312, and EP9315 processors.
12 */
13
14
15#include <linux/platform_device.h>
16#include <linux/io.h>
17#include <linux/fb.h>
18#include <linux/backlight.h>
19
20#include <mach/hardware.h>
21
22#define EP93XX_RASTER_REG(x) (EP93XX_RASTER_BASE + (x))
23#define EP93XX_RASTER_BRIGHTNESS EP93XX_RASTER_REG(0x20)
24
25#define EP93XX_MAX_COUNT 255
26#define EP93XX_MAX_BRIGHT 255
27#define EP93XX_DEF_BRIGHT 128
28
29struct ep93xxbl {
30 void __iomem *mmio;
31 int brightness;
32};
33
34static int ep93xxbl_set(struct backlight_device *bl, int brightness)
35{
36 struct ep93xxbl *ep93xxbl = bl_get_data(bl);
37
38 __raw_writel((brightness << 8) | EP93XX_MAX_COUNT, ep93xxbl->mmio);
39
40 ep93xxbl->brightness = brightness;
41
42 return 0;
43}
44
45static int ep93xxbl_update_status(struct backlight_device *bl)
46{
47 int brightness = bl->props.brightness;
48
49 if (bl->props.power != FB_BLANK_UNBLANK ||
50 bl->props.fb_blank != FB_BLANK_UNBLANK)
51 brightness = 0;
52
53 return ep93xxbl_set(bl, brightness);
54}
55
56static int ep93xxbl_get_brightness(struct backlight_device *bl)
57{
58 struct ep93xxbl *ep93xxbl = bl_get_data(bl);
59
60 return ep93xxbl->brightness;
61}
62
63static const struct backlight_ops ep93xxbl_ops = {
64 .update_status = ep93xxbl_update_status,
65 .get_brightness = ep93xxbl_get_brightness,
66};
67
68static int __init ep93xxbl_probe(struct platform_device *dev)
69{
70 struct ep93xxbl *ep93xxbl;
71 struct backlight_device *bl;
72 struct backlight_properties props;
73
74 ep93xxbl = devm_kzalloc(&dev->dev, sizeof(*ep93xxbl), GFP_KERNEL);
75 if (!ep93xxbl)
76 return -ENOMEM;
77
78 /*
79 * This register is located in the range already ioremap'ed by
80 * the framebuffer driver. A MFD driver seems a bit of overkill
81 * to handle this so use the static I/O mapping; this address
82 * is already virtual.
83 *
84 * NOTE: No locking is required; the framebuffer does not touch
85 * this register.
86 */
87 ep93xxbl->mmio = EP93XX_RASTER_BRIGHTNESS;
88
89 memset(&props, 0, sizeof(struct backlight_properties));
90 props.max_brightness = EP93XX_MAX_BRIGHT;
91 bl = backlight_device_register(dev->name, &dev->dev, ep93xxbl,
92 &ep93xxbl_ops, &props);
93 if (IS_ERR(bl))
94 return PTR_ERR(bl);
95
96 bl->props.brightness = EP93XX_DEF_BRIGHT;
97
98 platform_set_drvdata(dev, bl);
99
100 ep93xxbl_update_status(bl);
101
102 return 0;
103}
104
105static int ep93xxbl_remove(struct platform_device *dev)
106{
107 struct backlight_device *bl = platform_get_drvdata(dev);
108
109 backlight_device_unregister(bl);
110 platform_set_drvdata(dev, NULL);
111 return 0;
112}
113
114#ifdef CONFIG_PM
115static int ep93xxbl_suspend(struct platform_device *dev, pm_message_t state)
116{
117 struct backlight_device *bl = platform_get_drvdata(dev);
118
119 return ep93xxbl_set(bl, 0);
120}
121
122static int ep93xxbl_resume(struct platform_device *dev)
123{
124 struct backlight_device *bl = platform_get_drvdata(dev);
125
126 backlight_update_status(bl);
127 return 0;
128}
129#else
130#define ep93xxbl_suspend NULL
131#define ep93xxbl_resume NULL
132#endif
133
134static struct platform_driver ep93xxbl_driver = {
135 .driver = {
136 .name = "ep93xx-bl",
137 .owner = THIS_MODULE,
138 },
139 .probe = ep93xxbl_probe,
140 .remove = __devexit_p(ep93xxbl_remove),
141 .suspend = ep93xxbl_suspend,
142 .resume = ep93xxbl_resume,
143};
144
145static int __init ep93xxbl_init(void)
146{
147 return platform_driver_register(&ep93xxbl_driver);
148}
149module_init(ep93xxbl_init);
150
151static void __exit ep93xxbl_exit(void)
152{
153 platform_driver_unregister(&ep93xxbl_driver);
154}
155module_exit(ep93xxbl_exit);
156
157MODULE_DESCRIPTION("EP93xx Backlight Driver");
158MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>");
159MODULE_LICENSE("GPL");
160MODULE_ALIAS("platform:ep93xx-bl");
diff --git a/drivers/video/backlight/l4f00242t03.c b/drivers/video/backlight/l4f00242t03.c
index bcdb12c93efd..9093ef0fa869 100644
--- a/drivers/video/backlight/l4f00242t03.c
+++ b/drivers/video/backlight/l4f00242t03.c
@@ -125,8 +125,7 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi)
125 125
126 if (priv == NULL) { 126 if (priv == NULL) {
127 dev_err(&spi->dev, "No memory for this device.\n"); 127 dev_err(&spi->dev, "No memory for this device.\n");
128 ret = -ENOMEM; 128 return -ENOMEM;
129 goto err;
130 } 129 }
131 130
132 dev_set_drvdata(&spi->dev, priv); 131 dev_set_drvdata(&spi->dev, priv);
@@ -139,7 +138,7 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi)
139 if (ret) { 138 if (ret) {
140 dev_err(&spi->dev, 139 dev_err(&spi->dev,
141 "Unable to get the lcd l4f00242t03 reset gpio.\n"); 140 "Unable to get the lcd l4f00242t03 reset gpio.\n");
142 return ret; 141 goto err;
143 } 142 }
144 143
145 ret = gpio_direction_output(pdata->reset_gpio, 1); 144 ret = gpio_direction_output(pdata->reset_gpio, 1);
@@ -151,7 +150,7 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi)
151 if (ret) { 150 if (ret) {
152 dev_err(&spi->dev, 151 dev_err(&spi->dev,
153 "Unable to get the lcd l4f00242t03 data en gpio.\n"); 152 "Unable to get the lcd l4f00242t03 data en gpio.\n");
154 return ret; 153 goto err2;
155 } 154 }
156 155
157 ret = gpio_direction_output(pdata->data_enable_gpio, 0); 156 ret = gpio_direction_output(pdata->data_enable_gpio, 0);
@@ -222,9 +221,9 @@ static int __devexit l4f00242t03_remove(struct spi_device *spi)
222 gpio_free(pdata->reset_gpio); 221 gpio_free(pdata->reset_gpio);
223 222
224 if (priv->io_reg) 223 if (priv->io_reg)
225 regulator_put(priv->core_reg);
226 if (priv->core_reg)
227 regulator_put(priv->io_reg); 224 regulator_put(priv->io_reg);
225 if (priv->core_reg)
226 regulator_put(priv->core_reg);
228 227
229 kfree(priv); 228 kfree(priv);
230 229
diff --git a/drivers/video/backlight/max8925_bl.c b/drivers/video/backlight/max8925_bl.c
index b5accc957ad3..b2b2c7ba1f63 100644
--- a/drivers/video/backlight/max8925_bl.c
+++ b/drivers/video/backlight/max8925_bl.c
@@ -162,6 +162,7 @@ static int __devinit max8925_backlight_probe(struct platform_device *pdev)
162 backlight_update_status(bl); 162 backlight_update_status(bl);
163 return 0; 163 return 0;
164out: 164out:
165 backlight_device_unregister(bl);
165 kfree(data); 166 kfree(data);
166 return ret; 167 return ret;
167} 168}
diff --git a/drivers/video/backlight/mbp_nvidia_bl.c b/drivers/video/backlight/mbp_nvidia_bl.c
index 1b5d3fe6bbbc..9fb533f6373e 100644
--- a/drivers/video/backlight/mbp_nvidia_bl.c
+++ b/drivers/video/backlight/mbp_nvidia_bl.c
@@ -141,7 +141,7 @@ static const struct dmi_system_id __initdata mbp_device_table[] = {
141 .callback = mbp_dmi_match, 141 .callback = mbp_dmi_match,
142 .ident = "MacBook 1,1", 142 .ident = "MacBook 1,1",
143 .matches = { 143 .matches = {
144 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), 144 DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."),
145 DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"), 145 DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"),
146 }, 146 },
147 .driver_data = (void *)&intel_chipset_data, 147 .driver_data = (void *)&intel_chipset_data,
@@ -184,6 +184,42 @@ static const struct dmi_system_id __initdata mbp_device_table[] = {
184 }, 184 },
185 { 185 {
186 .callback = mbp_dmi_match, 186 .callback = mbp_dmi_match,
187 .ident = "MacBookPro 1,1",
188 .matches = {
189 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
190 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro1,1"),
191 },
192 .driver_data = (void *)&intel_chipset_data,
193 },
194 {
195 .callback = mbp_dmi_match,
196 .ident = "MacBookPro 1,2",
197 .matches = {
198 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
199 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro1,2"),
200 },
201 .driver_data = (void *)&intel_chipset_data,
202 },
203 {
204 .callback = mbp_dmi_match,
205 .ident = "MacBookPro 2,1",
206 .matches = {
207 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
208 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro2,1"),
209 },
210 .driver_data = (void *)&intel_chipset_data,
211 },
212 {
213 .callback = mbp_dmi_match,
214 .ident = "MacBookPro 2,2",
215 .matches = {
216 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
217 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro2,2"),
218 },
219 .driver_data = (void *)&intel_chipset_data,
220 },
221 {
222 .callback = mbp_dmi_match,
187 .ident = "MacBookPro 3,1", 223 .ident = "MacBookPro 3,1",
188 .matches = { 224 .matches = {
189 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), 225 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
@@ -238,6 +274,15 @@ static const struct dmi_system_id __initdata mbp_device_table[] = {
238 }, 274 },
239 { 275 {
240 .callback = mbp_dmi_match, 276 .callback = mbp_dmi_match,
277 .ident = "MacBook 6,1",
278 .matches = {
279 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
280 DMI_MATCH(DMI_PRODUCT_NAME, "MacBook6,1"),
281 },
282 .driver_data = (void *)&nvidia_chipset_data,
283 },
284 {
285 .callback = mbp_dmi_match,
241 .ident = "MacBookAir 2,1", 286 .ident = "MacBookAir 2,1",
242 .matches = { 287 .matches = {
243 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), 288 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
diff --git a/drivers/video/backlight/pcf50633-backlight.c b/drivers/video/backlight/pcf50633-backlight.c
new file mode 100644
index 000000000000..3c424f7efdcc
--- /dev/null
+++ b/drivers/video/backlight/pcf50633-backlight.c
@@ -0,0 +1,190 @@
1/*
2 * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
3 * PCF50633 backlight device driver
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 *
10 * You should have received a copy of the GNU General Public License along
11 * with this program; if not, write to the Free Software Foundation, Inc.,
12 * 675 Mass Ave, Cambridge, MA 02139, USA.
13 *
14 */
15
16#include <linux/kernel.h>
17#include <linux/module.h>
18#include <linux/slab.h>
19#include <linux/platform_device.h>
20
21#include <linux/backlight.h>
22#include <linux/fb.h>
23
24#include <linux/mfd/pcf50633/core.h>
25#include <linux/mfd/pcf50633/backlight.h>
26
27struct pcf50633_bl {
28 struct pcf50633 *pcf;
29 struct backlight_device *bl;
30
31 unsigned int brightness;
32 unsigned int brightness_limit;
33};
34
35/*
36 * pcf50633_bl_set_brightness_limit
37 *
38 * Update the brightness limit for the pc50633 backlight. The actual brightness
39 * will not go above the limit. This is useful to limit power drain for example
40 * on low battery.
41 *
42 * @dev: Pointer to a pcf50633 device
43 * @limit: The brightness limit. Valid values are 0-63
44 */
45int pcf50633_bl_set_brightness_limit(struct pcf50633 *pcf, unsigned int limit)
46{
47 struct pcf50633_bl *pcf_bl = platform_get_drvdata(pcf->bl_pdev);
48
49 if (!pcf_bl)
50 return -ENODEV;
51
52 pcf_bl->brightness_limit = limit & 0x3f;
53 backlight_update_status(pcf_bl->bl);
54
55 return 0;
56}
57
58static int pcf50633_bl_update_status(struct backlight_device *bl)
59{
60 struct pcf50633_bl *pcf_bl = bl_get_data(bl);
61 unsigned int new_brightness;
62
63
64 if (bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK) ||
65 bl->props.power != FB_BLANK_UNBLANK)
66 new_brightness = 0;
67 else if (bl->props.brightness < pcf_bl->brightness_limit)
68 new_brightness = bl->props.brightness;
69 else
70 new_brightness = pcf_bl->brightness_limit;
71
72
73 if (pcf_bl->brightness == new_brightness)
74 return 0;
75
76 if (new_brightness) {
77 pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDOUT,
78 new_brightness);
79 if (!pcf_bl->brightness)
80 pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDENA, 1);
81 } else {
82 pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDENA, 0);
83 }
84
85 pcf_bl->brightness = new_brightness;
86
87 return 0;
88}
89
90static int pcf50633_bl_get_brightness(struct backlight_device *bl)
91{
92 struct pcf50633_bl *pcf_bl = bl_get_data(bl);
93 return pcf_bl->brightness;
94}
95
96static const struct backlight_ops pcf50633_bl_ops = {
97 .get_brightness = pcf50633_bl_get_brightness,
98 .update_status = pcf50633_bl_update_status,
99 .options = BL_CORE_SUSPENDRESUME,
100};
101
102static int __devinit pcf50633_bl_probe(struct platform_device *pdev)
103{
104 int ret;
105 struct pcf50633_bl *pcf_bl;
106 struct device *parent = pdev->dev.parent;
107 struct pcf50633_platform_data *pcf50633_data = parent->platform_data;
108 struct pcf50633_bl_platform_data *pdata = pcf50633_data->backlight_data;
109 struct backlight_properties bl_props;
110
111 pcf_bl = kzalloc(sizeof(*pcf_bl), GFP_KERNEL);
112 if (!pcf_bl)
113 return -ENOMEM;
114
115 bl_props.max_brightness = 0x3f;
116 bl_props.power = FB_BLANK_UNBLANK;
117
118 if (pdata) {
119 bl_props.brightness = pdata->default_brightness;
120 pcf_bl->brightness_limit = pdata->default_brightness_limit;
121 } else {
122 bl_props.brightness = 0x3f;
123 pcf_bl->brightness_limit = 0x3f;
124 }
125
126 pcf_bl->pcf = dev_to_pcf50633(pdev->dev.parent);
127
128 pcf_bl->bl = backlight_device_register(pdev->name, &pdev->dev, pcf_bl,
129 &pcf50633_bl_ops, &bl_props);
130
131 if (IS_ERR(pcf_bl->bl)) {
132 ret = PTR_ERR(pcf_bl->bl);
133 goto err_free;
134 }
135
136 platform_set_drvdata(pdev, pcf_bl);
137
138 pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDDIM, pdata->ramp_time);
139
140 /* Should be different from bl_props.brightness, so we do not exit
141 * update_status early the first time it's called */
142 pcf_bl->brightness = pcf_bl->bl->props.brightness + 1;
143
144 backlight_update_status(pcf_bl->bl);
145
146 return 0;
147
148err_free:
149 kfree(pcf_bl);
150
151 return ret;
152}
153
154static int __devexit pcf50633_bl_remove(struct platform_device *pdev)
155{
156 struct pcf50633_bl *pcf_bl = platform_get_drvdata(pdev);
157
158 backlight_device_unregister(pcf_bl->bl);
159
160 platform_set_drvdata(pdev, NULL);
161
162 kfree(pcf_bl);
163
164 return 0;
165}
166
167static struct platform_driver pcf50633_bl_driver = {
168 .probe = pcf50633_bl_probe,
169 .remove = __devexit_p(pcf50633_bl_remove),
170 .driver = {
171 .name = "pcf50633-backlight",
172 },
173};
174
175static int __init pcf50633_bl_init(void)
176{
177 return platform_driver_register(&pcf50633_bl_driver);
178}
179module_init(pcf50633_bl_init);
180
181static void __exit pcf50633_bl_exit(void)
182{
183 platform_driver_unregister(&pcf50633_bl_driver);
184}
185module_exit(pcf50633_bl_exit);
186
187MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
188MODULE_DESCRIPTION("PCF50633 backlight driver");
189MODULE_LICENSE("GPL");
190MODULE_ALIAS("platform:pcf50633-backlight");
diff --git a/drivers/video/backlight/s6e63m0.c b/drivers/video/backlight/s6e63m0.c
new file mode 100644
index 000000000000..a3128c9cb7ad
--- /dev/null
+++ b/drivers/video/backlight/s6e63m0.c
@@ -0,0 +1,920 @@
1/*
2 * S6E63M0 AMOLED LCD panel driver.
3 *
4 * Author: InKi Dae <inki.dae@samsung.com>
5 *
6 * Derived from drivers/video/omap/lcd-apollon.c
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 */
22
23#include <linux/wait.h>
24#include <linux/fb.h>
25#include <linux/delay.h>
26#include <linux/gpio.h>
27#include <linux/spi/spi.h>
28#include <linux/irq.h>
29#include <linux/interrupt.h>
30#include <linux/kernel.h>
31#include <linux/lcd.h>
32#include <linux/backlight.h>
33
34#include "s6e63m0_gamma.h"
35
36#define SLEEPMSEC 0x1000
37#define ENDDEF 0x2000
38#define DEFMASK 0xFF00
39#define COMMAND_ONLY 0xFE
40#define DATA_ONLY 0xFF
41
42#define MIN_BRIGHTNESS 0
43#define MAX_BRIGHTNESS 10
44
45#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL)
46
47struct s6e63m0 {
48 struct device *dev;
49 struct spi_device *spi;
50 unsigned int power;
51 unsigned int current_brightness;
52 unsigned int gamma_mode;
53 unsigned int gamma_table_count;
54 struct lcd_device *ld;
55 struct backlight_device *bd;
56 struct lcd_platform_data *lcd_pd;
57};
58
59static const unsigned short SEQ_PANEL_CONDITION_SET[] = {
60 0xF8, 0x01,
61 DATA_ONLY, 0x27,
62 DATA_ONLY, 0x27,
63 DATA_ONLY, 0x07,
64 DATA_ONLY, 0x07,
65 DATA_ONLY, 0x54,
66 DATA_ONLY, 0x9f,
67 DATA_ONLY, 0x63,
68 DATA_ONLY, 0x86,
69 DATA_ONLY, 0x1a,
70 DATA_ONLY, 0x33,
71 DATA_ONLY, 0x0d,
72 DATA_ONLY, 0x00,
73 DATA_ONLY, 0x00,
74
75 ENDDEF, 0x0000
76};
77
78static const unsigned short SEQ_DISPLAY_CONDITION_SET[] = {
79 0xf2, 0x02,
80 DATA_ONLY, 0x03,
81 DATA_ONLY, 0x1c,
82 DATA_ONLY, 0x10,
83 DATA_ONLY, 0x10,
84
85 0xf7, 0x03,
86 DATA_ONLY, 0x00,
87 DATA_ONLY, 0x00,
88
89 ENDDEF, 0x0000
90};
91
92static const unsigned short SEQ_GAMMA_SETTING[] = {
93 0xfa, 0x00,
94 DATA_ONLY, 0x18,
95 DATA_ONLY, 0x08,
96 DATA_ONLY, 0x24,
97 DATA_ONLY, 0x64,
98 DATA_ONLY, 0x56,
99 DATA_ONLY, 0x33,
100 DATA_ONLY, 0xb6,
101 DATA_ONLY, 0xba,
102 DATA_ONLY, 0xa8,
103 DATA_ONLY, 0xac,
104 DATA_ONLY, 0xb1,
105 DATA_ONLY, 0x9d,
106 DATA_ONLY, 0xc1,
107 DATA_ONLY, 0xc1,
108 DATA_ONLY, 0xb7,
109 DATA_ONLY, 0x00,
110 DATA_ONLY, 0x9c,
111 DATA_ONLY, 0x00,
112 DATA_ONLY, 0x9f,
113 DATA_ONLY, 0x00,
114 DATA_ONLY, 0xd6,
115
116 0xfa, 0x01,
117
118 ENDDEF, 0x0000
119};
120
121static const unsigned short SEQ_ETC_CONDITION_SET[] = {
122 0xf6, 0x00,
123 DATA_ONLY, 0x8c,
124 DATA_ONLY, 0x07,
125
126 0xb3, 0xc,
127
128 0xb5, 0x2c,
129 DATA_ONLY, 0x12,
130 DATA_ONLY, 0x0c,
131 DATA_ONLY, 0x0a,
132 DATA_ONLY, 0x10,
133 DATA_ONLY, 0x0e,
134 DATA_ONLY, 0x17,
135 DATA_ONLY, 0x13,
136 DATA_ONLY, 0x1f,
137 DATA_ONLY, 0x1a,
138 DATA_ONLY, 0x2a,
139 DATA_ONLY, 0x24,
140 DATA_ONLY, 0x1f,
141 DATA_ONLY, 0x1b,
142 DATA_ONLY, 0x1a,
143 DATA_ONLY, 0x17,
144
145 DATA_ONLY, 0x2b,
146 DATA_ONLY, 0x26,
147 DATA_ONLY, 0x22,
148 DATA_ONLY, 0x20,
149 DATA_ONLY, 0x3a,
150 DATA_ONLY, 0x34,
151 DATA_ONLY, 0x30,
152 DATA_ONLY, 0x2c,
153 DATA_ONLY, 0x29,
154 DATA_ONLY, 0x26,
155 DATA_ONLY, 0x25,
156 DATA_ONLY, 0x23,
157 DATA_ONLY, 0x21,
158 DATA_ONLY, 0x20,
159 DATA_ONLY, 0x1e,
160 DATA_ONLY, 0x1e,
161
162 0xb6, 0x00,
163 DATA_ONLY, 0x00,
164 DATA_ONLY, 0x11,
165 DATA_ONLY, 0x22,
166 DATA_ONLY, 0x33,
167 DATA_ONLY, 0x44,
168 DATA_ONLY, 0x44,
169 DATA_ONLY, 0x44,
170
171 DATA_ONLY, 0x55,
172 DATA_ONLY, 0x55,
173 DATA_ONLY, 0x66,
174 DATA_ONLY, 0x66,
175 DATA_ONLY, 0x66,
176 DATA_ONLY, 0x66,
177 DATA_ONLY, 0x66,
178 DATA_ONLY, 0x66,
179
180 0xb7, 0x2c,
181 DATA_ONLY, 0x12,
182 DATA_ONLY, 0x0c,
183 DATA_ONLY, 0x0a,
184 DATA_ONLY, 0x10,
185 DATA_ONLY, 0x0e,
186 DATA_ONLY, 0x17,
187 DATA_ONLY, 0x13,
188 DATA_ONLY, 0x1f,
189 DATA_ONLY, 0x1a,
190 DATA_ONLY, 0x2a,
191 DATA_ONLY, 0x24,
192 DATA_ONLY, 0x1f,
193 DATA_ONLY, 0x1b,
194 DATA_ONLY, 0x1a,
195 DATA_ONLY, 0x17,
196
197 DATA_ONLY, 0x2b,
198 DATA_ONLY, 0x26,
199 DATA_ONLY, 0x22,
200 DATA_ONLY, 0x20,
201 DATA_ONLY, 0x3a,
202 DATA_ONLY, 0x34,
203 DATA_ONLY, 0x30,
204 DATA_ONLY, 0x2c,
205 DATA_ONLY, 0x29,
206 DATA_ONLY, 0x26,
207 DATA_ONLY, 0x25,
208 DATA_ONLY, 0x23,
209 DATA_ONLY, 0x21,
210 DATA_ONLY, 0x20,
211 DATA_ONLY, 0x1e,
212 DATA_ONLY, 0x1e,
213
214 0xb8, 0x00,
215 DATA_ONLY, 0x00,
216 DATA_ONLY, 0x11,
217 DATA_ONLY, 0x22,
218 DATA_ONLY, 0x33,
219 DATA_ONLY, 0x44,
220 DATA_ONLY, 0x44,
221 DATA_ONLY, 0x44,
222
223 DATA_ONLY, 0x55,
224 DATA_ONLY, 0x55,
225 DATA_ONLY, 0x66,
226 DATA_ONLY, 0x66,
227 DATA_ONLY, 0x66,
228 DATA_ONLY, 0x66,
229 DATA_ONLY, 0x66,
230 DATA_ONLY, 0x66,
231
232 0xb9, 0x2c,
233 DATA_ONLY, 0x12,
234 DATA_ONLY, 0x0c,
235 DATA_ONLY, 0x0a,
236 DATA_ONLY, 0x10,
237 DATA_ONLY, 0x0e,
238 DATA_ONLY, 0x17,
239 DATA_ONLY, 0x13,
240 DATA_ONLY, 0x1f,
241 DATA_ONLY, 0x1a,
242 DATA_ONLY, 0x2a,
243 DATA_ONLY, 0x24,
244 DATA_ONLY, 0x1f,
245 DATA_ONLY, 0x1b,
246 DATA_ONLY, 0x1a,
247 DATA_ONLY, 0x17,
248
249 DATA_ONLY, 0x2b,
250 DATA_ONLY, 0x26,
251 DATA_ONLY, 0x22,
252 DATA_ONLY, 0x20,
253 DATA_ONLY, 0x3a,
254 DATA_ONLY, 0x34,
255 DATA_ONLY, 0x30,
256 DATA_ONLY, 0x2c,
257 DATA_ONLY, 0x29,
258 DATA_ONLY, 0x26,
259 DATA_ONLY, 0x25,
260 DATA_ONLY, 0x23,
261 DATA_ONLY, 0x21,
262 DATA_ONLY, 0x20,
263 DATA_ONLY, 0x1e,
264 DATA_ONLY, 0x1e,
265
266 0xba, 0x00,
267 DATA_ONLY, 0x00,
268 DATA_ONLY, 0x11,
269 DATA_ONLY, 0x22,
270 DATA_ONLY, 0x33,
271 DATA_ONLY, 0x44,
272 DATA_ONLY, 0x44,
273 DATA_ONLY, 0x44,
274
275 DATA_ONLY, 0x55,
276 DATA_ONLY, 0x55,
277 DATA_ONLY, 0x66,
278 DATA_ONLY, 0x66,
279 DATA_ONLY, 0x66,
280 DATA_ONLY, 0x66,
281 DATA_ONLY, 0x66,
282 DATA_ONLY, 0x66,
283
284 0xc1, 0x4d,
285 DATA_ONLY, 0x96,
286 DATA_ONLY, 0x1d,
287 DATA_ONLY, 0x00,
288 DATA_ONLY, 0x00,
289 DATA_ONLY, 0x01,
290 DATA_ONLY, 0xdf,
291 DATA_ONLY, 0x00,
292 DATA_ONLY, 0x00,
293 DATA_ONLY, 0x03,
294 DATA_ONLY, 0x1f,
295 DATA_ONLY, 0x00,
296 DATA_ONLY, 0x00,
297 DATA_ONLY, 0x00,
298 DATA_ONLY, 0x00,
299 DATA_ONLY, 0x00,
300 DATA_ONLY, 0x00,
301 DATA_ONLY, 0x00,
302 DATA_ONLY, 0x00,
303 DATA_ONLY, 0x03,
304 DATA_ONLY, 0x06,
305 DATA_ONLY, 0x09,
306 DATA_ONLY, 0x0d,
307 DATA_ONLY, 0x0f,
308 DATA_ONLY, 0x12,
309 DATA_ONLY, 0x15,
310 DATA_ONLY, 0x18,
311
312 0xb2, 0x10,
313 DATA_ONLY, 0x10,
314 DATA_ONLY, 0x0b,
315 DATA_ONLY, 0x05,
316
317 ENDDEF, 0x0000
318};
319
320static const unsigned short SEQ_ACL_ON[] = {
321 /* ACL on */
322 0xc0, 0x01,
323
324 ENDDEF, 0x0000
325};
326
327static const unsigned short SEQ_ACL_OFF[] = {
328 /* ACL off */
329 0xc0, 0x00,
330
331 ENDDEF, 0x0000
332};
333
334static const unsigned short SEQ_ELVSS_ON[] = {
335 /* ELVSS on */
336 0xb1, 0x0b,
337
338 ENDDEF, 0x0000
339};
340
341static const unsigned short SEQ_ELVSS_OFF[] = {
342 /* ELVSS off */
343 0xb1, 0x0a,
344
345 ENDDEF, 0x0000
346};
347
348static const unsigned short SEQ_STAND_BY_OFF[] = {
349 0x11, COMMAND_ONLY,
350
351 ENDDEF, 0x0000
352};
353
354static const unsigned short SEQ_STAND_BY_ON[] = {
355 0x10, COMMAND_ONLY,
356
357 ENDDEF, 0x0000
358};
359
360static const unsigned short SEQ_DISPLAY_ON[] = {
361 0x29, COMMAND_ONLY,
362
363 ENDDEF, 0x0000
364};
365
366
367static int s6e63m0_spi_write_byte(struct s6e63m0 *lcd, int addr, int data)
368{
369 u16 buf[1];
370 struct spi_message msg;
371
372 struct spi_transfer xfer = {
373 .len = 2,
374 .tx_buf = buf,
375 };
376
377 buf[0] = (addr << 8) | data;
378
379 spi_message_init(&msg);
380 spi_message_add_tail(&xfer, &msg);
381
382 return spi_sync(lcd->spi, &msg);
383}
384
385static int s6e63m0_spi_write(struct s6e63m0 *lcd, unsigned char address,
386 unsigned char command)
387{
388 int ret = 0;
389
390 if (address != DATA_ONLY)
391 ret = s6e63m0_spi_write_byte(lcd, 0x0, address);
392 if (command != COMMAND_ONLY)
393 ret = s6e63m0_spi_write_byte(lcd, 0x1, command);
394
395 return ret;
396}
397
398static int s6e63m0_panel_send_sequence(struct s6e63m0 *lcd,
399 const unsigned short *wbuf)
400{
401 int ret = 0, i = 0;
402
403 while ((wbuf[i] & DEFMASK) != ENDDEF) {
404 if ((wbuf[i] & DEFMASK) != SLEEPMSEC) {
405 ret = s6e63m0_spi_write(lcd, wbuf[i], wbuf[i+1]);
406 if (ret)
407 break;
408 } else
409 udelay(wbuf[i+1]*1000);
410 i += 2;
411 }
412
413 return ret;
414}
415
416static int _s6e63m0_gamma_ctl(struct s6e63m0 *lcd, const unsigned int *gamma)
417{
418 unsigned int i = 0;
419 int ret = 0;
420
421 /* disable gamma table updating. */
422 ret = s6e63m0_spi_write(lcd, 0xfa, 0x00);
423 if (ret) {
424 dev_err(lcd->dev, "failed to disable gamma table updating.\n");
425 goto gamma_err;
426 }
427
428 for (i = 0 ; i < GAMMA_TABLE_COUNT; i++) {
429 ret = s6e63m0_spi_write(lcd, DATA_ONLY, gamma[i]);
430 if (ret) {
431 dev_err(lcd->dev, "failed to set gamma table.\n");
432 goto gamma_err;
433 }
434 }
435
436 /* update gamma table. */
437 ret = s6e63m0_spi_write(lcd, 0xfa, 0x01);
438 if (ret)
439 dev_err(lcd->dev, "failed to update gamma table.\n");
440
441gamma_err:
442 return ret;
443}
444
445static int s6e63m0_gamma_ctl(struct s6e63m0 *lcd, int gamma)
446{
447 int ret = 0;
448
449 ret = _s6e63m0_gamma_ctl(lcd, gamma_table.gamma_22_table[gamma]);
450
451 return ret;
452}
453
454
455static int s6e63m0_ldi_init(struct s6e63m0 *lcd)
456{
457 int ret, i;
458 const unsigned short *init_seq[] = {
459 SEQ_PANEL_CONDITION_SET,
460 SEQ_DISPLAY_CONDITION_SET,
461 SEQ_GAMMA_SETTING,
462 SEQ_ETC_CONDITION_SET,
463 SEQ_ACL_ON,
464 SEQ_ELVSS_ON,
465 };
466
467 for (i = 0; i < ARRAY_SIZE(init_seq); i++) {
468 ret = s6e63m0_panel_send_sequence(lcd, init_seq[i]);
469 if (ret)
470 break;
471 }
472
473 return ret;
474}
475
476static int s6e63m0_ldi_enable(struct s6e63m0 *lcd)
477{
478 int ret = 0, i;
479 const unsigned short *enable_seq[] = {
480 SEQ_STAND_BY_OFF,
481 SEQ_DISPLAY_ON,
482 };
483
484 for (i = 0; i < ARRAY_SIZE(enable_seq); i++) {
485 ret = s6e63m0_panel_send_sequence(lcd, enable_seq[i]);
486 if (ret)
487 break;
488 }
489
490 return ret;
491}
492
493static int s6e63m0_ldi_disable(struct s6e63m0 *lcd)
494{
495 int ret;
496
497 ret = s6e63m0_panel_send_sequence(lcd, SEQ_STAND_BY_ON);
498
499 return ret;
500}
501
502static int s6e63m0_power_on(struct s6e63m0 *lcd)
503{
504 int ret = 0;
505 struct lcd_platform_data *pd = NULL;
506 struct backlight_device *bd = NULL;
507
508 pd = lcd->lcd_pd;
509 if (!pd) {
510 dev_err(lcd->dev, "platform data is NULL.\n");
511 return -EFAULT;
512 }
513
514 bd = lcd->bd;
515 if (!bd) {
516 dev_err(lcd->dev, "backlight device is NULL.\n");
517 return -EFAULT;
518 }
519
520 if (!pd->power_on) {
521 dev_err(lcd->dev, "power_on is NULL.\n");
522 return -EFAULT;
523 } else {
524 pd->power_on(lcd->ld, 1);
525 mdelay(pd->power_on_delay);
526 }
527
528 if (!pd->reset) {
529 dev_err(lcd->dev, "reset is NULL.\n");
530 return -EFAULT;
531 } else {
532 pd->reset(lcd->ld);
533 mdelay(pd->reset_delay);
534 }
535
536 ret = s6e63m0_ldi_init(lcd);
537 if (ret) {
538 dev_err(lcd->dev, "failed to initialize ldi.\n");
539 return ret;
540 }
541
542 ret = s6e63m0_ldi_enable(lcd);
543 if (ret) {
544 dev_err(lcd->dev, "failed to enable ldi.\n");
545 return ret;
546 }
547
548 /* set brightness to current value after power on or resume. */
549 ret = s6e63m0_gamma_ctl(lcd, bd->props.brightness);
550 if (ret) {
551 dev_err(lcd->dev, "lcd gamma setting failed.\n");
552 return ret;
553 }
554
555 return 0;
556}
557
558static int s6e63m0_power_off(struct s6e63m0 *lcd)
559{
560 int ret = 0;
561 struct lcd_platform_data *pd = NULL;
562
563 pd = lcd->lcd_pd;
564 if (!pd) {
565 dev_err(lcd->dev, "platform data is NULL.\n");
566 return -EFAULT;
567 }
568
569 ret = s6e63m0_ldi_disable(lcd);
570 if (ret) {
571 dev_err(lcd->dev, "lcd setting failed.\n");
572 return -EIO;
573 }
574
575 mdelay(pd->power_off_delay);
576
577 if (!pd->power_on) {
578 dev_err(lcd->dev, "power_on is NULL.\n");
579 return -EFAULT;
580 } else
581 pd->power_on(lcd->ld, 0);
582
583 return 0;
584}
585
586static int s6e63m0_power(struct s6e63m0 *lcd, int power)
587{
588 int ret = 0;
589
590 if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power))
591 ret = s6e63m0_power_on(lcd);
592 else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->power))
593 ret = s6e63m0_power_off(lcd);
594
595 if (!ret)
596 lcd->power = power;
597
598 return ret;
599}
600
601static int s6e63m0_set_power(struct lcd_device *ld, int power)
602{
603 struct s6e63m0 *lcd = lcd_get_data(ld);
604
605 if (power != FB_BLANK_UNBLANK && power != FB_BLANK_POWERDOWN &&
606 power != FB_BLANK_NORMAL) {
607 dev_err(lcd->dev, "power value should be 0, 1 or 4.\n");
608 return -EINVAL;
609 }
610
611 return s6e63m0_power(lcd, power);
612}
613
614static int s6e63m0_get_power(struct lcd_device *ld)
615{
616 struct s6e63m0 *lcd = lcd_get_data(ld);
617
618 return lcd->power;
619}
620
621static int s6e63m0_get_brightness(struct backlight_device *bd)
622{
623 return bd->props.brightness;
624}
625
626static int s6e63m0_set_brightness(struct backlight_device *bd)
627{
628 int ret = 0, brightness = bd->props.brightness;
629 struct s6e63m0 *lcd = bl_get_data(bd);
630
631 if (brightness < MIN_BRIGHTNESS ||
632 brightness > bd->props.max_brightness) {
633 dev_err(&bd->dev, "lcd brightness should be %d to %d.\n",
634 MIN_BRIGHTNESS, MAX_BRIGHTNESS);
635 return -EINVAL;
636 }
637
638 ret = s6e63m0_gamma_ctl(lcd, bd->props.brightness);
639 if (ret) {
640 dev_err(&bd->dev, "lcd brightness setting failed.\n");
641 return -EIO;
642 }
643
644 return ret;
645}
646
647static struct lcd_ops s6e63m0_lcd_ops = {
648 .set_power = s6e63m0_set_power,
649 .get_power = s6e63m0_get_power,
650};
651
652static const struct backlight_ops s6e63m0_backlight_ops = {
653 .get_brightness = s6e63m0_get_brightness,
654 .update_status = s6e63m0_set_brightness,
655};
656
657static ssize_t s6e63m0_sysfs_show_gamma_mode(struct device *dev,
658 struct device_attribute *attr, char *buf)
659{
660 struct s6e63m0 *lcd = dev_get_drvdata(dev);
661 char temp[10];
662
663 switch (lcd->gamma_mode) {
664 case 0:
665 sprintf(temp, "2.2 mode\n");
666 strcat(buf, temp);
667 break;
668 case 1:
669 sprintf(temp, "1.9 mode\n");
670 strcat(buf, temp);
671 break;
672 case 2:
673 sprintf(temp, "1.7 mode\n");
674 strcat(buf, temp);
675 break;
676 default:
677 dev_info(dev, "gamma mode could be 0:2.2, 1:1.9 or 2:1.7)n");
678 break;
679 }
680
681 return strlen(buf);
682}
683
684static ssize_t s6e63m0_sysfs_store_gamma_mode(struct device *dev,
685 struct device_attribute *attr,
686 const char *buf, size_t len)
687{
688 struct s6e63m0 *lcd = dev_get_drvdata(dev);
689 struct backlight_device *bd = NULL;
690 int brightness, rc;
691
692 rc = strict_strtoul(buf, 0, (unsigned long *)&lcd->gamma_mode);
693 if (rc < 0)
694 return rc;
695
696 bd = lcd->bd;
697
698 brightness = bd->props.brightness;
699
700 switch (lcd->gamma_mode) {
701 case 0:
702 _s6e63m0_gamma_ctl(lcd, gamma_table.gamma_22_table[brightness]);
703 break;
704 case 1:
705 _s6e63m0_gamma_ctl(lcd, gamma_table.gamma_19_table[brightness]);
706 break;
707 case 2:
708 _s6e63m0_gamma_ctl(lcd, gamma_table.gamma_17_table[brightness]);
709 break;
710 default:
711 dev_info(dev, "gamma mode could be 0:2.2, 1:1.9 or 2:1.7\n");
712 _s6e63m0_gamma_ctl(lcd, gamma_table.gamma_22_table[brightness]);
713 break;
714 }
715 return len;
716}
717
718static DEVICE_ATTR(gamma_mode, 0644,
719 s6e63m0_sysfs_show_gamma_mode, s6e63m0_sysfs_store_gamma_mode);
720
721static ssize_t s6e63m0_sysfs_show_gamma_table(struct device *dev,
722 struct device_attribute *attr, char *buf)
723{
724 struct s6e63m0 *lcd = dev_get_drvdata(dev);
725 char temp[3];
726
727 sprintf(temp, "%d\n", lcd->gamma_table_count);
728 strcpy(buf, temp);
729
730 return strlen(buf);
731}
732static DEVICE_ATTR(gamma_table, 0644,
733 s6e63m0_sysfs_show_gamma_table, NULL);
734
735static int __init s6e63m0_probe(struct spi_device *spi)
736{
737 int ret = 0;
738 struct s6e63m0 *lcd = NULL;
739 struct lcd_device *ld = NULL;
740 struct backlight_device *bd = NULL;
741
742 lcd = kzalloc(sizeof(struct s6e63m0), GFP_KERNEL);
743 if (!lcd)
744 return -ENOMEM;
745
746 /* s6e63m0 lcd panel uses 3-wire 9bits SPI Mode. */
747 spi->bits_per_word = 9;
748
749 ret = spi_setup(spi);
750 if (ret < 0) {
751 dev_err(&spi->dev, "spi setup failed.\n");
752 goto out_free_lcd;
753 }
754
755 lcd->spi = spi;
756 lcd->dev = &spi->dev;
757
758 lcd->lcd_pd = (struct lcd_platform_data *)spi->dev.platform_data;
759 if (!lcd->lcd_pd) {
760 dev_err(&spi->dev, "platform data is NULL.\n");
761 goto out_free_lcd;
762 }
763
764 ld = lcd_device_register("s6e63m0", &spi->dev, lcd, &s6e63m0_lcd_ops);
765 if (IS_ERR(ld)) {
766 ret = PTR_ERR(ld);
767 goto out_free_lcd;
768 }
769
770 lcd->ld = ld;
771
772 bd = backlight_device_register("s6e63m0bl-bl", &spi->dev, lcd,
773 &s6e63m0_backlight_ops, NULL);
774 if (IS_ERR(bd)) {
775 ret = PTR_ERR(bd);
776 goto out_lcd_unregister;
777 }
778
779 bd->props.max_brightness = MAX_BRIGHTNESS;
780 bd->props.brightness = MAX_BRIGHTNESS;
781 lcd->bd = bd;
782
783 /*
784 * it gets gamma table count available so it gets user
785 * know that.
786 */
787 lcd->gamma_table_count =
788 sizeof(gamma_table) / (MAX_GAMMA_LEVEL * sizeof(int));
789
790 ret = device_create_file(&(spi->dev), &dev_attr_gamma_mode);
791 if (ret < 0)
792 dev_err(&(spi->dev), "failed to add sysfs entries\n");
793
794 ret = device_create_file(&(spi->dev), &dev_attr_gamma_table);
795 if (ret < 0)
796 dev_err(&(spi->dev), "failed to add sysfs entries\n");
797
798 /*
799 * if lcd panel was on from bootloader like u-boot then
800 * do not lcd on.
801 */
802 if (!lcd->lcd_pd->lcd_enabled) {
803 /*
804 * if lcd panel was off from bootloader then
805 * current lcd status is powerdown and then
806 * it enables lcd panel.
807 */
808 lcd->power = FB_BLANK_POWERDOWN;
809
810 s6e63m0_power(lcd, FB_BLANK_UNBLANK);
811 } else
812 lcd->power = FB_BLANK_UNBLANK;
813
814 dev_set_drvdata(&spi->dev, lcd);
815
816 dev_info(&spi->dev, "s6e63m0 panel driver has been probed.\n");
817
818 return 0;
819
820out_lcd_unregister:
821 lcd_device_unregister(ld);
822out_free_lcd:
823 kfree(lcd);
824 return ret;
825}
826
827static int __devexit s6e63m0_remove(struct spi_device *spi)
828{
829 struct s6e63m0 *lcd = dev_get_drvdata(&spi->dev);
830
831 s6e63m0_power(lcd, FB_BLANK_POWERDOWN);
832 lcd_device_unregister(lcd->ld);
833 kfree(lcd);
834
835 return 0;
836}
837
838#if defined(CONFIG_PM)
839unsigned int before_power;
840
841static int s6e63m0_suspend(struct spi_device *spi, pm_message_t mesg)
842{
843 int ret = 0;
844 struct s6e63m0 *lcd = dev_get_drvdata(&spi->dev);
845
846 dev_dbg(&spi->dev, "lcd->power = %d\n", lcd->power);
847
848 before_power = lcd->power;
849
850 /*
851 * when lcd panel is suspend, lcd panel becomes off
852 * regardless of status.
853 */
854 ret = s6e63m0_power(lcd, FB_BLANK_POWERDOWN);
855
856 return ret;
857}
858
859static int s6e63m0_resume(struct spi_device *spi)
860{
861 int ret = 0;
862 struct s6e63m0 *lcd = dev_get_drvdata(&spi->dev);
863
864 /*
865 * after suspended, if lcd panel status is FB_BLANK_UNBLANK
866 * (at that time, before_power is FB_BLANK_UNBLANK) then
867 * it changes that status to FB_BLANK_POWERDOWN to get lcd on.
868 */
869 if (before_power == FB_BLANK_UNBLANK)
870 lcd->power = FB_BLANK_POWERDOWN;
871
872 dev_dbg(&spi->dev, "before_power = %d\n", before_power);
873
874 ret = s6e63m0_power(lcd, before_power);
875
876 return ret;
877}
878#else
879#define s6e63m0_suspend NULL
880#define s6e63m0_resume NULL
881#endif
882
883/* Power down all displays on reboot, poweroff or halt. */
884static void s6e63m0_shutdown(struct spi_device *spi)
885{
886 struct s6e63m0 *lcd = dev_get_drvdata(&spi->dev);
887
888 s6e63m0_power(lcd, FB_BLANK_POWERDOWN);
889}
890
891static struct spi_driver s6e63m0_driver = {
892 .driver = {
893 .name = "s6e63m0",
894 .bus = &spi_bus_type,
895 .owner = THIS_MODULE,
896 },
897 .probe = s6e63m0_probe,
898 .remove = __devexit_p(s6e63m0_remove),
899 .shutdown = s6e63m0_shutdown,
900 .suspend = s6e63m0_suspend,
901 .resume = s6e63m0_resume,
902};
903
904static int __init s6e63m0_init(void)
905{
906 return spi_register_driver(&s6e63m0_driver);
907}
908
909static void __exit s6e63m0_exit(void)
910{
911 spi_unregister_driver(&s6e63m0_driver);
912}
913
914module_init(s6e63m0_init);
915module_exit(s6e63m0_exit);
916
917MODULE_AUTHOR("InKi Dae <inki.dae@samsung.com>");
918MODULE_DESCRIPTION("S6E63M0 LCD Driver");
919MODULE_LICENSE("GPL");
920
diff --git a/drivers/video/backlight/s6e63m0_gamma.h b/drivers/video/backlight/s6e63m0_gamma.h
new file mode 100644
index 000000000000..2c44bdb0696b
--- /dev/null
+++ b/drivers/video/backlight/s6e63m0_gamma.h
@@ -0,0 +1,266 @@
1/* linux/drivers/video/samsung/s6e63m0_brightness.h
2 *
3 * Gamma level definitions.
4 *
5 * Copyright (c) 2009 Samsung Electronics
6 * InKi Dae <inki.dae@samsung.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#ifndef _S6E63M0_BRIGHTNESS_H
14#define _S6E63M0_BRIGHTNESS_H
15
16#define MAX_GAMMA_LEVEL 11
17#define GAMMA_TABLE_COUNT 21
18
19/* gamma value: 2.2 */
20static const unsigned int s6e63m0_22_300[] = {
21 0x18, 0x08, 0x24, 0x5f, 0x50, 0x2d, 0xB6,
22 0xB9, 0xA7, 0xAd, 0xB1, 0x9f, 0xbe, 0xC0,
23 0xB5, 0x00, 0xa0, 0x00, 0xa4, 0x00, 0xdb
24};
25
26static const unsigned int s6e63m0_22_280[] = {
27 0x18, 0x08, 0x24, 0x64, 0x56, 0x33, 0xB6,
28 0xBA, 0xA8, 0xAC, 0xB1, 0x9D, 0xC1, 0xC1,
29 0xB7, 0x00, 0x9C, 0x00, 0x9F, 0x00, 0xD6
30};
31
32static const unsigned int s6e63m0_22_260[] = {
33 0x18, 0x08, 0x24, 0x66, 0x58, 0x34, 0xB6,
34 0xBA, 0xA7, 0xAF, 0xB3, 0xA0, 0xC1, 0xC2,
35 0xB7, 0x00, 0x97, 0x00, 0x9A, 0x00, 0xD1
36
37};
38
39static const unsigned int s6e63m0_22_240[] = {
40 0x18, 0x08, 0x24, 0x62, 0x54, 0x30, 0xB9,
41 0xBB, 0xA9, 0xB0, 0xB3, 0xA1, 0xC1, 0xC3,
42 0xB7, 0x00, 0x91, 0x00, 0x95, 0x00, 0xDA
43
44};
45static const unsigned int s6e63m0_22_220[] = {
46 0x18, 0x08, 0x24, 0x63, 0x53, 0x31, 0xB8,
47 0xBC, 0xA9, 0xB0, 0xB5, 0xA2, 0xC4, 0xC4,
48 0xB8, 0x00, 0x8B, 0x00, 0x8E, 0x00, 0xC2
49};
50
51static const unsigned int s6e63m0_22_200[] = {
52 0x18, 0x08, 0x24, 0x66, 0x55, 0x34, 0xBA,
53 0xBD, 0xAB, 0xB1, 0xB5, 0xA3, 0xC5, 0xC6,
54 0xB9, 0x00, 0x85, 0x00, 0x88, 0x00, 0xBA
55};
56
57static const unsigned int s6e63m0_22_170[] = {
58 0x18, 0x08, 0x24, 0x69, 0x54, 0x37, 0xBB,
59 0xBE, 0xAC, 0xB4, 0xB7, 0xA6, 0xC7, 0xC8,
60 0xBC, 0x00, 0x7B, 0x00, 0x7E, 0x00, 0xAB
61};
62
63static const unsigned int s6e63m0_22_140[] = {
64 0x18, 0x08, 0x24, 0x6C, 0x54, 0x3A, 0xBC,
65 0xBF, 0xAC, 0xB7, 0xBB, 0xA9, 0xC9, 0xC9,
66 0xBE, 0x00, 0x71, 0x00, 0x73, 0x00, 0x9E
67};
68
69static const unsigned int s6e63m0_22_110[] = {
70 0x18, 0x08, 0x24, 0x70, 0x51, 0x3E, 0xBF,
71 0xC1, 0xAF, 0xB9, 0xBC, 0xAB, 0xCC, 0xCC,
72 0xC2, 0x00, 0x65, 0x00, 0x67, 0x00, 0x8D
73};
74
75static const unsigned int s6e63m0_22_90[] = {
76 0x18, 0x08, 0x24, 0x73, 0x4A, 0x3D, 0xC0,
77 0xC2, 0xB1, 0xBB, 0xBE, 0xAC, 0xCE, 0xCF,
78 0xC5, 0x00, 0x5D, 0x00, 0x5E, 0x00, 0x82
79};
80
81static const unsigned int s6e63m0_22_30[] = {
82 0x18, 0x08, 0x24, 0x78, 0xEC, 0x3D, 0xC8,
83 0xC2, 0xB6, 0xC4, 0xC7, 0xB6, 0xD5, 0xD7,
84 0xCC, 0x00, 0x39, 0x00, 0x36, 0x00, 0x51
85};
86
87/* gamma value: 1.9 */
88static const unsigned int s6e63m0_19_300[] = {
89 0x18, 0x08, 0x24, 0x61, 0x5F, 0x39, 0xBA,
90 0xBD, 0xAD, 0xB1, 0xB6, 0xA5, 0xC4, 0xC5,
91 0xBC, 0x00, 0xA0, 0x00, 0xA4, 0x00, 0xDB
92};
93
94static const unsigned int s6e63m0_19_280[] = {
95 0x18, 0x08, 0x24, 0x61, 0x60, 0x39, 0xBB,
96 0xBE, 0xAD, 0xB2, 0xB6, 0xA6, 0xC5, 0xC7,
97 0xBD, 0x00, 0x9B, 0x00, 0x9E, 0x00, 0xD5
98};
99
100static const unsigned int s6e63m0_19_260[] = {
101 0x18, 0x08, 0x24, 0x63, 0x61, 0x3B, 0xBA,
102 0xBE, 0xAC, 0xB3, 0xB8, 0xA7, 0xC6, 0xC8,
103 0xBD, 0x00, 0x96, 0x00, 0x98, 0x00, 0xCF
104};
105
106static const unsigned int s6e63m0_19_240[] = {
107 0x18, 0x08, 0x24, 0x67, 0x64, 0x3F, 0xBB,
108 0xBE, 0xAD, 0xB3, 0xB9, 0xA7, 0xC8, 0xC9,
109 0xBE, 0x00, 0x90, 0x00, 0x92, 0x00, 0xC8
110};
111
112static const unsigned int s6e63m0_19_220[] = {
113 0x18, 0x08, 0x24, 0x68, 0x64, 0x40, 0xBC,
114 0xBF, 0xAF, 0xB4, 0xBA, 0xA9, 0xC8, 0xCA,
115 0xBE, 0x00, 0x8B, 0x00, 0x8C, 0x00, 0xC0
116};
117
118static const unsigned int s6e63m0_19_200[] = {
119 0x18, 0x08, 0x24, 0x68, 0x64, 0x3F, 0xBE,
120 0xC0, 0xB0, 0xB6, 0xBB, 0xAB, 0xC8, 0xCB,
121 0xBF, 0x00, 0x85, 0x00, 0x86, 0x00, 0xB8
122};
123
124static const unsigned int s6e63m0_19_170[] = {
125 0x18, 0x08, 0x24, 0x69, 0x64, 0x40, 0xBF,
126 0xC1, 0xB0, 0xB9, 0xBE, 0xAD, 0xCB, 0xCD,
127 0xC2, 0x00, 0x7A, 0x00, 0x7B, 0x00, 0xAA
128};
129
130static const unsigned int s6e63m0_19_140[] = {
131 0x18, 0x08, 0x24, 0x6E, 0x65, 0x45, 0xC0,
132 0xC3, 0xB2, 0xBA, 0xBE, 0xAE, 0xCD, 0xD0,
133 0xC4, 0x00, 0x70, 0x00, 0x70, 0x00, 0x9C
134};
135
136static const unsigned int s6e63m0_19_110[] = {
137 0x18, 0x08, 0x24, 0x6F, 0x65, 0x46, 0xC2,
138 0xC4, 0xB3, 0xBF, 0xC2, 0xB2, 0xCF, 0xD1,
139 0xC6, 0x00, 0x64, 0x00, 0x64, 0x00, 0x8D
140};
141
142static const unsigned int s6e63m0_19_90[] = {
143 0x18, 0x08, 0x24, 0x74, 0x60, 0x4A, 0xC3,
144 0xC6, 0xB5, 0xBF, 0xC3, 0xB2, 0xD2, 0xD3,
145 0xC8, 0x00, 0x5B, 0x00, 0x5B, 0x00, 0x81
146};
147
148static const unsigned int s6e63m0_19_30[] = {
149 0x18, 0x08, 0x24, 0x84, 0x45, 0x4F, 0xCA,
150 0xCB, 0xBC, 0xC9, 0xCB, 0xBC, 0xDA, 0xDA,
151 0xD0, 0x00, 0x35, 0x00, 0x34, 0x00, 0x4E
152};
153
154/* gamma value: 1.7 */
155static const unsigned int s6e63m0_17_300[] = {
156 0x18, 0x08, 0x24, 0x70, 0x70, 0x4F, 0xBF,
157 0xC2, 0xB2, 0xB8, 0xBC, 0xAC, 0xCB, 0xCD,
158 0xC3, 0x00, 0xA0, 0x00, 0xA4, 0x00, 0xDB
159};
160
161static const unsigned int s6e63m0_17_280[] = {
162 0x18, 0x08, 0x24, 0x71, 0x71, 0x50, 0xBF,
163 0xC2, 0xB2, 0xBA, 0xBE, 0xAE, 0xCB, 0xCD,
164 0xC3, 0x00, 0x9C, 0x00, 0x9F, 0x00, 0xD6
165};
166
167static const unsigned int s6e63m0_17_260[] = {
168 0x18, 0x08, 0x24, 0x72, 0x72, 0x50, 0xC0,
169 0xC3, 0xB4, 0xB9, 0xBE, 0xAE, 0xCC, 0xCF,
170 0xC4, 0x00, 0x97, 0x00, 0x9A, 0x00, 0xD1
171};
172
173static const unsigned int s6e63m0_17_240[] = {
174 0x18, 0x08, 0x24, 0x71, 0x72, 0x4F, 0xC2,
175 0xC4, 0xB5, 0xBB, 0xBF, 0xB0, 0xCC, 0xCF,
176 0xC3, 0x00, 0x91, 0x00, 0x95, 0x00, 0xCA
177};
178
179static const unsigned int s6e63m0_17_220[] = {
180 0x18, 0x08, 0x24, 0x71, 0x73, 0x4F, 0xC2,
181 0xC5, 0xB5, 0xBD, 0xC0, 0xB2, 0xCD, 0xD1,
182 0xC5, 0x00, 0x8B, 0x00, 0x8E, 0x00, 0xC2
183};
184
185static const unsigned int s6e63m0_17_200[] = {
186 0x18, 0x08, 0x24, 0x72, 0x75, 0x51, 0xC2,
187 0xC6, 0xB5, 0xBF, 0xC1, 0xB3, 0xCE, 0xD1,
188 0xC6, 0x00, 0x85, 0x00, 0x88, 0x00, 0xBA
189};
190
191static const unsigned int s6e63m0_17_170[] = {
192 0x18, 0x08, 0x24, 0x75, 0x77, 0x54, 0xC3,
193 0xC7, 0xB7, 0xC0, 0xC3, 0xB4, 0xD1, 0xD3,
194 0xC9, 0x00, 0x7B, 0x00, 0x7E, 0x00, 0xAB
195};
196
197static const unsigned int s6e63m0_17_140[] = {
198 0x18, 0x08, 0x24, 0x7B, 0x77, 0x58, 0xC3,
199 0xC8, 0xB8, 0xC2, 0xC6, 0xB6, 0xD3, 0xD4,
200 0xCA, 0x00, 0x71, 0x00, 0x73, 0x00, 0x9E
201};
202
203static const unsigned int s6e63m0_17_110[] = {
204 0x18, 0x08, 0x24, 0x81, 0x7B, 0x5D, 0xC6,
205 0xCA, 0xBB, 0xC3, 0xC7, 0xB8, 0xD6, 0xD8,
206 0xCD, 0x00, 0x65, 0x00, 0x67, 0x00, 0x8D
207};
208
209static const unsigned int s6e63m0_17_90[] = {
210 0x18, 0x08, 0x24, 0x82, 0x7A, 0x5B, 0xC8,
211 0xCB, 0xBD, 0xC5, 0xCA, 0xBA, 0xD6, 0xD8,
212 0xCE, 0x00, 0x5D, 0x00, 0x5E, 0x00, 0x82
213};
214
215static const unsigned int s6e63m0_17_30[] = {
216 0x18, 0x08, 0x24, 0x8F, 0x73, 0x63, 0xD1,
217 0xD0, 0xC5, 0xCC, 0xD1, 0xC2, 0xDE, 0xE0,
218 0xD6, 0x00, 0x39, 0x00, 0x36, 0x00, 0x51
219};
220
221struct s6e63m0_gamma {
222 unsigned int *gamma_22_table[MAX_GAMMA_LEVEL];
223 unsigned int *gamma_19_table[MAX_GAMMA_LEVEL];
224 unsigned int *gamma_17_table[MAX_GAMMA_LEVEL];
225};
226
227static struct s6e63m0_gamma gamma_table = {
228 .gamma_22_table[0] = (unsigned int *)&s6e63m0_22_30,
229 .gamma_22_table[1] = (unsigned int *)&s6e63m0_22_90,
230 .gamma_22_table[2] = (unsigned int *)&s6e63m0_22_110,
231 .gamma_22_table[3] = (unsigned int *)&s6e63m0_22_140,
232 .gamma_22_table[4] = (unsigned int *)&s6e63m0_22_170,
233 .gamma_22_table[5] = (unsigned int *)&s6e63m0_22_200,
234 .gamma_22_table[6] = (unsigned int *)&s6e63m0_22_220,
235 .gamma_22_table[7] = (unsigned int *)&s6e63m0_22_240,
236 .gamma_22_table[8] = (unsigned int *)&s6e63m0_22_260,
237 .gamma_22_table[9] = (unsigned int *)&s6e63m0_22_280,
238 .gamma_22_table[10] = (unsigned int *)&s6e63m0_22_300,
239
240 .gamma_19_table[0] = (unsigned int *)&s6e63m0_19_30,
241 .gamma_19_table[1] = (unsigned int *)&s6e63m0_19_90,
242 .gamma_19_table[2] = (unsigned int *)&s6e63m0_19_110,
243 .gamma_19_table[3] = (unsigned int *)&s6e63m0_19_140,
244 .gamma_19_table[4] = (unsigned int *)&s6e63m0_19_170,
245 .gamma_19_table[5] = (unsigned int *)&s6e63m0_19_200,
246 .gamma_19_table[6] = (unsigned int *)&s6e63m0_19_220,
247 .gamma_19_table[7] = (unsigned int *)&s6e63m0_19_240,
248 .gamma_19_table[8] = (unsigned int *)&s6e63m0_19_260,
249 .gamma_19_table[9] = (unsigned int *)&s6e63m0_19_280,
250 .gamma_19_table[10] = (unsigned int *)&s6e63m0_19_300,
251
252 .gamma_17_table[0] = (unsigned int *)&s6e63m0_17_30,
253 .gamma_17_table[1] = (unsigned int *)&s6e63m0_17_90,
254 .gamma_17_table[2] = (unsigned int *)&s6e63m0_17_110,
255 .gamma_17_table[3] = (unsigned int *)&s6e63m0_17_140,
256 .gamma_17_table[4] = (unsigned int *)&s6e63m0_17_170,
257 .gamma_17_table[5] = (unsigned int *)&s6e63m0_17_200,
258 .gamma_17_table[6] = (unsigned int *)&s6e63m0_17_220,
259 .gamma_17_table[7] = (unsigned int *)&s6e63m0_17_240,
260 .gamma_17_table[8] = (unsigned int *)&s6e63m0_17_260,
261 .gamma_17_table[9] = (unsigned int *)&s6e63m0_17_280,
262 .gamma_17_table[10] = (unsigned int *)&s6e63m0_17_300,
263};
264
265#endif
266
diff --git a/drivers/video/backlight/tosa_bl.c b/drivers/video/backlight/tosa_bl.c
index e03e60bbfd85..2a04b382ec48 100644
--- a/drivers/video/backlight/tosa_bl.c
+++ b/drivers/video/backlight/tosa_bl.c
@@ -119,7 +119,6 @@ static int __devinit tosa_bl_probe(struct i2c_client *client,
119 119
120err_reg: 120err_reg:
121 data->bl = NULL; 121 data->bl = NULL;
122 i2c_set_clientdata(client, NULL);
123err_gpio_dir: 122err_gpio_dir:
124 gpio_free(TOSA_GPIO_BL_C20MA); 123 gpio_free(TOSA_GPIO_BL_C20MA);
125err_gpio_bl: 124err_gpio_bl:
@@ -133,7 +132,6 @@ static int __devexit tosa_bl_remove(struct i2c_client *client)
133 132
134 backlight_device_unregister(data->bl); 133 backlight_device_unregister(data->bl);
135 data->bl = NULL; 134 data->bl = NULL;
136 i2c_set_clientdata(client, NULL);
137 135
138 gpio_free(TOSA_GPIO_BL_C20MA); 136 gpio_free(TOSA_GPIO_BL_C20MA);
139 137
diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c
index 23b2a8c0dbfc..b020ba7f1cf2 100644
--- a/drivers/video/bf54x-lq043fb.c
+++ b/drivers/video/bf54x-lq043fb.c
@@ -501,7 +501,9 @@ static irqreturn_t bfin_bf54x_irq_error(int irq, void *dev_id)
501 501
502static int __devinit bfin_bf54x_probe(struct platform_device *pdev) 502static int __devinit bfin_bf54x_probe(struct platform_device *pdev)
503{ 503{
504#ifndef NO_BL_SUPPORT
504 struct backlight_properties props; 505 struct backlight_properties props;
506#endif
505 struct bfin_bf54xfb_info *info; 507 struct bfin_bf54xfb_info *info;
506 struct fb_info *fbinfo; 508 struct fb_info *fbinfo;
507 int ret; 509 int ret;
@@ -654,7 +656,8 @@ static int __devinit bfin_bf54x_probe(struct platform_device *pdev)
654 printk(KERN_ERR DRIVER_NAME 656 printk(KERN_ERR DRIVER_NAME
655 ": unable to register backlight.\n"); 657 ": unable to register backlight.\n");
656 ret = -EINVAL; 658 ret = -EINVAL;
657 goto out9; 659 unregister_framebuffer(fbinfo);
660 goto out8;
658 } 661 }
659 662
660 lcd_dev = lcd_device_register(DRIVER_NAME, &pdev->dev, NULL, &bfin_lcd_ops); 663 lcd_dev = lcd_device_register(DRIVER_NAME, &pdev->dev, NULL, &bfin_lcd_ops);
@@ -663,8 +666,6 @@ static int __devinit bfin_bf54x_probe(struct platform_device *pdev)
663 666
664 return 0; 667 return 0;
665 668
666out9:
667 unregister_framebuffer(fbinfo);
668out8: 669out8:
669 free_irq(info->irq, info); 670 free_irq(info->irq, info);
670out7: 671out7:
diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c
index c2ec3dcd4e91..7a50272eaab9 100644
--- a/drivers/video/bfin-t350mcqb-fb.c
+++ b/drivers/video/bfin-t350mcqb-fb.c
@@ -420,7 +420,9 @@ static irqreturn_t bfin_t350mcqb_irq_error(int irq, void *dev_id)
420 420
421static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev) 421static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev)
422{ 422{
423#ifndef NO_BL_SUPPORT
423 struct backlight_properties props; 424 struct backlight_properties props;
425#endif
424 struct bfin_t350mcqbfb_info *info; 426 struct bfin_t350mcqbfb_info *info;
425 struct fb_info *fbinfo; 427 struct fb_info *fbinfo;
426 int ret; 428 int ret;
@@ -550,7 +552,8 @@ static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev)
550 printk(KERN_ERR DRIVER_NAME 552 printk(KERN_ERR DRIVER_NAME
551 ": unable to register backlight.\n"); 553 ": unable to register backlight.\n");
552 ret = -EINVAL; 554 ret = -EINVAL;
553 goto out9; 555 unregister_framebuffer(fbinfo);
556 goto out8;
554 } 557 }
555 558
556 lcd_dev = lcd_device_register(DRIVER_NAME, NULL, &bfin_lcd_ops); 559 lcd_dev = lcd_device_register(DRIVER_NAME, NULL, &bfin_lcd_ops);
@@ -559,8 +562,6 @@ static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev)
559 562
560 return 0; 563 return 0;
561 564
562out9:
563 unregister_framebuffer(fbinfo);
564out8: 565out8:
565 free_irq(info->irq, info); 566 free_irq(info->irq, info);
566out7: 567out7:
diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c
index 2c371c07f0da..09f1b9b462f4 100644
--- a/drivers/video/bw2.c
+++ b/drivers/video/bw2.c
@@ -275,7 +275,7 @@ static int __devinit bw2_do_default_mode(struct bw2_par *par,
275 275
276static int __devinit bw2_probe(struct of_device *op, const struct of_device_id *match) 276static int __devinit bw2_probe(struct of_device *op, const struct of_device_id *match)
277{ 277{
278 struct device_node *dp = op->node; 278 struct device_node *dp = op->dev.of_node;
279 struct fb_info *info; 279 struct fb_info *info;
280 struct bw2_par *par; 280 struct bw2_par *par;
281 int linebytes, err; 281 int linebytes, err;
diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c
index d12e05b6e63f..e5dc2241194f 100644
--- a/drivers/video/cg14.c
+++ b/drivers/video/cg14.c
@@ -465,7 +465,7 @@ static void cg14_unmap_regs(struct of_device *op, struct fb_info *info,
465 465
466static int __devinit cg14_probe(struct of_device *op, const struct of_device_id *match) 466static int __devinit cg14_probe(struct of_device *op, const struct of_device_id *match)
467{ 467{
468 struct device_node *dp = op->node; 468 struct device_node *dp = op->dev.of_node;
469 struct fb_info *info; 469 struct fb_info *info;
470 struct cg14_par *par; 470 struct cg14_par *par;
471 int is_8mb, linebytes, i, err; 471 int is_8mb, linebytes, i, err;
diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c
index b98f93f7f663..558d73a948a0 100644
--- a/drivers/video/cg3.c
+++ b/drivers/video/cg3.c
@@ -349,7 +349,7 @@ static int __devinit cg3_do_default_mode(struct cg3_par *par)
349static int __devinit cg3_probe(struct of_device *op, 349static int __devinit cg3_probe(struct of_device *op,
350 const struct of_device_id *match) 350 const struct of_device_id *match)
351{ 351{
352 struct device_node *dp = op->node; 352 struct device_node *dp = op->dev.of_node;
353 struct fb_info *info; 353 struct fb_info *info;
354 struct cg3_par *par; 354 struct cg3_par *par;
355 int linebytes, err; 355 int linebytes, err;
diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c
index 1105a591dcc1..6b93ef93cb12 100644
--- a/drivers/video/fb_defio.c
+++ b/drivers/video/fb_defio.c
@@ -66,7 +66,7 @@ static int fb_deferred_io_fault(struct vm_area_struct *vma,
66 return 0; 66 return 0;
67} 67}
68 68
69int fb_deferred_io_fsync(struct file *file, struct dentry *dentry, int datasync) 69int fb_deferred_io_fsync(struct file *file, int datasync)
70{ 70{
71 struct fb_info *info = file->private_data; 71 struct fb_info *info = file->private_data;
72 72
@@ -100,6 +100,16 @@ static int fb_deferred_io_mkwrite(struct vm_area_struct *vma,
100 /* protect against the workqueue changing the page list */ 100 /* protect against the workqueue changing the page list */
101 mutex_lock(&fbdefio->lock); 101 mutex_lock(&fbdefio->lock);
102 102
103 /*
104 * We want the page to remain locked from ->page_mkwrite until
105 * the PTE is marked dirty to avoid page_mkclean() being called
106 * before the PTE is updated, which would leave the page ignored
107 * by defio.
108 * Do this by locking the page here and informing the caller
109 * about it with VM_FAULT_LOCKED.
110 */
111 lock_page(page);
112
103 /* we loop through the pagelist before adding in order 113 /* we loop through the pagelist before adding in order
104 to keep the pagelist sorted */ 114 to keep the pagelist sorted */
105 list_for_each_entry(cur, &fbdefio->pagelist, lru) { 115 list_for_each_entry(cur, &fbdefio->pagelist, lru) {
@@ -121,7 +131,7 @@ page_already_added:
121 131
122 /* come back after delay to process the deferred IO */ 132 /* come back after delay to process the deferred IO */
123 schedule_delayed_work(&info->deferred_work, fbdefio->delay); 133 schedule_delayed_work(&info->deferred_work, fbdefio->delay);
124 return 0; 134 return VM_FAULT_LOCKED;
125} 135}
126 136
127static const struct vm_operations_struct fb_deferred_io_vm_ops = { 137static const struct vm_operations_struct fb_deferred_io_vm_ops = {
@@ -155,41 +165,25 @@ static void fb_deferred_io_work(struct work_struct *work)
155{ 165{
156 struct fb_info *info = container_of(work, struct fb_info, 166 struct fb_info *info = container_of(work, struct fb_info,
157 deferred_work.work); 167 deferred_work.work);
168 struct list_head *node, *next;
169 struct page *cur;
158 struct fb_deferred_io *fbdefio = info->fbdefio; 170 struct fb_deferred_io *fbdefio = info->fbdefio;
159 struct page *page, *tmp_page;
160 struct list_head *node, *tmp_node;
161 struct list_head non_dirty;
162
163 INIT_LIST_HEAD(&non_dirty);
164 171
165 /* here we mkclean the pages, then do all deferred IO */ 172 /* here we mkclean the pages, then do all deferred IO */
166 mutex_lock(&fbdefio->lock); 173 mutex_lock(&fbdefio->lock);
167 list_for_each_entry_safe(page, tmp_page, &fbdefio->pagelist, lru) { 174 list_for_each_entry(cur, &fbdefio->pagelist, lru) {
168 lock_page(page); 175 lock_page(cur);
169 /* 176 page_mkclean(cur);
170 * The workqueue callback can be triggered after a 177 unlock_page(cur);
171 * ->page_mkwrite() call but before the PTE has been marked
172 * dirty. In this case page_mkclean() won't "rearm" the page.
173 *
174 * To avoid this, remove those "non-dirty" pages from the
175 * pagelist before calling the driver's callback, then add
176 * them back to get processed on the next work iteration.
177 * At that time, their PTEs will hopefully be dirty for real.
178 */
179 if (!page_mkclean(page))
180 list_move_tail(&page->lru, &non_dirty);
181 unlock_page(page);
182 } 178 }
183 179
184 /* driver's callback with pagelist */ 180 /* driver's callback with pagelist */
185 fbdefio->deferred_io(info, &fbdefio->pagelist); 181 fbdefio->deferred_io(info, &fbdefio->pagelist);
186 182
187 /* clear the list... */ 183 /* clear the list */
188 list_for_each_safe(node, tmp_node, &fbdefio->pagelist) { 184 list_for_each_safe(node, next, &fbdefio->pagelist) {
189 list_del(node); 185 list_del(node);
190 } 186 }
191 /* ... and add back the "non-dirty" pages to the list */
192 list_splice_tail(&non_dirty, &fbdefio->pagelist);
193 mutex_unlock(&fbdefio->lock); 187 mutex_unlock(&fbdefio->lock);
194} 188}
195 189
@@ -218,7 +212,6 @@ EXPORT_SYMBOL_GPL(fb_deferred_io_open);
218void fb_deferred_io_cleanup(struct fb_info *info) 212void fb_deferred_io_cleanup(struct fb_info *info)
219{ 213{
220 struct fb_deferred_io *fbdefio = info->fbdefio; 214 struct fb_deferred_io *fbdefio = info->fbdefio;
221 struct list_head *node, *tmp_node;
222 struct page *page; 215 struct page *page;
223 int i; 216 int i;
224 217
@@ -226,13 +219,6 @@ void fb_deferred_io_cleanup(struct fb_info *info)
226 cancel_delayed_work(&info->deferred_work); 219 cancel_delayed_work(&info->deferred_work);
227 flush_scheduled_work(); 220 flush_scheduled_work();
228 221
229 /* the list may have still some non-dirty pages at this point */
230 mutex_lock(&fbdefio->lock);
231 list_for_each_safe(node, tmp_node, &fbdefio->pagelist) {
232 list_del(node);
233 }
234 mutex_unlock(&fbdefio->lock);
235
236 /* clear out the mapping that we setup */ 222 /* clear out the mapping that we setup */
237 for (i = 0 ; i < info->fix.smem_len; i += PAGE_SIZE) { 223 for (i = 0 ; i < info->fix.smem_len; i += PAGE_SIZE) {
238 page = fb_deferred_io_page(info, i); 224 page = fb_deferred_io_page(info, i);
diff --git a/drivers/video/leo.c b/drivers/video/leo.c
index 3d7895316eaf..9e8bf7d5e249 100644
--- a/drivers/video/leo.c
+++ b/drivers/video/leo.c
@@ -550,7 +550,7 @@ static void leo_unmap_regs(struct of_device *op, struct fb_info *info,
550static int __devinit leo_probe(struct of_device *op, 550static int __devinit leo_probe(struct of_device *op,
551 const struct of_device_id *match) 551 const struct of_device_id *match)
552{ 552{
553 struct device_node *dp = op->node; 553 struct device_node *dp = op->dev.of_node;
554 struct fb_info *info; 554 struct fb_info *info;
555 struct leo_par *par; 555 struct leo_par *par;
556 int linebytes, err; 556 int linebytes, err;
diff --git a/drivers/video/mb862xx/mb862xxfb.c b/drivers/video/mb862xx/mb862xxfb.c
index 0540de4f5cb4..4e2b8cc3d460 100644
--- a/drivers/video/mb862xx/mb862xxfb.c
+++ b/drivers/video/mb862xx/mb862xxfb.c
@@ -553,7 +553,7 @@ static int mb862xx_gdc_init(struct mb862xxfb_par *par)
553static int __devinit of_platform_mb862xx_probe(struct of_device *ofdev, 553static int __devinit of_platform_mb862xx_probe(struct of_device *ofdev,
554 const struct of_device_id *id) 554 const struct of_device_id *id)
555{ 555{
556 struct device_node *np = ofdev->node; 556 struct device_node *np = ofdev->dev.of_node;
557 struct device *dev = &ofdev->dev; 557 struct device *dev = &ofdev->dev;
558 struct mb862xxfb_par *par; 558 struct mb862xxfb_par *par;
559 struct fb_info *info; 559 struct fb_info *info;
diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c
index c85dd408a9b8..6552751e81aa 100644
--- a/drivers/video/p9100.c
+++ b/drivers/video/p9100.c
@@ -251,7 +251,7 @@ static void p9100_init_fix(struct fb_info *info, int linebytes, struct device_no
251 251
252static int __devinit p9100_probe(struct of_device *op, const struct of_device_id *match) 252static int __devinit p9100_probe(struct of_device *op, const struct of_device_id *match)
253{ 253{
254 struct device_node *dp = op->node; 254 struct device_node *dp = op->dev.of_node;
255 struct fb_info *info; 255 struct fb_info *info;
256 struct p9100_par *par; 256 struct p9100_par *par;
257 int linebytes, err; 257 int linebytes, err;
diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c
index d4471b4c0374..dce8c97b4333 100644
--- a/drivers/video/s3fb.c
+++ b/drivers/video/s3fb.c
@@ -71,7 +71,8 @@ static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64",
71 "S3 Trio64UV+", "S3 Trio64V2/DX", "S3 Trio64V2/GX", 71 "S3 Trio64UV+", "S3 Trio64V2/DX", "S3 Trio64V2/GX",
72 "S3 Plato/PX", "S3 Aurora64VP", "S3 Virge", 72 "S3 Plato/PX", "S3 Aurora64VP", "S3 Virge",
73 "S3 Virge/VX", "S3 Virge/DX", "S3 Virge/GX", 73 "S3 Virge/VX", "S3 Virge/DX", "S3 Virge/GX",
74 "S3 Virge/GX2", "S3 Virge/GX2P", "S3 Virge/GX2P"}; 74 "S3 Virge/GX2", "S3 Virge/GX2P", "S3 Virge/GX2P",
75 "S3 Trio3D/1X", "S3 Trio3D/2X", "S3 Trio3D/2X"};
75 76
76#define CHIP_UNKNOWN 0x00 77#define CHIP_UNKNOWN 0x00
77#define CHIP_732_TRIO32 0x01 78#define CHIP_732_TRIO32 0x01
@@ -89,10 +90,14 @@ static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64",
89#define CHIP_356_VIRGE_GX2 0x0D 90#define CHIP_356_VIRGE_GX2 0x0D
90#define CHIP_357_VIRGE_GX2P 0x0E 91#define CHIP_357_VIRGE_GX2P 0x0E
91#define CHIP_359_VIRGE_GX2P 0x0F 92#define CHIP_359_VIRGE_GX2P 0x0F
93#define CHIP_360_TRIO3D_1X 0x10
94#define CHIP_362_TRIO3D_2X 0x11
95#define CHIP_368_TRIO3D_2X 0x12
92 96
93#define CHIP_XXX_TRIO 0x80 97#define CHIP_XXX_TRIO 0x80
94#define CHIP_XXX_TRIO64V2_DXGX 0x81 98#define CHIP_XXX_TRIO64V2_DXGX 0x81
95#define CHIP_XXX_VIRGE_DXGX 0x82 99#define CHIP_XXX_VIRGE_DXGX 0x82
100#define CHIP_36X_TRIO3D_1X_2X 0x83
96 101
97#define CHIP_UNDECIDED_FLAG 0x80 102#define CHIP_UNDECIDED_FLAG 0x80
98#define CHIP_MASK 0xFF 103#define CHIP_MASK 0xFF
@@ -324,6 +329,7 @@ static void s3fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
324 329
325static void s3_set_pixclock(struct fb_info *info, u32 pixclock) 330static void s3_set_pixclock(struct fb_info *info, u32 pixclock)
326{ 331{
332 struct s3fb_info *par = info->par;
327 u16 m, n, r; 333 u16 m, n, r;
328 u8 regval; 334 u8 regval;
329 int rv; 335 int rv;
@@ -339,7 +345,13 @@ static void s3_set_pixclock(struct fb_info *info, u32 pixclock)
339 vga_w(NULL, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD); 345 vga_w(NULL, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD);
340 346
341 /* Set S3 clock registers */ 347 /* Set S3 clock registers */
342 vga_wseq(NULL, 0x12, ((n - 2) | (r << 5))); 348 if (par->chip == CHIP_360_TRIO3D_1X ||
349 par->chip == CHIP_362_TRIO3D_2X ||
350 par->chip == CHIP_368_TRIO3D_2X) {
351 vga_wseq(NULL, 0x12, (n - 2) | ((r & 3) << 6)); /* n and two bits of r */
352 vga_wseq(NULL, 0x29, r >> 2); /* remaining highest bit of r */
353 } else
354 vga_wseq(NULL, 0x12, (n - 2) | (r << 5));
343 vga_wseq(NULL, 0x13, m - 2); 355 vga_wseq(NULL, 0x13, m - 2);
344 356
345 udelay(1000); 357 udelay(1000);
@@ -456,7 +468,7 @@ static int s3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
456static int s3fb_set_par(struct fb_info *info) 468static int s3fb_set_par(struct fb_info *info)
457{ 469{
458 struct s3fb_info *par = info->par; 470 struct s3fb_info *par = info->par;
459 u32 value, mode, hmul, offset_value, screen_size, multiplex; 471 u32 value, mode, hmul, offset_value, screen_size, multiplex, dbytes;
460 u32 bpp = info->var.bits_per_pixel; 472 u32 bpp = info->var.bits_per_pixel;
461 473
462 if (bpp != 0) { 474 if (bpp != 0) {
@@ -518,7 +530,7 @@ static int s3fb_set_par(struct fb_info *info)
518 svga_wcrt_mask(0x33, 0x00, 0x08); /* no DDR ? */ 530 svga_wcrt_mask(0x33, 0x00, 0x08); /* no DDR ? */
519 svga_wcrt_mask(0x43, 0x00, 0x01); /* no DDR ? */ 531 svga_wcrt_mask(0x43, 0x00, 0x01); /* no DDR ? */
520 532
521 svga_wcrt_mask(0x5D, 0x00, 0x28); // Clear strange HSlen bits 533 svga_wcrt_mask(0x5D, 0x00, 0x28); /* Clear strange HSlen bits */
522 534
523/* svga_wcrt_mask(0x58, 0x03, 0x03); */ 535/* svga_wcrt_mask(0x58, 0x03, 0x03); */
524 536
@@ -530,10 +542,14 @@ static int s3fb_set_par(struct fb_info *info)
530 pr_debug("fb%d: offset register : %d\n", info->node, offset_value); 542 pr_debug("fb%d: offset register : %d\n", info->node, offset_value);
531 svga_wcrt_multi(s3_offset_regs, offset_value); 543 svga_wcrt_multi(s3_offset_regs, offset_value);
532 544
533 vga_wcrt(NULL, 0x54, 0x18); /* M parameter */ 545 if (par->chip != CHIP_360_TRIO3D_1X &&
534 vga_wcrt(NULL, 0x60, 0xff); /* N parameter */ 546 par->chip != CHIP_362_TRIO3D_2X &&
535 vga_wcrt(NULL, 0x61, 0xff); /* L parameter */ 547 par->chip != CHIP_368_TRIO3D_2X) {
536 vga_wcrt(NULL, 0x62, 0xff); /* L parameter */ 548 vga_wcrt(NULL, 0x54, 0x18); /* M parameter */
549 vga_wcrt(NULL, 0x60, 0xff); /* N parameter */
550 vga_wcrt(NULL, 0x61, 0xff); /* L parameter */
551 vga_wcrt(NULL, 0x62, 0xff); /* L parameter */
552 }
537 553
538 vga_wcrt(NULL, 0x3A, 0x35); 554 vga_wcrt(NULL, 0x3A, 0x35);
539 svga_wattr(0x33, 0x00); 555 svga_wattr(0x33, 0x00);
@@ -570,6 +586,16 @@ static int s3fb_set_par(struct fb_info *info)
570 vga_wcrt(NULL, 0x66, 0x90); 586 vga_wcrt(NULL, 0x66, 0x90);
571 } 587 }
572 588
589 if (par->chip == CHIP_360_TRIO3D_1X ||
590 par->chip == CHIP_362_TRIO3D_2X ||
591 par->chip == CHIP_368_TRIO3D_2X) {
592 dbytes = info->var.xres * ((bpp+7)/8);
593 vga_wcrt(NULL, 0x91, (dbytes + 7) / 8);
594 vga_wcrt(NULL, 0x90, (((dbytes + 7) / 8) >> 8) | 0x80);
595
596 vga_wcrt(NULL, 0x66, 0x81);
597 }
598
573 svga_wcrt_mask(0x31, 0x00, 0x40); 599 svga_wcrt_mask(0x31, 0x00, 0x40);
574 multiplex = 0; 600 multiplex = 0;
575 hmul = 1; 601 hmul = 1;
@@ -615,11 +641,13 @@ static int s3fb_set_par(struct fb_info *info)
615 break; 641 break;
616 case 3: 642 case 3:
617 pr_debug("fb%d: 8 bit pseudocolor\n", info->node); 643 pr_debug("fb%d: 8 bit pseudocolor\n", info->node);
618 if (info->var.pixclock > 20000) { 644 svga_wcrt_mask(0x50, 0x00, 0x30);
619 svga_wcrt_mask(0x50, 0x00, 0x30); 645 if (info->var.pixclock > 20000 ||
646 par->chip == CHIP_360_TRIO3D_1X ||
647 par->chip == CHIP_362_TRIO3D_2X ||
648 par->chip == CHIP_368_TRIO3D_2X)
620 svga_wcrt_mask(0x67, 0x00, 0xF0); 649 svga_wcrt_mask(0x67, 0x00, 0xF0);
621 } else { 650 else {
622 svga_wcrt_mask(0x50, 0x00, 0x30);
623 svga_wcrt_mask(0x67, 0x10, 0xF0); 651 svga_wcrt_mask(0x67, 0x10, 0xF0);
624 multiplex = 1; 652 multiplex = 1;
625 } 653 }
@@ -634,7 +662,10 @@ static int s3fb_set_par(struct fb_info *info)
634 } else { 662 } else {
635 svga_wcrt_mask(0x50, 0x10, 0x30); 663 svga_wcrt_mask(0x50, 0x10, 0x30);
636 svga_wcrt_mask(0x67, 0x30, 0xF0); 664 svga_wcrt_mask(0x67, 0x30, 0xF0);
637 hmul = 2; 665 if (par->chip != CHIP_360_TRIO3D_1X &&
666 par->chip != CHIP_362_TRIO3D_2X &&
667 par->chip != CHIP_368_TRIO3D_2X)
668 hmul = 2;
638 } 669 }
639 break; 670 break;
640 case 5: 671 case 5:
@@ -647,7 +678,10 @@ static int s3fb_set_par(struct fb_info *info)
647 } else { 678 } else {
648 svga_wcrt_mask(0x50, 0x10, 0x30); 679 svga_wcrt_mask(0x50, 0x10, 0x30);
649 svga_wcrt_mask(0x67, 0x50, 0xF0); 680 svga_wcrt_mask(0x67, 0x50, 0xF0);
650 hmul = 2; 681 if (par->chip != CHIP_360_TRIO3D_1X &&
682 par->chip != CHIP_362_TRIO3D_2X &&
683 par->chip != CHIP_368_TRIO3D_2X)
684 hmul = 2;
651 } 685 }
652 break; 686 break;
653 case 6: 687 case 6:
@@ -866,6 +900,17 @@ static int __devinit s3_identification(int chip)
866 return CHIP_385_VIRGE_GX; 900 return CHIP_385_VIRGE_GX;
867 } 901 }
868 902
903 if (chip == CHIP_36X_TRIO3D_1X_2X) {
904 switch (vga_rcrt(NULL, 0x2f)) {
905 case 0x00:
906 return CHIP_360_TRIO3D_1X;
907 case 0x01:
908 return CHIP_362_TRIO3D_2X;
909 case 0x02:
910 return CHIP_368_TRIO3D_2X;
911 }
912 }
913
869 return CHIP_UNKNOWN; 914 return CHIP_UNKNOWN;
870} 915}
871 916
@@ -930,17 +975,32 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i
930 vga_wcrt(NULL, 0x38, 0x48); 975 vga_wcrt(NULL, 0x38, 0x48);
931 vga_wcrt(NULL, 0x39, 0xA5); 976 vga_wcrt(NULL, 0x39, 0xA5);
932 977
933 /* Find how many physical memory there is on card */ 978 /* Identify chip type */
934 /* 0x36 register is accessible even if other registers are locked */
935 regval = vga_rcrt(NULL, 0x36);
936 info->screen_size = s3_memsizes[regval >> 5] << 10;
937 info->fix.smem_len = info->screen_size;
938
939 par->chip = id->driver_data & CHIP_MASK; 979 par->chip = id->driver_data & CHIP_MASK;
940 par->rev = vga_rcrt(NULL, 0x2f); 980 par->rev = vga_rcrt(NULL, 0x2f);
941 if (par->chip & CHIP_UNDECIDED_FLAG) 981 if (par->chip & CHIP_UNDECIDED_FLAG)
942 par->chip = s3_identification(par->chip); 982 par->chip = s3_identification(par->chip);
943 983
984 /* Find how many physical memory there is on card */
985 /* 0x36 register is accessible even if other registers are locked */
986 regval = vga_rcrt(NULL, 0x36);
987 if (par->chip == CHIP_360_TRIO3D_1X ||
988 par->chip == CHIP_362_TRIO3D_2X ||
989 par->chip == CHIP_368_TRIO3D_2X) {
990 switch ((regval & 0xE0) >> 5) {
991 case 0: /* 8MB -- only 4MB usable for display */
992 case 1: /* 4MB with 32-bit bus */
993 case 2: /* 4MB */
994 info->screen_size = 4 << 20;
995 break;
996 case 6: /* 2MB */
997 info->screen_size = 2 << 20;
998 break;
999 }
1000 } else
1001 info->screen_size = s3_memsizes[regval >> 5] << 10;
1002 info->fix.smem_len = info->screen_size;
1003
944 /* Find MCLK frequency */ 1004 /* Find MCLK frequency */
945 regval = vga_rseq(NULL, 0x10); 1005 regval = vga_rseq(NULL, 0x10);
946 par->mclk_freq = ((vga_rseq(NULL, 0x11) + 2) * 14318) / ((regval & 0x1F) + 2); 1006 par->mclk_freq = ((vga_rseq(NULL, 0x11) + 2) * 14318) / ((regval & 0x1F) + 2);
@@ -1131,6 +1191,7 @@ static struct pci_device_id s3_devices[] __devinitdata = {
1131 {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A10), .driver_data = CHIP_356_VIRGE_GX2}, 1191 {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A10), .driver_data = CHIP_356_VIRGE_GX2},
1132 {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A11), .driver_data = CHIP_357_VIRGE_GX2P}, 1192 {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A11), .driver_data = CHIP_357_VIRGE_GX2P},
1133 {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A12), .driver_data = CHIP_359_VIRGE_GX2P}, 1193 {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A12), .driver_data = CHIP_359_VIRGE_GX2P},
1194 {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A13), .driver_data = CHIP_36X_TRIO3D_1X_2X},
1134 1195
1135 {0, 0, 0, 0, 0, 0, 0} 1196 {0, 0, 0, 0, 0, 0, 0}
1136}; 1197};
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index e8c769944812..12c451a711e9 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -991,13 +991,13 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
991 priv->ch[j].lcdc = priv; 991 priv->ch[j].lcdc = priv;
992 memcpy(&priv->ch[j].cfg, &pdata->ch[i], sizeof(pdata->ch[i])); 992 memcpy(&priv->ch[j].cfg, &pdata->ch[i], sizeof(pdata->ch[i]));
993 993
994 error = sh_mobile_lcdc_check_interface(&priv->ch[i]); 994 error = sh_mobile_lcdc_check_interface(&priv->ch[j]);
995 if (error) { 995 if (error) {
996 dev_err(&pdev->dev, "unsupported interface type\n"); 996 dev_err(&pdev->dev, "unsupported interface type\n");
997 goto err1; 997 goto err1;
998 } 998 }
999 init_waitqueue_head(&priv->ch[i].frame_end_wait); 999 init_waitqueue_head(&priv->ch[j].frame_end_wait);
1000 init_completion(&priv->ch[i].vsync_completion); 1000 init_completion(&priv->ch[j].vsync_completion);
1001 priv->ch[j].pan_offset = 0; 1001 priv->ch[j].pan_offset = 0;
1002 1002
1003 switch (pdata->ch[i].chan) { 1003 switch (pdata->ch[i].chan) {
diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c
index ef7a7bd8b503..cc039b33d2d8 100644
--- a/drivers/video/tcx.c
+++ b/drivers/video/tcx.c
@@ -365,7 +365,7 @@ static void tcx_unmap_regs(struct of_device *op, struct fb_info *info,
365static int __devinit tcx_probe(struct of_device *op, 365static int __devinit tcx_probe(struct of_device *op,
366 const struct of_device_id *match) 366 const struct of_device_id *match)
367{ 367{
368 struct device_node *dp = op->node; 368 struct device_node *dp = op->dev.of_node;
369 struct fb_info *info; 369 struct fb_info *info;
370 struct tcx_par *par; 370 struct tcx_par *par;
371 int linebytes, i, err; 371 int linebytes, i, err;
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index 2bc40e682f95..1082541358f0 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/via/viafbdev.c
@@ -578,14 +578,9 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
578 break; 578 break;
579 579
580 case VIAFB_SET_GAMMA_LUT: 580 case VIAFB_SET_GAMMA_LUT:
581 viafb_gamma_table = kmalloc(256 * sizeof(u32), GFP_KERNEL); 581 viafb_gamma_table = memdup_user(argp, 256 * sizeof(u32));
582 if (!viafb_gamma_table) 582 if (IS_ERR(viafb_gamma_table))
583 return -ENOMEM; 583 return PTR_ERR(viafb_gamma_table);
584 if (copy_from_user(viafb_gamma_table, argp,
585 256 * sizeof(u32))) {
586 kfree(viafb_gamma_table);
587 return -EFAULT;
588 }
589 viafb_set_gamma_table(viafb_bpp, viafb_gamma_table); 584 viafb_set_gamma_table(viafb_bpp, viafb_gamma_table);
590 kfree(viafb_gamma_table); 585 kfree(viafb_gamma_table);
591 break; 586 break;
diff --git a/drivers/watchdog/gef_wdt.c b/drivers/watchdog/gef_wdt.c
index ca0f4c6cf5ab..1df284f9c2a1 100644
--- a/drivers/watchdog/gef_wdt.c
+++ b/drivers/watchdog/gef_wdt.c
@@ -273,7 +273,7 @@ static int __devinit gef_wdt_probe(struct of_device *dev,
273 bus_clk = freq; 273 bus_clk = freq;
274 274
275 /* Map devices registers into memory */ 275 /* Map devices registers into memory */
276 gef_wdt_regs = of_iomap(dev->node, 0); 276 gef_wdt_regs = of_iomap(dev->dev.of_node, 0);
277 if (gef_wdt_regs == NULL) 277 if (gef_wdt_regs == NULL)
278 return -ENOMEM; 278 return -ENOMEM;
279 279
diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c
index 6622335773bb..4cda64dd309c 100644
--- a/drivers/watchdog/mpc8xxx_wdt.c
+++ b/drivers/watchdog/mpc8xxx_wdt.c
@@ -189,7 +189,7 @@ static int __devinit mpc8xxx_wdt_probe(struct of_device *ofdev,
189 const struct of_device_id *match) 189 const struct of_device_id *match)
190{ 190{
191 int ret; 191 int ret;
192 struct device_node *np = ofdev->node; 192 struct device_node *np = ofdev->dev.of_node;
193 struct mpc8xxx_wdt_type *wdt_type = match->data; 193 struct mpc8xxx_wdt_type *wdt_type = match->data;
194 u32 freq = fsl_get_sys_freq(); 194 u32 freq = fsl_get_sys_freq();
195 bool enabled; 195 bool enabled;
diff --git a/drivers/watchdog/rdc321x_wdt.c b/drivers/watchdog/rdc321x_wdt.c
index 69c6adbd8205..428f8a1583e8 100644
--- a/drivers/watchdog/rdc321x_wdt.c
+++ b/drivers/watchdog/rdc321x_wdt.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * RDC321x watchdog driver 2 * RDC321x watchdog driver
3 * 3 *
4 * Copyright (C) 2007 Florian Fainelli <florian@openwrt.org> 4 * Copyright (C) 2007-2010 Florian Fainelli <florian@openwrt.org>
5 * 5 *
6 * This driver is highly inspired from the cpu5_wdt driver 6 * This driver is highly inspired from the cpu5_wdt driver
7 * 7 *
@@ -36,8 +36,7 @@
36#include <linux/watchdog.h> 36#include <linux/watchdog.h>
37#include <linux/io.h> 37#include <linux/io.h>
38#include <linux/uaccess.h> 38#include <linux/uaccess.h>
39 39#include <linux/mfd/rdc321x.h>
40#include <asm/rdc321x_defs.h>
41 40
42#define RDC_WDT_MASK 0x80000000 /* Mask */ 41#define RDC_WDT_MASK 0x80000000 /* Mask */
43#define RDC_WDT_EN 0x00800000 /* Enable bit */ 42#define RDC_WDT_EN 0x00800000 /* Enable bit */
@@ -63,6 +62,8 @@ static struct {
63 int default_ticks; 62 int default_ticks;
64 unsigned long inuse; 63 unsigned long inuse;
65 spinlock_t lock; 64 spinlock_t lock;
65 struct pci_dev *sb_pdev;
66 int base_reg;
66} rdc321x_wdt_device; 67} rdc321x_wdt_device;
67 68
68/* generic helper functions */ 69/* generic helper functions */
@@ -70,14 +71,18 @@ static struct {
70static void rdc321x_wdt_trigger(unsigned long unused) 71static void rdc321x_wdt_trigger(unsigned long unused)
71{ 72{
72 unsigned long flags; 73 unsigned long flags;
74 u32 val;
73 75
74 if (rdc321x_wdt_device.running) 76 if (rdc321x_wdt_device.running)
75 ticks--; 77 ticks--;
76 78
77 /* keep watchdog alive */ 79 /* keep watchdog alive */
78 spin_lock_irqsave(&rdc321x_wdt_device.lock, flags); 80 spin_lock_irqsave(&rdc321x_wdt_device.lock, flags);
79 outl(RDC_WDT_EN | inl(RDC3210_CFGREG_DATA), 81 pci_read_config_dword(rdc321x_wdt_device.sb_pdev,
80 RDC3210_CFGREG_DATA); 82 rdc321x_wdt_device.base_reg, &val);
83 val |= RDC_WDT_EN;
84 pci_write_config_dword(rdc321x_wdt_device.sb_pdev,
85 rdc321x_wdt_device.base_reg, val);
81 spin_unlock_irqrestore(&rdc321x_wdt_device.lock, flags); 86 spin_unlock_irqrestore(&rdc321x_wdt_device.lock, flags);
82 87
83 /* requeue?? */ 88 /* requeue?? */
@@ -105,10 +110,13 @@ static void rdc321x_wdt_start(void)
105 110
106 /* Clear the timer */ 111 /* Clear the timer */
107 spin_lock_irqsave(&rdc321x_wdt_device.lock, flags); 112 spin_lock_irqsave(&rdc321x_wdt_device.lock, flags);
108 outl(RDC_CLS_TMR, RDC3210_CFGREG_ADDR); 113 pci_write_config_dword(rdc321x_wdt_device.sb_pdev,
114 rdc321x_wdt_device.base_reg, RDC_CLS_TMR);
109 115
110 /* Enable watchdog and set the timeout to 81.92 us */ 116 /* Enable watchdog and set the timeout to 81.92 us */
111 outl(RDC_WDT_EN | RDC_WDT_CNT, RDC3210_CFGREG_DATA); 117 pci_write_config_dword(rdc321x_wdt_device.sb_pdev,
118 rdc321x_wdt_device.base_reg,
119 RDC_WDT_EN | RDC_WDT_CNT);
112 spin_unlock_irqrestore(&rdc321x_wdt_device.lock, flags); 120 spin_unlock_irqrestore(&rdc321x_wdt_device.lock, flags);
113 121
114 mod_timer(&rdc321x_wdt_device.timer, 122 mod_timer(&rdc321x_wdt_device.timer,
@@ -148,7 +156,7 @@ static long rdc321x_wdt_ioctl(struct file *file, unsigned int cmd,
148 unsigned long arg) 156 unsigned long arg)
149{ 157{
150 void __user *argp = (void __user *)arg; 158 void __user *argp = (void __user *)arg;
151 unsigned int value; 159 u32 value;
152 static const struct watchdog_info ident = { 160 static const struct watchdog_info ident = {
153 .options = WDIOF_CARDRESET, 161 .options = WDIOF_CARDRESET,
154 .identity = "RDC321x WDT", 162 .identity = "RDC321x WDT",
@@ -162,9 +170,10 @@ static long rdc321x_wdt_ioctl(struct file *file, unsigned int cmd,
162 case WDIOC_GETSTATUS: 170 case WDIOC_GETSTATUS:
163 /* Read the value from the DATA register */ 171 /* Read the value from the DATA register */
164 spin_lock_irqsave(&rdc321x_wdt_device.lock, flags); 172 spin_lock_irqsave(&rdc321x_wdt_device.lock, flags);
165 value = inl(RDC3210_CFGREG_DATA); 173 pci_read_config_dword(rdc321x_wdt_device.sb_pdev,
174 rdc321x_wdt_device.base_reg, &value);
166 spin_unlock_irqrestore(&rdc321x_wdt_device.lock, flags); 175 spin_unlock_irqrestore(&rdc321x_wdt_device.lock, flags);
167 if (copy_to_user(argp, &value, sizeof(int))) 176 if (copy_to_user(argp, &value, sizeof(u32)))
168 return -EFAULT; 177 return -EFAULT;
169 break; 178 break;
170 case WDIOC_GETSUPPORT: 179 case WDIOC_GETSUPPORT:
@@ -219,17 +228,35 @@ static struct miscdevice rdc321x_wdt_misc = {
219static int __devinit rdc321x_wdt_probe(struct platform_device *pdev) 228static int __devinit rdc321x_wdt_probe(struct platform_device *pdev)
220{ 229{
221 int err; 230 int err;
231 struct resource *r;
232 struct rdc321x_wdt_pdata *pdata;
233
234 pdata = pdev->dev.platform_data;
235 if (!pdata) {
236 dev_err(&pdev->dev, "no platform data supplied\n");
237 return -ENODEV;
238 }
239
240 r = platform_get_resource_byname(pdev, IORESOURCE_IO, "wdt-reg");
241 if (!r) {
242 dev_err(&pdev->dev, "failed to get wdt-reg resource\n");
243 return -ENODEV;
244 }
245
246 rdc321x_wdt_device.sb_pdev = pdata->sb_pdev;
247 rdc321x_wdt_device.base_reg = r->start;
222 248
223 err = misc_register(&rdc321x_wdt_misc); 249 err = misc_register(&rdc321x_wdt_misc);
224 if (err < 0) { 250 if (err < 0) {
225 printk(KERN_ERR PFX "watchdog misc_register failed\n"); 251 dev_err(&pdev->dev, "misc_register failed\n");
226 return err; 252 return err;
227 } 253 }
228 254
229 spin_lock_init(&rdc321x_wdt_device.lock); 255 spin_lock_init(&rdc321x_wdt_device.lock);
230 256
231 /* Reset the watchdog */ 257 /* Reset the watchdog */
232 outl(RDC_WDT_RST, RDC3210_CFGREG_DATA); 258 pci_write_config_dword(rdc321x_wdt_device.sb_pdev,
259 rdc321x_wdt_device.base_reg, RDC_WDT_RST);
233 260
234 init_completion(&rdc321x_wdt_device.stop); 261 init_completion(&rdc321x_wdt_device.stop);
235 rdc321x_wdt_device.queue = 0; 262 rdc321x_wdt_device.queue = 0;
@@ -240,7 +267,7 @@ static int __devinit rdc321x_wdt_probe(struct platform_device *pdev)
240 267
241 rdc321x_wdt_device.default_ticks = ticks; 268 rdc321x_wdt_device.default_ticks = ticks;
242 269
243 printk(KERN_INFO PFX "watchdog init success\n"); 270 dev_info(&pdev->dev, "watchdog init success\n");
244 271
245 return 0; 272 return 0;
246} 273}
diff --git a/drivers/watchdog/wm8350_wdt.c b/drivers/watchdog/wm8350_wdt.c
index 89dd7b035295..b68d928c8f90 100644
--- a/drivers/watchdog/wm8350_wdt.c
+++ b/drivers/watchdog/wm8350_wdt.c
@@ -284,7 +284,7 @@ static int __devinit wm8350_wdt_probe(struct platform_device *pdev)
284 struct wm8350 *wm8350 = platform_get_drvdata(pdev); 284 struct wm8350 *wm8350 = platform_get_drvdata(pdev);
285 285
286 if (!wm8350) { 286 if (!wm8350) {
287 dev_err(wm8350->dev, "No driver data supplied\n"); 287 pr_err("No driver data supplied\n");
288 return -ENODEV; 288 return -ENODEV;
289 } 289 }
290 290
diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c
index eab33f1dbdf7..7b547f53f65e 100644
--- a/drivers/xen/xenbus/xenbus_xs.c
+++ b/drivers/xen/xenbus/xenbus_xs.c
@@ -499,7 +499,7 @@ int xenbus_printf(struct xenbus_transaction t,
499#define PRINTF_BUFFER_SIZE 4096 499#define PRINTF_BUFFER_SIZE 4096
500 char *printf_buffer; 500 char *printf_buffer;
501 501
502 printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_KERNEL); 502 printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_NOIO | __GFP_HIGH);
503 if (printf_buffer == NULL) 503 if (printf_buffer == NULL)
504 return -ENOMEM; 504 return -ENOMEM;
505 505